diff --git a/common/array_stack.h b/common/array_stack.h index 4aee5ec8a88f..9021c8a4bdb5 100644 --- a/common/array_stack.h +++ b/common/array_stack.h @@ -84,6 +84,9 @@ class ArrayStack { // Returns the current number of values in all arrays. auto all_values_size() const -> size_t { return values_.size(); } + // Returns true if the stack has no arrays pushed. + auto empty() const -> bool { return array_offsets_.empty(); } + private: // For each pushed array, the start index in elements_. llvm::SmallVector array_offsets_; diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index e4d4a4b600b7..219ed62b1e59 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -82,10 +82,15 @@ auto Context::VerifyOnFinish() -> void { // various pieces of context go out of scope. At this point, nothing should // remain. // node_stack_ will still contain top-level entities. - scope_stack_.VerifyOnFinish(); inst_block_stack_.VerifyOnFinish(); pattern_block_stack_.VerifyOnFinish(); param_and_arg_refs_stack_.VerifyOnFinish(); + args_type_info_stack_.VerifyOnFinish(); + CARBON_CHECK(struct_type_fields_stack_.empty()); + // TODO: Add verification for decl_name_stack_ and + // decl_introducer_state_stack_. + scope_stack_.VerifyOnFinish(); + // TODO: Add verification for generic_region_stack_. } auto Context::GetOrAddInst(SemIR::LocIdAndInst loc_id_and_inst) @@ -847,10 +852,8 @@ class TypeCompleter { break; } case CARBON_KIND(SemIR::StructType inst): { - for (auto field_id : context_.inst_blocks().Get(inst.fields_id)) { - Push(context_.insts() - .GetAs(field_id) - .field_type_id); + for (auto field : context_.struct_type_fields().Get(inst.fields_id)) { + Push(field.type_id); } break; } @@ -981,33 +984,30 @@ class TypeCompleter { auto BuildValueReprForInst(SemIR::TypeId type_id, SemIR::StructType struct_type) const -> SemIR::ValueRepr { - // TODO: Share more code with tuples. - auto fields = context_.inst_blocks().Get(struct_type.fields_id); + auto fields = context_.struct_type_fields().Get(struct_type.fields_id); if (fields.empty()) { return MakeEmptyValueRepr(); } // Find the value representation for each field, and construct a struct // of value representations. - llvm::SmallVector value_rep_fields; + llvm::SmallVector value_rep_fields; value_rep_fields.reserve(fields.size()); bool same_as_object_rep = true; - for (auto field_id : fields) { - auto field = context_.insts().GetAs(field_id); - auto field_value_rep = GetNestedValueRepr(field.field_type_id); - if (field_value_rep.type_id != field.field_type_id) { + for (auto field : fields) { + auto field_value_rep = GetNestedValueRepr(field.type_id); + if (field_value_rep.type_id != field.type_id) { same_as_object_rep = false; - field.field_type_id = field_value_rep.type_id; - field_id = context_.constant_values().GetInstId( - TryEvalInst(context_, SemIR::InstId::Invalid, field)); + field.type_id = field_value_rep.type_id; } - value_rep_fields.push_back(field_id); + value_rep_fields.push_back(field); } - auto value_rep = same_as_object_rep - ? type_id - : context_.GetStructType( - context_.inst_blocks().Add(value_rep_fields)); + auto value_rep = + same_as_object_rep + ? type_id + : context_.GetStructType( + context_.struct_type_fields().AddCanonical(value_rep_fields)); return BuildStructOrTupleValueRepr(fields.size(), value_rep, same_as_object_rep); } @@ -1243,8 +1243,9 @@ static auto GetCompleteTypeImpl(Context& context, EachArgT... each_arg) return type_id; } -auto Context::GetStructType(SemIR::InstBlockId refs_id) -> SemIR::TypeId { - return GetTypeImpl(*this, refs_id); +auto Context::GetStructType(SemIR::StructTypeFieldsId fields_id) + -> SemIR::TypeId { + return GetTypeImpl(*this, fields_id); } auto Context::GetTupleType(llvm::ArrayRef type_ids) diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 07bd650ec952..917f48cd24c6 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -394,9 +394,8 @@ class Context { // Returns a pointer type whose pointee type is `pointee_type_id`. auto GetPointerType(SemIR::TypeId pointee_type_id) -> SemIR::TypeId; - // Returns a struct type with the given fields, which should be a block of - // `StructTypeField`s. - auto GetStructType(SemIR::InstBlockId refs_id) -> SemIR::TypeId; + // Returns a struct type with the given fields. + auto GetStructType(SemIR::StructTypeFieldsId fields_id) -> SemIR::TypeId; // Returns a tuple type with the given element types. auto GetTupleType(llvm::ArrayRef type_ids) -> SemIR::TypeId; @@ -467,6 +466,10 @@ class Context { return args_type_info_stack_; } + auto struct_type_fields_stack() -> ArrayStack& { + return struct_type_fields_stack_; + } + auto decl_name_stack() -> DeclNameStack& { return decl_name_stack_; } auto decl_introducer_state_stack() -> DeclIntroducerStateStack& { @@ -527,6 +530,9 @@ class Context { auto name_scopes() -> SemIR::NameScopeStore& { return sem_ir().name_scopes(); } + auto struct_type_fields() -> SemIR::StructTypeFieldsStore& { + return sem_ir().struct_type_fields(); + } auto types() -> SemIR::TypeStore& { return sem_ir().types(); } auto type_blocks() -> SemIR::BlockValueStore& { return sem_ir().type_blocks(); @@ -613,6 +619,10 @@ class Context { // arguments. InstBlockStack args_type_info_stack_; + // The stack of StructTypeFields for in-progress StructTypeLiterals and Class + // object representations. + ArrayStack struct_type_fields_stack_; + // The stack used for qualified declaration name construction. DeclNameStack decl_name_stack_; diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 64386c37b7e5..0772a39af09f 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -390,13 +390,10 @@ static auto ConvertStructToStructOrClass(Context& context, std::is_same_v; auto& sem_ir = context.sem_ir(); - auto src_elem_fields = sem_ir.inst_blocks().Get(src_type.fields_id); - auto dest_elem_fields = sem_ir.inst_blocks().Get(dest_type.fields_id); - bool dest_has_vptr = - !dest_elem_fields.empty() && - sem_ir.insts() - .GetAs(dest_elem_fields.front()) - .name_id == SemIR::NameId::Vptr; + auto src_elem_fields = sem_ir.struct_type_fields().Get(src_type.fields_id); + auto dest_elem_fields = sem_ir.struct_type_fields().Get(dest_type.fields_id); + bool dest_has_vptr = !dest_elem_fields.empty() && + dest_elem_fields.front().name_id == SemIR::NameId::Vptr; auto dest_elem_fields_size = dest_elem_fields.size() - dest_has_vptr; auto value = sem_ir.insts().Get(value_id); @@ -432,9 +429,8 @@ static auto ConvertStructToStructOrClass(Context& context, // Prepare to look up fields in the source by index. Map src_field_indexes; if (src_type.fields_id != dest_type.fields_id) { - for (auto [i, field_id] : llvm::enumerate(src_elem_fields)) { - auto result = src_field_indexes.Insert( - context.insts().GetAs(field_id).name_id, i); + for (auto [i, field] : llvm::enumerate(src_elem_fields)) { + auto result = src_field_indexes.Insert(field.name_id, i); CARBON_CHECK(result.is_inserted(), "Duplicate field in source structure"); } } @@ -460,9 +456,7 @@ static auto ConvertStructToStructOrClass(Context& context, : SemIR::CopyOnWriteInstBlock( sem_ir, SemIR::CopyOnWriteInstBlock::UninitializedBlock{ dest_elem_fields.size()}); - for (auto [i, dest_field_id] : llvm::enumerate(dest_elem_fields)) { - auto dest_field = - sem_ir.insts().GetAs(dest_field_id); + for (auto [i, dest_field] : llvm::enumerate(dest_elem_fields)) { if (dest_field.name_id == SemIR::NameId::Vptr) { // TODO: Initialize the vptr to point to a vtable. new_block.Set(i, SemIR::InstId::BuiltinError); @@ -494,16 +488,15 @@ static auto ConvertStructToStructOrClass(Context& context, return SemIR::InstId::BuiltinError; } } - auto src_field = sem_ir.insts().GetAs( - src_elem_fields[src_field_index]); + auto src_field = src_elem_fields[src_field_index]; // TODO: This call recurses back into conversion. Switch to an iterative // approach. auto init_id = ConvertAggregateElement( - context, value_loc_id, value_id, src_field.field_type_id, - literal_elems, inner_kind, target.init_id, dest_field.field_type_id, - target.init_block, src_field_index); + context, value_loc_id, value_id, src_field.type_id, literal_elems, + inner_kind, target.init_id, dest_field.type_id, target.init_block, + src_field_index); if (init_id == SemIR::InstId::BuiltinError) { return SemIR::InstId::BuiltinError; } diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 9fb9d902789d..7cfcf592ed06 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -310,6 +310,36 @@ static auto GetConstantValue(EvalContext& eval_context, return eval_context.inst_blocks().AddCanonical(const_insts); } +// Compute the constant value of a type block. This may be different from the +// input type block if we have known generic arguments. +static auto GetConstantValue(EvalContext& eval_context, + SemIR::StructTypeFieldsId fields_id, Phase* phase) + -> SemIR::StructTypeFieldsId { + if (!fields_id.is_valid()) { + return SemIR::StructTypeFieldsId::Invalid; + } + auto fields = eval_context.context().struct_type_fields().Get(fields_id); + llvm::SmallVector new_fields; + for (auto field : fields) { + auto new_type_id = GetConstantValue(eval_context, field.type_id, phase); + if (!new_type_id.is_valid()) { + return SemIR::StructTypeFieldsId::Invalid; + } + + // Once we leave the small buffer, we know the first few elements are all + // constant, so it's likely that the entire block is constant. Resize to the + // target size given that we're going to allocate memory now anyway. + if (new_fields.size() == new_fields.capacity()) { + new_fields.reserve(fields.size()); + } + + new_fields.push_back({.name_id = field.name_id, .type_id = new_type_id}); + } + // TODO: If the new block is identical to the original block, and we know the + // old ID was canonical, return the original ID. + return eval_context.context().struct_type_fields().AddCanonical(new_fields); +} + // Compute the constant value of a type block. This may be different from the // input type block if we have known generic arguments. static auto GetConstantValue(EvalContext& eval_context, @@ -1235,9 +1265,6 @@ static auto TryEvalInstInContext(EvalContext& eval_context, case SemIR::StructType::Kind: return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::StructType::fields_id); - case SemIR::StructTypeField::Kind: - return RebuildIfFieldsAreConstant(eval_context, inst, - &SemIR::StructTypeField::field_type_id); case SemIR::StructValue::Kind: return RebuildIfFieldsAreConstant(eval_context, inst, &SemIR::StructValue::type_id, diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index c1e9715b7d96..90885e1b026d 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -131,15 +131,12 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, binding_id, {.type_id = field_type_id, .name_id = name_id, - .index = SemIR::ElementIndex(context.args_type_info_stack() - .PeekCurrentBlockContents() - .size())}); + .index = SemIR::ElementIndex( + context.struct_type_fields_stack().PeekArray().size())}); // Add a corresponding field to the object representation of the class. - context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - binding_id, - {.name_id = name_id, .field_type_id = cast_type_id})); + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_id = cast_type_id}); context.node_stack().Push(node_id, field_id); break; } diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index fd68f2efd27a..f0ef56f0f9a5 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -295,7 +295,7 @@ auto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id) context.inst_block_stack().Push(); context.node_stack().Push(node_id, class_id); - context.args_type_info_stack().Push(); + context.struct_type_fields_stack().PushArray(); // TODO: Handle the case where there's control flow in the class body. For // example: @@ -533,11 +533,10 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { auto field_type_id = context.GetUnboundElementType(class_info.self_type_id, base_info.type_id); class_info.base_id = context.AddInst( - node_id, - {.type_id = field_type_id, - .base_type_id = base_info.type_id, - .index = SemIR::ElementIndex( - context.args_type_info_stack().PeekCurrentBlockContents().size())}); + node_id, {.type_id = field_type_id, + .base_type_id = base_info.type_id, + .index = SemIR::ElementIndex( + context.struct_type_fields_stack().PeekArray().size())}); if (base_info.type_id != SemIR::TypeId::Error) { auto base_class_info = context.classes().Get( @@ -548,10 +547,8 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { // Add a corresponding field to the object representation of the class. // TODO: Consider whether we want to use `partial T` here. // TODO: Should we diagnose if there are already any fields? - context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - node_id, {.name_id = SemIR::NameId::Base, - .field_type_id = base_info.type_id})); + context.struct_type_fields_stack().AppendToTop( + {.name_id = SemIR::NameId::Base, .type_id = base_info.type_id}); // Bind the name `base` in the class to the base field. context.decl_name_stack().AddNameOrDiagnoseDuplicate( @@ -576,7 +573,7 @@ auto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool { static auto CheckCompleteAdapterClassType(Context& context, Parse::NodeId node_id, SemIR::ClassId class_id, - SemIR::InstBlockId fields_id) + SemIR::StructTypeFieldsId fields_id) -> SemIR::InstId { const auto& class_info = context.classes().Get(class_id); if (class_info.base_id.is_valid()) { @@ -589,14 +586,17 @@ static auto CheckCompleteAdapterClassType(Context& context, return SemIR::InstId::BuiltinError; } - if (!context.inst_blocks().Get(fields_id).empty()) { - auto first_field_id = context.inst_blocks().Get(fields_id).front(); + if (auto fields = context.struct_type_fields().Get(fields_id); + !fields.empty()) { + auto [first_field_inst_id, _] = context.LookupNameInExactScope( + node_id, fields.front().name_id, class_info.scope_id, + context.name_scopes().Get(class_info.scope_id)); CARBON_DIAGNOSTIC(AdaptWithFields, Error, "adapter with fields"); CARBON_DIAGNOSTIC(AdaptWithFieldHere, Note, "first field declaration is here"); context.emitter() .Build(class_info.adapt_id, AdaptWithFields) - .Note(first_field_id, AdaptWithFieldHere) + .Note(first_field_inst_id, AdaptWithFieldHere) .Emit(); return SemIR::InstId::BuiltinError; } @@ -649,7 +649,9 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id, SemIR::ClassId class_id) -> SemIR::InstId { auto& class_info = context.classes().Get(class_id); if (class_info.adapt_id.is_valid()) { - auto fields_id = context.args_type_info_stack().Pop(); + auto fields_id = context.struct_type_fields().AddCanonical( + context.struct_type_fields_stack().PeekArray()); + context.struct_type_fields_stack().PopArray(); return CheckCompleteAdapterClassType(context, node_id, class_id, fields_id); } @@ -666,15 +668,15 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id, } if (defining_vtable_ptr) { - context.args_type_info_stack().AddFrontInstId( - context.AddInstInNoBlock( - Parse::NodeId::Invalid, - {.name_id = SemIR::NameId::Vptr, - .field_type_id = context.GetPointerType( - context.GetBuiltinType(SemIR::BuiltinInstKind::VtableType))})); + context.struct_type_fields_stack().PrependToTop( + {.name_id = SemIR::NameId::Vptr, + .type_id = context.GetPointerType( + context.GetBuiltinType(SemIR::BuiltinInstKind::VtableType))}); } - auto fields_id = context.args_type_info_stack().Pop(); + auto fields_id = context.struct_type_fields().AddCanonical( + context.struct_type_fields_stack().PeekArray()); + context.struct_type_fields_stack().PopArray(); return context.AddInst( node_id, diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 657068319de9..6579d06680cd 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -10,23 +10,23 @@ namespace Carbon::Check { -auto HandleParseNode(Context& context, Parse::StructTypeLiteralStartId node_id) - -> bool { - context.scope_stack().Push(); - context.node_stack().Push(node_id); - context.param_and_arg_refs_stack().Push(); - return true; -} - auto HandleParseNode(Context& context, Parse::StructLiteralStartId node_id) -> bool { context.scope_stack().Push(); context.node_stack().Push(node_id); - context.args_type_info_stack().Push(); + context.struct_type_fields_stack().PushArray(); context.param_and_arg_refs_stack().Push(); return true; } +auto HandleParseNode(Context& context, Parse::StructTypeLiteralStartId node_id) + -> bool { + context.scope_stack().Push(); + context.node_stack().Push(node_id); + context.struct_type_fields_stack().PushArray(); + return true; +} + auto HandleParseNode(Context& context, Parse::StructFieldDesignatorId /*node_id*/) -> bool { // This leaves the designated name on top because the `.` isn't interesting. @@ -40,52 +40,47 @@ auto HandleParseNode(Context& context, Parse::StructLiteralCommaId /*node_id*/) return true; } -auto HandleParseNode(Context& context, +auto HandleParseNode(Context& /*context*/, Parse::StructTypeLiteralCommaId /*node_id*/) -> bool { - context.param_and_arg_refs_stack().ApplyComma(); return true; } auto HandleParseNode(Context& context, Parse::StructLiteralFieldId node_id) -> bool { auto value_inst_id = context.node_stack().PopExpr(); - auto [name_node, name_id] = context.node_stack().PopNameWithNodeId(); + // Get the name while leaving it on the stack. + auto name_id = context.node_stack().Peek(); // Store the name for the type. - context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - name_node, - {.name_id = name_id, - .field_type_id = context.insts().Get(value_inst_id).type_id()})); + auto value_type_id = context.insts().Get(value_inst_id).type_id(); + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_id = value_type_id}); // Push the value back on the stack as an argument. context.node_stack().Push(node_id, value_inst_id); return true; } -auto HandleParseNode(Context& context, Parse::StructTypeLiteralFieldId node_id) - -> bool { +auto HandleParseNode(Context& context, + Parse::StructTypeLiteralFieldId /*node_id*/) -> bool { auto [type_node, type_id] = context.node_stack().PopExprWithNodeId(); SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id).type_id; + // Get the name while leaving it on the stack. + auto name_id = context.node_stack().Peek(); - auto [name_node, name_id] = context.node_stack().PopNameWithNodeId(); - - auto inst_id = context.AddInst( - name_node, {.name_id = name_id, .field_type_id = cast_type_id}); - context.node_stack().Push(node_id, inst_id); + context.struct_type_fields_stack().AppendToTop( + {.name_id = name_id, .type_id = cast_type_id}); return true; } -static auto DiagnoseDuplicateNames(Context& context, - SemIR::InstBlockId type_block_id, - bool is_struct_type_literal) -> bool { - auto& sem_ir = context.sem_ir(); - auto fields = sem_ir.inst_blocks().Get(type_block_id); - Map names; - auto& insts = sem_ir.insts(); - for (SemIR::InstId field_inst_id : fields) { - auto field_inst = insts.GetAs(field_inst_id); - auto result = names.Insert(field_inst.name_id, field_inst_id); +// Diagnoses and returns true if there's a duplicate name. +static auto DiagnoseDuplicateNames( + Context& context, llvm::ArrayRef field_name_nodes, + llvm::ArrayRef fields, bool is_struct_type_literal) + -> bool { + Map names; + for (auto [field_name_node, field] : llvm::zip(field_name_nodes, fields)) { + auto result = names.Insert(field.name_id, field_name_node); if (!result.is_inserted()) { CARBON_DIAGNOSTIC(StructNameDuplicate, Error, "duplicated field name `{1}` in " @@ -94,9 +89,9 @@ static auto DiagnoseDuplicateNames(Context& context, CARBON_DIAGNOSTIC(StructNamePrevious, Note, "field with the same name here"); context.emitter() - .Build(field_inst_id, StructNameDuplicate, is_struct_type_literal, - field_inst.name_id) - .Note(result.value(), StructNamePrevious) + .Build(result.value(), StructNameDuplicate, is_struct_type_literal, + field.name_id) + .Note(field_name_node, StructNamePrevious) .Emit(); return true; } @@ -104,47 +99,80 @@ static auto DiagnoseDuplicateNames(Context& context, return false; } +// Pops the names of each field from the stack. These will have been left while +// handling struct fields. +static auto PopFieldNameNodes(Context& context, size_t field_count) + -> llvm::SmallVector { + llvm::SmallVector nodes; + nodes.reserve(field_count); + while (true) { + auto [name_node, _] = + context.node_stack().PopWithNodeIdIf(); + if (name_node.is_valid()) { + nodes.push_back(name_node); + } else { + break; + } + } + CARBON_CHECK(nodes.size() == field_count, "Found {0} names, expected {1}", + nodes.size(), field_count); + return nodes; +} + auto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool { - auto refs_id = context.param_and_arg_refs_stack().EndAndPop( + if (!context.node_stack().PeekIs(Parse::NodeCategory::MemberName)) { + // Remove the last parameter from the node stack before collecting names. + context.param_and_arg_refs_stack().EndNoPop( + Parse::NodeKind::StructLiteralStart); + } + + auto fields = context.struct_type_fields_stack().PeekArray(); + llvm::SmallVector field_name_nodes = + PopFieldNameNodes(context, fields.size()); + + auto elements_id = context.param_and_arg_refs_stack().EndAndPop( Parse::NodeKind::StructLiteralStart); context.scope_stack().Pop(); context.node_stack() .PopAndDiscardSoloNodeId(); - auto type_block_id = context.args_type_info_stack().Pop(); - if (DiagnoseDuplicateNames(context, type_block_id, + + if (DiagnoseDuplicateNames(context, field_name_nodes, fields, /*is_struct_type_literal=*/false)) { context.node_stack().Push(node_id, SemIR::InstId::BuiltinError); - return true; + } else { + auto type_id = context.GetStructType( + context.struct_type_fields().AddCanonical(fields)); + + auto value_id = context.AddInst( + node_id, {.type_id = type_id, .elements_id = elements_id}); + context.node_stack().Push(node_id, value_id); } - auto type_id = context.GetStructType(type_block_id); - - auto value_id = context.AddInst( - node_id, {.type_id = type_id, .elements_id = refs_id}); - context.node_stack().Push(node_id, value_id); + context.struct_type_fields_stack().PopArray(); return true; } auto HandleParseNode(Context& context, Parse::StructTypeLiteralId node_id) -> bool { - auto refs_id = context.param_and_arg_refs_stack().EndAndPop( - Parse::NodeKind::StructTypeLiteralStart); + auto fields = context.struct_type_fields_stack().PeekArray(); + llvm::SmallVector field_name_nodes = + PopFieldNameNodes(context, fields.size()); context.scope_stack().Pop(); context.node_stack() .PopAndDiscardSoloNodeId(); - CARBON_CHECK(refs_id != SemIR::InstBlockId::Empty, - "{{}} is handled by StructLiteral."); - - if (DiagnoseDuplicateNames(context, refs_id, + if (DiagnoseDuplicateNames(context, field_name_nodes, fields, /*is_struct_type_literal=*/true)) { context.node_stack().Push(node_id, SemIR::InstId::BuiltinError); - return true; + } else { + auto fields_id = context.struct_type_fields().AddCanonical(fields); + context.AddInstAndPush( + node_id, {.type_id = SemIR::TypeId::TypeType, .fields_id = fields_id}); } - context.AddInstAndPush( - node_id, {.type_id = SemIR::TypeId::TypeType, .fields_id = refs_id}); + + context.struct_type_fields_stack().PopArray(); return true; } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index eb44bf103078..13830e9ce604 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -1233,7 +1233,7 @@ class ImportRefResolver { return TryResolveTypedInst(inst); } case CARBON_KIND(SemIR::StructType inst): { - return TryResolveTypedInst(inst, inst_id); + return TryResolveTypedInst(inst); } case CARBON_KIND(SemIR::StructValue inst): { return TryResolveTypedInst(inst); @@ -2147,38 +2147,31 @@ class ImportRefResolver { .specific_id = specific_id}); } - auto TryResolveTypedInst(SemIR::StructType inst, SemIR::InstId import_inst_id) - -> ResolveResult { + auto TryResolveTypedInst(SemIR::StructType inst) -> ResolveResult { CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); - auto orig_fields = import_ir_.inst_blocks().Get(inst.fields_id); + auto orig_fields = import_ir_.struct_type_fields().Get(inst.fields_id); llvm::SmallVector field_const_ids; field_const_ids.reserve(orig_fields.size()); - for (auto field_id : orig_fields) { - auto field = import_ir_.insts().GetAs(field_id); - field_const_ids.push_back(GetLocalConstantId(field.field_type_id)); + for (auto field : orig_fields) { + field_const_ids.push_back(GetLocalConstantId(field.type_id)); } if (HasNewWork()) { return Retry(); } // Prepare a vector of fields for GetStructType. - // TODO: Should we have field constants so that we can deduplicate fields - // without creating instructions here? - llvm::SmallVector fields; - fields.reserve(orig_fields.size()); - for (auto [field_id, field_const_id] : + llvm::SmallVector new_fields; + new_fields.reserve(orig_fields.size()); + for (auto [orig_field, field_const_id] : llvm::zip(orig_fields, field_const_ids)) { - auto field = import_ir_.insts().GetAs(field_id); - auto name_id = GetLocalNameId(field.name_id); + auto name_id = GetLocalNameId(orig_field.name_id); auto field_type_id = context_.GetTypeIdForTypeConstant(field_const_id); - fields.push_back(context_.AddInstInNoBlock( - AddImportIRInst(import_inst_id), - {.name_id = name_id, .field_type_id = field_type_id})); + new_fields.push_back({.name_id = name_id, .type_id = field_type_id}); } return ResolveAs( {.type_id = SemIR::TypeId::TypeType, - .fields_id = context_.inst_blocks().AddCanonical(fields)}); + .fields_id = context_.struct_type_fields().AddCanonical(new_fields)}); } auto TryResolveTypedInst(SemIR::StructValue inst) -> ResolveResult { diff --git a/toolchain/check/inst_block_stack.h b/toolchain/check/inst_block_stack.h index fab55c51e4e6..df718a099a92 100644 --- a/toolchain/check/inst_block_stack.h +++ b/toolchain/check/inst_block_stack.h @@ -58,13 +58,6 @@ class InstBlockStack { insts_stack_.AppendToTop(inst_id); } - // Adds the given instruction ID to the front of the block at the top of the - // stack. - auto AddFrontInstId(SemIR::InstId inst_id) -> void { - CARBON_CHECK(!empty(), "no current block"); - insts_stack_.PrependToTop(inst_id); - } - // Returns whether the current block is statically reachable. auto is_current_block_reachable() -> bool { return id_stack_.back() != SemIR::InstBlockId::Unreachable; diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 4f1879d71631..d0f1fba34dca 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -405,14 +405,13 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, if (auto struct_type = context.insts().TryGetAs( context.constant_values().GetInstId(base_type_const_id))) { // TODO: Do we need to optimize this with a lookup table for O(1)? - for (auto [i, ref_id] : - llvm::enumerate(context.inst_blocks().Get(struct_type->fields_id))) { - auto field = context.insts().GetAs(ref_id); + for (auto [i, field] : llvm::enumerate( + context.struct_type_fields().Get(struct_type->fields_id))) { if (name_id == field.name_id) { // TODO: Model this as producing a lookup result, and do instance // binding separately. Perhaps a struct type should be a name scope. return context.GetOrAddInst( - loc_id, {.type_id = field.field_type_id, + loc_id, {.type_id = field.type_id, .struct_id = base_id, .index = SemIR::ElementIndex(i)}); } diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 6a5642925d60..86aae588c8ea 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -424,7 +424,6 @@ class NodeStack { case Parse::NodeKind::ShortCircuitOperandAnd: case Parse::NodeKind::ShortCircuitOperandOr: case Parse::NodeKind::StructLiteralField: - case Parse::NodeKind::StructTypeLiteralField: case Parse::NodeKind::WhereOperand: return Id::KindFor(); case Parse::NodeKind::IfCondition: @@ -465,6 +464,7 @@ class NodeStack { case Parse::NodeKind::ReturnStatementStart: case Parse::NodeKind::ReturnVarModifier: case Parse::NodeKind::StructLiteralStart: + case Parse::NodeKind::StructTypeLiteralField: case Parse::NodeKind::StructTypeLiteralStart: case Parse::NodeKind::TupleLiteralStart: case Parse::NodeKind::TuplePatternStart: diff --git a/toolchain/check/subst.cpp b/toolchain/check/subst.cpp index ecb3555352bf..d33439c63ebd 100644 --- a/toolchain/check/subst.cpp +++ b/toolchain/check/subst.cpp @@ -77,6 +77,13 @@ static auto PushOperand(Context& context, Worklist& worklist, worklist.Push(inst_id); } break; + case SemIR::IdKind::For: { + for (auto field : + context.struct_type_fields().Get(SemIR::StructTypeFieldsId(arg))) { + worklist.Push(context.types().GetInstId(field.type_id)); + } + break; + } case SemIR::IdKind::For: for (auto type_id : context.type_blocks().Get(SemIR::TypeBlockId(arg))) { worklist.Push(context.types().GetInstId(type_id)); @@ -134,6 +141,18 @@ static auto PopOperand(Context& context, Worklist& worklist, SemIR::IdKind kind, } return new_inst_block.GetCanonical().index; } + case SemIR::IdKind::For: { + SemIR::StructTypeFieldsId old_fields_id(arg); + auto old_fields = context.struct_type_fields().Get(old_fields_id); + SemIR::CopyOnWriteStructTypeFieldsBlock new_fields(context.sem_ir(), + old_fields_id); + for (auto i : llvm::reverse(llvm::seq(old_fields.size()))) { + new_fields.Set( + i, {.name_id = old_fields[i].name_id, + .type_id = context.GetTypeIdForTypeInst(worklist.Pop())}); + } + return new_fields.GetCanonical().index; + } case SemIR::IdKind::For: { SemIR::TypeBlockId old_type_block_id(arg); auto size = context.type_blocks().Get(old_type_block_id).size(); diff --git a/toolchain/check/testdata/alias/no_prelude/import_order.carbon b/toolchain/check/testdata/alias/no_prelude/import_order.carbon index e35dacc3a446..d27b79c95d6b 100644 --- a/toolchain/check/testdata/alias/no_prelude/import_order.carbon +++ b/toolchain/check/testdata/alias/no_prelude/import_order.carbon @@ -85,10 +85,10 @@ var a_val: a = {.v = b_val.v}; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//a, inst+1, unloaded -// CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+14, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//a, inst+16, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: type = import_ref Main//a, inst+18, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.5: type = import_ref Main//a, inst+20, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+12, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//a, inst+14, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: type = import_ref Main//a, inst+16, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.5: type = import_ref Main//a, inst+18, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.6 = import_ref Main//a, inst+2, unloaded // CHECK:STDOUT: %import_ref.7: %.5 = import_ref Main//a, inst+7, loaded [template = %.1] // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/basics/builtin_insts.carbon b/toolchain/check/testdata/basics/builtin_insts.carbon index 31311bdef1da..fe8ca5f9c39d 100644 --- a/toolchain/check/testdata/basics/builtin_insts.carbon +++ b/toolchain/check/testdata/basics/builtin_insts.carbon @@ -23,6 +23,7 @@ // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon index c303f2064eb9..197d9f648c00 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_and_textual_ir.carbon @@ -40,6 +40,7 @@ fn B() { // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} @@ -115,6 +116,7 @@ fn B() { // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} diff --git a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon index e616c9bffae6..1205d7423a62 100644 --- a/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/multifile_raw_ir.carbon @@ -40,6 +40,7 @@ fn B() { // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} @@ -94,6 +95,7 @@ fn B() { // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} diff --git a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon index a05b64bc3be0..21cf677df4e2 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_and_textual_ir.carbon @@ -31,6 +31,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: classes: {} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} diff --git a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon index 8e73cc822a33..b08453e7564a 100644 --- a/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon +++ b/toolchain/check/testdata/basics/no_prelude/raw_ir.carbon @@ -34,6 +34,7 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: generic0: {decl: inst+24, bindings: block11} // CHECK:STDOUT: specifics: // CHECK:STDOUT: specific0: {generic: generic0, args: block13} +// CHECK:STDOUT: struct_type_fields: {} // CHECK:STDOUT: types: // CHECK:STDOUT: typeTypeType: {kind: copy, type: typeTypeType} // CHECK:STDOUT: typeError: {kind: copy, type: typeError} diff --git a/toolchain/check/testdata/class/generic/import.carbon b/toolchain/check/testdata/class/generic/import.carbon index 32e71a761bd8..488daf48cbf1 100644 --- a/toolchain/check/testdata/class/generic/import.carbon +++ b/toolchain/check/testdata/class/generic/import.carbon @@ -275,7 +275,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref Main//foo, inst+9, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+21, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.2 = import_ref Main//foo, inst+71, loaded [template = constants.%F.2] +// CHECK:STDOUT: %import_ref.3: %F.type.2 = import_ref Main//foo, inst+69, loaded [template = constants.%F.2] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -283,7 +283,7 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.4 = import_ref Main//foo, inst+26, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+38, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+48, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+46, unloaded // CHECK:STDOUT: %import_ref.7: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -448,7 +448,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+9, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+21, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.3 = import_ref Main//foo, inst+71, loaded [template = constants.%F.3] +// CHECK:STDOUT: %import_ref.3: %F.type.3 = import_ref Main//foo, inst+69, loaded [template = constants.%F.3] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.4 // CHECK:STDOUT: import Core//prelude @@ -457,7 +457,7 @@ class Class(U:! type) { // CHECK:STDOUT: %import_ref.4: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+26, unloaded // CHECK:STDOUT: %import_ref.6: @CompleteClass.%.1 (%.4) = import_ref Main//foo, inst+38, loaded [template = %.1] -// CHECK:STDOUT: %import_ref.7: @CompleteClass.%F.type (%F.type.1) = import_ref Main//foo, inst+48, loaded [symbolic = @CompleteClass.%F (constants.%F.1)] +// CHECK:STDOUT: %import_ref.7: @CompleteClass.%F.type (%F.type.1) = import_ref Main//foo, inst+46, loaded [symbolic = @CompleteClass.%F (constants.%F.1)] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -649,7 +649,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//foo, inst+9, unloaded // CHECK:STDOUT: %import_ref.2: %CompleteClass.type = import_ref Main//foo, inst+21, loaded [template = constants.%CompleteClass.1] -// CHECK:STDOUT: %import_ref.3: %F.type.3 = import_ref Main//foo, inst+71, loaded [template = constants.%F.3] +// CHECK:STDOUT: %import_ref.3: %F.type.3 = import_ref Main//foo, inst+69, loaded [template = constants.%F.3] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: .ImplicitAs = %import_ref.8 @@ -658,7 +658,7 @@ class Class(U:! type) { // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.4 = import_ref Main//foo, inst+26, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//foo, inst+38, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+48, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//foo, inst+46, unloaded // CHECK:STDOUT: %import_ref.7: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] // CHECK:STDOUT: %import_ref.8: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+49, loaded [template = constants.%ImplicitAs] // CHECK:STDOUT: %import_ref.9 = import_ref Core//prelude/operators/as, inst+55, unloaded @@ -849,7 +849,7 @@ class Class(U:! type) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %Class.type = import_ref Main//foo, inst+9, loaded [template = constants.%Class.1] // CHECK:STDOUT: %import_ref.2 = import_ref Main//foo, inst+21, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//foo, inst+71, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//foo, inst+69, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... diff --git a/toolchain/check/testdata/class/import.carbon b/toolchain/check/testdata/class/import.carbon index a81fbf68f09e..aa31749ffdc6 100644 --- a/toolchain/check/testdata/class/import.carbon +++ b/toolchain/check/testdata/class/import.carbon @@ -184,8 +184,8 @@ fn Run() { // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//a, inst+3, loaded [template = constants.%Empty] // CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+8, loaded [template = constants.%Field] -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//a, inst+28, loaded [template = constants.%ForwardDeclared.1] -// CHECK:STDOUT: %import_ref.4: type = import_ref Main//a, inst+51, loaded [template = constants.%Incomplete] +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//a, inst+26, loaded [template = constants.%ForwardDeclared.1] +// CHECK:STDOUT: %import_ref.4: type = import_ref Main//a, inst+49, loaded [template = constants.%Incomplete] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... @@ -193,12 +193,12 @@ fn Run() { // CHECK:STDOUT: %import_ref.5 = import_ref Main//a, inst+4, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref Main//a, inst+9, unloaded // CHECK:STDOUT: %import_ref.7: %.9 = import_ref Main//a, inst+22, loaded [template = %.1] -// CHECK:STDOUT: %import_ref.8 = import_ref Main//a, inst+29, unloaded -// CHECK:STDOUT: %import_ref.9: %F.type = import_ref Main//a, inst+36, loaded [template = constants.%F] -// CHECK:STDOUT: %import_ref.10: %G.type = import_ref Main//a, inst+47, loaded [template = constants.%G] -// CHECK:STDOUT: %import_ref.11 = import_ref Main//a, inst+29, unloaded -// CHECK:STDOUT: %import_ref.12 = import_ref Main//a, inst+36, unloaded -// CHECK:STDOUT: %import_ref.13 = import_ref Main//a, inst+47, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref Main//a, inst+27, unloaded +// CHECK:STDOUT: %import_ref.9: %F.type = import_ref Main//a, inst+34, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.10: %G.type = import_ref Main//a, inst+45, loaded [template = constants.%G] +// CHECK:STDOUT: %import_ref.11 = import_ref Main//a, inst+27, unloaded +// CHECK:STDOUT: %import_ref.12 = import_ref Main//a, inst+34, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Main//a, inst+45, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -299,5 +299,5 @@ fn Run() { // CHECK:STDOUT: // CHECK:STDOUT: fn @F[%self.param_patt: %ForwardDeclared.1](); // CHECK:STDOUT: -// CHECK:STDOUT: fn @G[addr .inst+94: %.11](); +// CHECK:STDOUT: fn @G[addr .inst+91: %.11](); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/import_base.carbon b/toolchain/check/testdata/class/import_base.carbon index d2fe55cbdf32..b918a44e2c12 100644 --- a/toolchain/check/testdata/class/import_base.carbon +++ b/toolchain/check/testdata/class/import_base.carbon @@ -158,7 +158,7 @@ fn Run() { // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//a, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+45, loaded [template = constants.%Child] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+41, loaded [template = constants.%Child] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... @@ -167,9 +167,9 @@ fn Run() { // CHECK:STDOUT: %import_ref.4: %F.type = import_ref Main//a, inst+10, loaded [template = constants.%F] // CHECK:STDOUT: %import_ref.5 = import_ref Main//a, inst+19, unloaded // CHECK:STDOUT: %import_ref.6: %.13 = import_ref Main//a, inst+33, loaded [template = %.1] -// CHECK:STDOUT: %import_ref.7 = import_ref Main//a, inst+39, unloaded -// CHECK:STDOUT: %import_ref.8 = import_ref Main//a, inst+46, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//a, inst+50, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//a, inst+37, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref Main//a, inst+42, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref Main//a, inst+46, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/class/import_struct_cyle.carbon b/toolchain/check/testdata/class/import_struct_cyle.carbon index da470ef18209..fe2d248b9acf 100644 --- a/toolchain/check/testdata/class/import_struct_cyle.carbon +++ b/toolchain/check/testdata/class/import_struct_cyle.carbon @@ -94,13 +94,13 @@ fn Run() { // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//a, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2: ref %.3 = import_ref Main//a, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: ref %.3 = import_ref Main//a, inst+11, loaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.3 = import_ref Main//a, inst+4, unloaded -// CHECK:STDOUT: %import_ref.4: %.7 = import_ref Main//a, inst+20, loaded [template = %.1] +// CHECK:STDOUT: %import_ref.4: %.7 = import_ref Main//a, inst+17, loaded [template = %.1] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/function/declaration/import.carbon b/toolchain/check/testdata/function/declaration/import.carbon index aefad2d73674..560059ad57b7 100644 --- a/toolchain/check/testdata/function/declaration/import.carbon +++ b/toolchain/check/testdata/function/declaration/import.carbon @@ -474,13 +474,13 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//api, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//api, inst+28, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+53, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+56, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+51, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+54, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+60, loaded [template = constants.%E] +// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+58, loaded [template = constants.%E] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -594,13 +594,13 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//api, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//api, inst+28, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+53, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+56, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+51, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+54, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = file.%E.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+60, loaded [template = constants.%E] +// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+58, loaded [template = constants.%E] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -744,13 +744,13 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//extern_api, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//extern_api, inst+28, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//extern_api, inst+53, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//extern_api, inst+56, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//extern_api, inst+51, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//extern_api, inst+54, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = file.%E.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//extern_api, inst+60, loaded [template = constants.%E] +// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//extern_api, inst+58, loaded [template = constants.%E] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.7 // CHECK:STDOUT: import Core//prelude @@ -893,18 +893,18 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//api, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//api, inst+28, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+53, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+56, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//api, inst+51, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//api, inst+54, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+60, loaded [template = constants.%E] +// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//api, inst+58, loaded [template = constants.%E] // CHECK:STDOUT: %import_ref.7 = import_ref Main//extern_api, inst+3, unloaded // CHECK:STDOUT: %import_ref.8 = import_ref Main//extern_api, inst+28, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//extern_api, inst+53, unloaded -// CHECK:STDOUT: %import_ref.10 = import_ref Main//extern_api, inst+56, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//extern_api, inst+60, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref Main//extern_api, inst+51, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//extern_api, inst+54, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//extern_api, inst+58, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.12 // CHECK:STDOUT: import Core//prelude @@ -1017,18 +1017,18 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//extern_api, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//extern_api, inst+28, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//extern_api, inst+53, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//extern_api, inst+56, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//extern_api, inst+51, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//extern_api, inst+54, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//extern_api, inst+60, loaded [template = constants.%E] +// CHECK:STDOUT: %import_ref.6: %E.type = import_ref Main//extern_api, inst+58, loaded [template = constants.%E] // CHECK:STDOUT: %import_ref.7 = import_ref Main//api, inst+3, unloaded // CHECK:STDOUT: %import_ref.8 = import_ref Main//api, inst+28, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//api, inst+53, unloaded -// CHECK:STDOUT: %import_ref.10 = import_ref Main//api, inst+56, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//api, inst+60, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref Main//api, inst+51, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//api, inst+54, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//api, inst+58, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.12 // CHECK:STDOUT: import Core//prelude @@ -1121,13 +1121,13 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//api, inst+3, unloaded // CHECK:STDOUT: %import_ref.2 = import_ref Main//api, inst+28, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//api, inst+53, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//api, inst+56, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//api, inst+51, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//api, inst+54, unloaded +// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//api, inst+60, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//api, inst+58, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... @@ -1152,13 +1152,13 @@ import library "extern_api"; // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_api, inst+3, unloaded // CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_api, inst+28, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//extern_api, inst+53, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//extern_api, inst+56, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+59, loaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//extern_api, inst+51, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//extern_api, inst+54, unloaded +// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+57, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//extern_api, inst+60, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//extern_api, inst+58, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... diff --git a/toolchain/check/testdata/function/definition/import.carbon b/toolchain/check/testdata/function/definition/import.carbon index 529dc9b60982..2b9935231612 100644 --- a/toolchain/check/testdata/function/definition/import.carbon +++ b/toolchain/check/testdata/function/definition/import.carbon @@ -261,8 +261,8 @@ fn D() {} // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//fns, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//fns, inst+29, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//fns, inst+56, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//fns, inst+68, unloaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Main//fns, inst+54, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//fns, inst+65, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.5 // CHECK:STDOUT: import Core//prelude @@ -343,8 +343,8 @@ fn D() {} // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//fns, inst+3, loaded [template = constants.%A] // CHECK:STDOUT: %import_ref.2: %B.type = import_ref Main//fns, inst+29, loaded [template = constants.%B] -// CHECK:STDOUT: %import_ref.3 = import_ref Main//fns, inst+56, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//fns, inst+68, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//fns, inst+54, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//fns, inst+65, unloaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.5 // CHECK:STDOUT: import Core//prelude @@ -430,8 +430,8 @@ fn D() {} // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//fns, inst+3, unloaded // CHECK:STDOUT: %import_ref.2 = import_ref Main//fns, inst+29, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//fns, inst+56, unloaded -// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//fns, inst+68, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//fns, inst+54, unloaded +// CHECK:STDOUT: %import_ref.4: %D.type = import_ref Main//fns, inst+65, loaded [template = constants.%D] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... diff --git a/toolchain/check/testdata/interface/no_prelude/import.carbon b/toolchain/check/testdata/interface/no_prelude/import.carbon index ae2866b6e36b..75e78c9f6a2b 100644 --- a/toolchain/check/testdata/interface/no_prelude/import.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import.carbon @@ -177,7 +177,7 @@ var f: ForwardDeclared* = &f_ref.f; // CHECK:STDOUT: %import_ref.1: type = import_ref Main//a, inst+1, loaded [template = constants.%Empty.type] // CHECK:STDOUT: %import_ref.2: type = import_ref Main//a, inst+5, loaded [template = constants.%Basic.type] // CHECK:STDOUT: %import_ref.3: type = import_ref Main//a, inst+20, loaded [template = constants.%ForwardDeclared.type] -// CHECK:STDOUT: %import_ref.4: ref %.11 = import_ref Main//a, inst+42, loaded +// CHECK:STDOUT: %import_ref.4: ref %.11 = import_ref Main//a, inst+39, loaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//a, inst+3, unloaded // CHECK:STDOUT: %import_ref.6 = import_ref Main//a, inst+7, unloaded // CHECK:STDOUT: %import_ref.7: %.2 = import_ref Main//a, inst+11, loaded [template = constants.%.3] diff --git a/toolchain/check/testdata/packages/fail_import_type_error.carbon b/toolchain/check/testdata/packages/fail_import_type_error.carbon index f20fd8ae818e..3281fc5aa63c 100644 --- a/toolchain/check/testdata/packages/fail_import_type_error.carbon +++ b/toolchain/check/testdata/packages/fail_import_type_error.carbon @@ -88,9 +88,9 @@ var d: i32 = d_ref; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: ref = import_ref Implicit//default, inst+5, loaded -// CHECK:STDOUT: %import_ref.2: ref = import_ref Implicit//default, inst+10, loaded -// CHECK:STDOUT: %import_ref.3: ref = import_ref Implicit//default, inst+14, loaded -// CHECK:STDOUT: %import_ref.4: ref = import_ref Implicit//default, inst+18, loaded +// CHECK:STDOUT: %import_ref.2: ref = import_ref Implicit//default, inst+9, loaded +// CHECK:STDOUT: %import_ref.3: ref = import_ref Implicit//default, inst+13, loaded +// CHECK:STDOUT: %import_ref.4: ref = import_ref Implicit//default, inst+17, loaded // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.5 // CHECK:STDOUT: import Core//prelude diff --git a/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon index c5407fe2b18a..eb6dc751ede3 100644 --- a/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon +++ b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon @@ -346,9 +346,9 @@ alias C = Other.C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+9, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -546,9 +546,9 @@ alias C = Other.C; // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: import Other//export_name // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+9, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -600,9 +600,9 @@ alias C = Other.C; // CHECK:STDOUT: import Other//export_name // CHECK:STDOUT: import Other//export_name_copy // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+9, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -653,9 +653,9 @@ alias C = Other.C; // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: import Other//export_name_indirect // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name_indirect, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name_indirect, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name_indirect, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name_indirect, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name_indirect, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name_indirect, inst+9, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -712,9 +712,9 @@ alias C = Other.C; // CHECK:STDOUT: import Other//export_name_indirect // CHECK:STDOUT: import Other//base // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+9, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -828,9 +828,9 @@ alias C = Other.C; // CHECK:STDOUT: import Other//export_name // CHECK:STDOUT: import Other//conflict // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+12, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+10, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+11, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Other//export_name, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Other//export_name, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Other//export_name, inst+9, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Other//conflict, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/no_prelude/export_import.carbon b/toolchain/check/testdata/packages/no_prelude/export_import.carbon index 70de99dec0d4..0f10901030de 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_import.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_import.carbon @@ -771,7 +771,7 @@ var indirect_c: C = {.x = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//use_non_export_then_base, inst+15, unloaded +// CHECK:STDOUT: %import_ref.1 = import_ref Main//use_non_export_then_base, inst+13, unloaded // CHECK:STDOUT: %import_ref.2: type = import_ref Main//base, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+7, unloaded diff --git a/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon b/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon index 0383ef14e90c..77eaab8c104c 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon @@ -162,7 +162,7 @@ var d: D = {.y = ()}; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//base, inst+1, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+13, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+11, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -184,7 +184,7 @@ var d: D = {.y = ()}; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+13, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+11, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+7, unloaded // CHECK:STDOUT: } @@ -215,7 +215,7 @@ var d: D = {.y = ()}; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+13, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//base, inst+11, unloaded // CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+7, unloaded // CHECK:STDOUT: } @@ -238,7 +238,7 @@ var d: D = {.y = ()}; // CHECK:STDOUT: --- export_name_then_import.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref = import_ref Main//export_name, inst+13, unloaded +// CHECK:STDOUT: %import_ref = import_ref Main//export_name, inst+11, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -261,9 +261,9 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+13, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+11, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+12, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+11, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+9, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+10, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -309,9 +309,9 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_name, inst+13, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_name, inst+11, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_name, inst+12, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_name, inst+11, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_name, inst+9, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_name, inst+10, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -357,9 +357,9 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+13, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+11, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+12, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+11, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+9, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+10, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -400,7 +400,7 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref = import_ref Main//export_import_then_name, inst+13, unloaded +// CHECK:STDOUT: %import_ref = import_ref Main//export_import_then_name, inst+11, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -435,9 +435,9 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+13, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+11, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+12, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+11, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//export_import_then_name, inst+9, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+10, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -488,12 +488,12 @@ var d: D = {.y = ()}; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+13, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: type = import_ref Main//base, inst+13, loaded [template = constants.%D] -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+11, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_import_then_name, inst+12, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+18, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_import_then_name, inst+11, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//base, inst+11, loaded [template = constants.%D] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export_import_then_name, inst+9, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_import_then_name, inst+10, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+16, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/packages/no_prelude/export_name.carbon b/toolchain/check/testdata/packages/no_prelude/export_name.carbon index 698f16a2bd26..f4c3e765c8c4 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_name.carbon @@ -262,15 +262,15 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = file.%NSC // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//base, inst+14, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//base, inst+12, loaded [template = constants.%NSC] // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+7, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+15, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//base, inst+19, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+13, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//base, inst+17, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -298,12 +298,12 @@ private export C; // CHECK:STDOUT: --- not_reexporting.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//export, inst+15, unloaded +// CHECK:STDOUT: %import_ref.1 = import_ref Main//export, inst+13, unloaded // CHECK:STDOUT: %import_ref.2: = import_ref Main//export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3 = import_ref Main//export, inst+24, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//export, inst+20, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -327,16 +327,16 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+15, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref Main//export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = file.%NSC // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+24, loaded [template = constants.%NSC] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+22, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+23, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+20, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+18, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+19, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -385,16 +385,16 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+15, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref Main//export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+24, loaded [template = constants.%NSC] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+22, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+23, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+20, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+18, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+19, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -465,16 +465,16 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_export, inst+15, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_export, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref Main//export_export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export_export, inst+24, loaded [template = constants.%NSC] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//export_export, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//export_export, inst+22, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//export_export, inst+23, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export_export, inst+20, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//export_export, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//export_export, inst+18, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//export_export, inst+19, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -546,16 +546,16 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_export, inst+15, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export_export, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref Main//export_export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export_export, inst+24, loaded [template = constants.%NSC] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//export_export, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//export_export, inst+22, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//export_export, inst+23, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export_export, inst+20, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export_export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//export_export, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//export_export, inst+18, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//export_export, inst+19, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -612,11 +612,11 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1 = import_ref Main//base, inst+1, unloaded -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+14, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+12, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -660,11 +660,11 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+14, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+12, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+7, unloaded // CHECK:STDOUT: } @@ -702,15 +702,15 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//base, inst+14, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//base, inst+12, loaded [template = constants.%NSC] // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+7, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+15, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//base, inst+19, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//base, inst+13, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//base, inst+17, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -781,16 +781,16 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+15, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//export, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref Main//export, inst+4, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+24, loaded [template = constants.%NSC] -// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+14, unloaded -// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+22, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+23, unloaded +// CHECK:STDOUT: %import_ref.3: type = import_ref Main//export, inst+20, loaded [template = constants.%NSC] +// CHECK:STDOUT: %import_ref.4 = import_ref Main//export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//export, inst+12, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//export, inst+18, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref Main//export, inst+19, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -868,11 +868,11 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+14, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+12, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+7, unloaded // CHECK:STDOUT: } @@ -905,9 +905,9 @@ private export C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//repeat_export, inst+15, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//repeat_export, inst+13, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//repeat_export, inst+14, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//repeat_export, inst+13, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//repeat_export, inst+11, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//repeat_export, inst+12, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -951,11 +951,11 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %import_ref.1: type = import_ref Main//base, inst+1, loaded [template = constants.%C] -// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+13, loaded +// CHECK:STDOUT: %import_ref.2: = import_ref Main//base, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { // CHECK:STDOUT: .NSC = %import_ref.3 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+14, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//base, inst+12, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref Main//base, inst+2, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref Main//base, inst+7, unloaded // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/return/no_prelude/import_convert_function.carbon b/toolchain/check/testdata/return/no_prelude/import_convert_function.carbon index deb587a029e5..0cd6f599dcb4 100644 --- a/toolchain/check/testdata/return/no_prelude/import_convert_function.carbon +++ b/toolchain/check/testdata/return/no_prelude/import_convert_function.carbon @@ -917,7 +917,7 @@ fn F0(n: i32) -> P.D { // CHECK:STDOUT: %import_ref.2: type = import_ref P//library, inst+29, loaded [template = constants.%D] // CHECK:STDOUT: %import_ref.3 = import_ref P//library, inst+30, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref P//library, inst+35, unloaded -// CHECK:STDOUT: %import_ref.5 = import_ref P//library, inst+41, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref P//library, inst+39, unloaded // CHECK:STDOUT: %import_ref.6: %C.type = import_ref P//library, inst+20, loaded [template = constants.%C.1] // CHECK:STDOUT: %import_ref.7 = import_ref P//library, inst+25, unloaded // CHECK:STDOUT: %import_ref.8: %ImplicitAs.type.1 = import_ref Core//default, inst+15, loaded [template = constants.%ImplicitAs] @@ -926,31 +926,31 @@ fn F0(n: i32) -> P.D { // CHECK:STDOUT: %import_ref.11 = import_ref Core//default, inst+36, unloaded // CHECK:STDOUT: %import_ref.12 = import_ref Core//default, inst+36, unloaded // CHECK:STDOUT: %import_ref.13 = import_ref Core//default, inst+36, unloaded -// CHECK:STDOUT: %import_ref.14: type = import_ref P//library, inst+72, loaded [template = constants.%C.3] -// CHECK:STDOUT: %import_ref.15: type = import_ref P//library, inst+117, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.16: = import_ref P//library, inst+137, loaded [template = constants.%.22] -// CHECK:STDOUT: %import_ref.17: type = import_ref P//library, inst+147, loaded [template = constants.%C.4] -// CHECK:STDOUT: %import_ref.18: type = import_ref P//library, inst+152, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.19: = import_ref P//library, inst+167, loaded [template = constants.%.23] -// CHECK:STDOUT: %import_ref.20: type = import_ref P//library, inst+176, loaded [template = constants.%C.5] -// CHECK:STDOUT: %import_ref.21: type = import_ref P//library, inst+181, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.22: = import_ref P//library, inst+196, loaded [template = constants.%.24] -// CHECK:STDOUT: %import_ref.23: type = import_ref P//library, inst+205, loaded [template = constants.%C.6] -// CHECK:STDOUT: %import_ref.24: type = import_ref P//library, inst+210, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.25: = import_ref P//library, inst+225, loaded [template = constants.%.25] -// CHECK:STDOUT: %import_ref.26: type = import_ref P//library, inst+234, loaded [template = constants.%C.7] -// CHECK:STDOUT: %import_ref.27: type = import_ref P//library, inst+239, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.28: = import_ref P//library, inst+254, loaded [template = constants.%.26] -// CHECK:STDOUT: %import_ref.29: type = import_ref P//library, inst+263, loaded [template = constants.%C.8] -// CHECK:STDOUT: %import_ref.30: type = import_ref P//library, inst+268, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.31: = import_ref P//library, inst+283, loaded [template = constants.%.27] -// CHECK:STDOUT: %import_ref.32: type = import_ref P//library, inst+292, loaded [template = constants.%C.9] -// CHECK:STDOUT: %import_ref.33: type = import_ref P//library, inst+297, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.34: = import_ref P//library, inst+312, loaded [template = constants.%.28] -// CHECK:STDOUT: %import_ref.35: type = import_ref P//library, inst+321, loaded [template = constants.%C.10] -// CHECK:STDOUT: %import_ref.36: type = import_ref P//library, inst+326, loaded [template = constants.%ImplicitAs.type.3] -// CHECK:STDOUT: %import_ref.37: = import_ref P//library, inst+341, loaded [template = constants.%.29] -// CHECK:STDOUT: %import_ref.38: %Make.type = import_ref P//library, inst+52, loaded [template = constants.%Make] +// CHECK:STDOUT: %import_ref.14: type = import_ref P//library, inst+66, loaded [template = constants.%C.3] +// CHECK:STDOUT: %import_ref.15: type = import_ref P//library, inst+111, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.16: = import_ref P//library, inst+131, loaded [template = constants.%.22] +// CHECK:STDOUT: %import_ref.17: type = import_ref P//library, inst+141, loaded [template = constants.%C.4] +// CHECK:STDOUT: %import_ref.18: type = import_ref P//library, inst+146, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.19: = import_ref P//library, inst+161, loaded [template = constants.%.23] +// CHECK:STDOUT: %import_ref.20: type = import_ref P//library, inst+170, loaded [template = constants.%C.5] +// CHECK:STDOUT: %import_ref.21: type = import_ref P//library, inst+175, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.22: = import_ref P//library, inst+190, loaded [template = constants.%.24] +// CHECK:STDOUT: %import_ref.23: type = import_ref P//library, inst+199, loaded [template = constants.%C.6] +// CHECK:STDOUT: %import_ref.24: type = import_ref P//library, inst+204, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.25: = import_ref P//library, inst+219, loaded [template = constants.%.25] +// CHECK:STDOUT: %import_ref.26: type = import_ref P//library, inst+228, loaded [template = constants.%C.7] +// CHECK:STDOUT: %import_ref.27: type = import_ref P//library, inst+233, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.28: = import_ref P//library, inst+248, loaded [template = constants.%.26] +// CHECK:STDOUT: %import_ref.29: type = import_ref P//library, inst+257, loaded [template = constants.%C.8] +// CHECK:STDOUT: %import_ref.30: type = import_ref P//library, inst+262, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.31: = import_ref P//library, inst+277, loaded [template = constants.%.27] +// CHECK:STDOUT: %import_ref.32: type = import_ref P//library, inst+286, loaded [template = constants.%C.9] +// CHECK:STDOUT: %import_ref.33: type = import_ref P//library, inst+291, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.34: = import_ref P//library, inst+306, loaded [template = constants.%.28] +// CHECK:STDOUT: %import_ref.35: type = import_ref P//library, inst+315, loaded [template = constants.%C.10] +// CHECK:STDOUT: %import_ref.36: type = import_ref P//library, inst+320, loaded [template = constants.%ImplicitAs.type.3] +// CHECK:STDOUT: %import_ref.37: = import_ref P//library, inst+335, loaded [template = constants.%.29] +// CHECK:STDOUT: %import_ref.38: %Make.type = import_ref P//library, inst+48, loaded [template = constants.%Make] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index 0891a5dc73f2..b75fb2f7d9eb 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -247,17 +247,17 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: ref %.2 = import_ref Implicit//default, inst+19, loaded -// CHECK:STDOUT: %import_ref.2: ref %.6 = import_ref Implicit//default, inst+59, loaded -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+104, loaded [template = constants.%C.1] -// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+131, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.1: ref %.2 = import_ref Implicit//default, inst+17, loaded +// CHECK:STDOUT: %import_ref.2: ref %.6 = import_ref Implicit//default, inst+47, loaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+86, loaded [template = constants.%C.1] +// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+111, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .Int32 = %import_ref.5 // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.5: %Int32.type = import_ref Core//prelude/types, inst+15, loaded [template = constants.%Int32] -// CHECK:STDOUT: %import_ref.6 = import_ref Implicit//default, inst+109, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Implicit//default, inst+91, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -396,15 +396,15 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Implicit//default, inst+19, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Implicit//default, inst+59, unloaded -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+104, loaded [template = constants.%C.1] -// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+131, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.1 = import_ref Implicit//default, inst+17, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Implicit//default, inst+47, unloaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+86, loaded [template = constants.%C.1] +// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+111, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.5 = import_ref Implicit//default, inst+109, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Implicit//default, inst+91, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -506,16 +506,16 @@ var c_bad: C({.a = 3, .b = 4}) = F(); // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Implicit//default, inst+19, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Implicit//default, inst+59, unloaded -// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+104, loaded [template = constants.%C.1] -// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+131, loaded [template = constants.%F] +// CHECK:STDOUT: %import_ref.1 = import_ref Implicit//default, inst+17, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Implicit//default, inst+47, unloaded +// CHECK:STDOUT: %import_ref.3: %C.type = import_ref Implicit//default, inst+86, loaded [template = constants.%C.1] +// CHECK:STDOUT: %import_ref.4: %F.type = import_ref Implicit//default, inst+111, loaded [template = constants.%F] // CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { // CHECK:STDOUT: .ImplicitAs = %import_ref.6 // CHECK:STDOUT: import Core//prelude // CHECK:STDOUT: import Core//prelude/... // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.5 = import_ref Implicit//default, inst+109, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Implicit//default, inst+91, unloaded // CHECK:STDOUT: %import_ref.6: %ImplicitAs.type.1 = import_ref Core//prelude/operators/as, inst+49, loaded [template = constants.%ImplicitAs] // CHECK:STDOUT: %import_ref.7 = import_ref Core//prelude/operators/as, inst+55, unloaded // CHECK:STDOUT: %import_ref.8: @ImplicitAs.%.1 (%.11) = import_ref Core//prelude/operators/as, inst+77, loaded [symbolic = @ImplicitAs.%.2 (constants.%.15)] diff --git a/toolchain/lower/constant.cpp b/toolchain/lower/constant.cpp index 528ea882f54b..6fdaa614ba41 100644 --- a/toolchain/lower/constant.cpp +++ b/toolchain/lower/constant.cpp @@ -234,13 +234,6 @@ static auto EmitAsConstant(ConstantContext& /*context*/, CARBON_FATAL("TODO: Add support: {0}", inst); } -static auto EmitAsConstant(ConstantContext& /*context*/, - SemIR::StructTypeField /*inst*/) -> llvm::Constant* { - // A StructTypeField isn't a value, so this constant value won't ever be used. - // It also doesn't even have a type, so we can't use GetUnusedConstant. - return nullptr; -} - auto LowerConstants(FileContext& file_context, llvm::MutableArrayRef constants) -> void { ConstantContext context(file_context, constants); diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index f32dc6a3f901..63a990954505 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -548,13 +548,11 @@ static auto BuildTypeForInst(FileContext& context, SemIR::PointerType /*inst*/) static auto BuildTypeForInst(FileContext& context, SemIR::StructType inst) -> llvm::Type* { - auto fields = context.sem_ir().inst_blocks().Get(inst.fields_id); + auto fields = context.sem_ir().struct_type_fields().Get(inst.fields_id); llvm::SmallVector subtypes; subtypes.reserve(fields.size()); - for (auto field_id : fields) { - auto field = - context.sem_ir().insts().GetAs(field_id); - subtypes.push_back(context.GetType(field.field_type_id)); + for (auto field : fields) { + subtypes.push_back(context.GetType(field.type_id)); } return llvm::StructType::get(context.llvm_context(), subtypes); } diff --git a/toolchain/lower/handle_aggregates.cpp b/toolchain/lower/handle_aggregates.cpp index 3765849a4b52..45d710cf984c 100644 --- a/toolchain/lower/handle_aggregates.cpp +++ b/toolchain/lower/handle_aggregates.cpp @@ -91,14 +91,11 @@ static auto GetAggregateElement(FunctionContext& context, static auto GetStructFieldName(FunctionContext& context, SemIR::TypeId struct_type_id, SemIR::ElementIndex index) -> llvm::StringRef { - auto fields = context.sem_ir().inst_blocks().Get( - context.sem_ir() - .types() - .GetAs(struct_type_id) - .fields_id); - auto field = context.sem_ir().insts().GetAs( - fields[index.index]); - return context.sem_ir().names().GetIRBaseName(field.name_id); + auto struct_type = + context.sem_ir().types().GetAs(struct_type_id); + auto fields = + context.sem_ir().struct_type_fields().Get(struct_type.fields_id); + return context.sem_ir().names().GetIRBaseName(fields[index.index].name_id); } auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, @@ -237,11 +234,6 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, inst_id, EmitAggregateValueRepr(context, inst.type_id, inst.elements_id)); } -auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/, - SemIR::StructTypeField /*inst*/) -> void { - // No action to take. -} - auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, SemIR::TupleAccess inst) -> void { context.SetLocal(inst_id, diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 6b135c50fe36..7996b9e1cb1d 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -110,6 +110,7 @@ cc_library( "interface.h", "name.h", "name_scope.h", + "struct_type_field.h", "type.h", "type_info.h", ], diff --git a/toolchain/sem_ir/copy_on_write_block.h b/toolchain/sem_ir/copy_on_write_block.h index 676ccf2f9116..7fc279c3745d 100644 --- a/toolchain/sem_ir/copy_on_write_block.h +++ b/toolchain/sem_ir/copy_on_write_block.h @@ -68,6 +68,8 @@ class CopyOnWriteBlock { }; using CopyOnWriteInstBlock = CopyOnWriteBlock; +using CopyOnWriteStructTypeFieldsBlock = + CopyOnWriteBlock; using CopyOnWriteTypeBlock = CopyOnWriteBlock; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 4531ba0e9ceb..7461f552612c 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -111,6 +111,7 @@ auto File::OutputYaml(bool include_builtins) const -> Yaml::OutputMapping { map.Add("classes", classes_.OutputYaml()); map.Add("generics", generics_.OutputYaml()); map.Add("specifics", specifics_.OutputYaml()); + map.Add("struct_type_fields", struct_type_fields_.OutputYaml()); map.Add("types", types_.OutputYaml()); map.Add("type_blocks", type_blocks_.OutputYaml()); map.Add( @@ -163,6 +164,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const mem_usage.Collect(MemUsage::ConcatLabel(label, "import_irs_"), import_irs_); mem_usage.Collect(MemUsage::ConcatLabel(label, "import_ir_insts_"), import_ir_insts_); + mem_usage.Collect(MemUsage::ConcatLabel(label, "struct_type_fields_"), + struct_type_fields_); mem_usage.Collect(MemUsage::ConcatLabel(label, "type_blocks_"), type_blocks_); mem_usage.Collect(MemUsage::ConcatLabel(label, "insts_"), insts_); mem_usage.Collect(MemUsage::ConcatLabel(label, "name_scopes_"), name_scopes_); @@ -202,7 +205,6 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory { case Return::Kind: case ReturnSlotPattern::Kind: case ReturnExpr::Kind: - case StructTypeField::Kind: return ExprCategory::NotExpr; case ImportRefUnloaded::Kind: diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index fe871f497754..355c2f856ad4 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -26,6 +26,7 @@ #include "toolchain/sem_ir/interface.h" #include "toolchain/sem_ir/name.h" #include "toolchain/sem_ir/name_scope.h" +#include "toolchain/sem_ir/struct_type_field.h" #include "toolchain/sem_ir/type.h" #include "toolchain/sem_ir/type_info.h" @@ -142,6 +143,12 @@ class File : public Printable { } auto name_scopes() -> NameScopeStore& { return name_scopes_; } auto name_scopes() const -> const NameScopeStore& { return name_scopes_; } + auto struct_type_fields() -> StructTypeFieldsStore& { + return struct_type_fields_; + } + auto struct_type_fields() const -> const StructTypeFieldsStore& { + return struct_type_fields_; + } auto types() -> TypeStore& { return types_; } auto types() const -> const TypeStore& { return types_; } auto type_blocks() -> BlockValueStore& { return type_blocks_; } @@ -256,6 +263,9 @@ class File : public Printable { // types. ConstantStore constants_; + // Storage for StructTypeField lists. + StructTypeFieldsStore struct_type_fields_ = StructTypeFieldsStore(allocator_); + // Descriptions of types used in this file. TypeStore types_ = TypeStore(&insts_, &constant_values_); }; diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 5fcbc7f4b161..02f8a68beb4e 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -342,14 +342,6 @@ class FormatterImpl { sem_ir_.inst_blocks().GetOrEmpty(generic.GetEvalBlock(region)), sem_ir_.inst_blocks().GetOrEmpty( specific.GetValueBlock(region)))) { - if (generic_inst_id && specific_inst_id && - sem_ir_.insts().Is(*generic_inst_id) && - sem_ir_.insts().Is(*specific_inst_id)) { - // Skip printing struct type fields to match the way we print the - // generic. - continue; - } - Indent(); if (generic_inst_id) { FormatName(*generic_inst_id); @@ -899,18 +891,14 @@ class FormatterImpl { FormatTrailingBlock(inst.requirements_id); } - // StructTypeFields are formatted as part of their StructType. - auto FormatInst(InstId /*inst_id*/, StructTypeField /*inst*/) -> void {} - auto FormatInstRHS(StructType inst) -> void { out_ << " {"; llvm::ListSeparator sep; - for (auto field_id : sem_ir_.inst_blocks().Get(inst.fields_id)) { + for (auto field : sem_ir_.struct_type_fields().Get(inst.fields_id)) { out_ << sep << "."; - auto field = sem_ir_.insts().GetAs(field_id); FormatName(field.name_id); out_ << ": "; - FormatType(field.field_type_id); + FormatType(field.type_id); } out_ << "}"; } diff --git a/toolchain/sem_ir/id_kind.h b/toolchain/sem_ir/id_kind.h index 50540481e9bc..376a7fbdf436 100644 --- a/toolchain/sem_ir/id_kind.h +++ b/toolchain/sem_ir/id_kind.h @@ -123,8 +123,9 @@ using IdKind = TypeEnum< InstId, AbsoluteInstId, MatchingInstId, ConstantId, EntityNameId, CompileTimeBindIndex, RuntimeParamIndex, FacetTypeId, FunctionId, ClassId, InterfaceId, ImplId, GenericId, SpecificId, ImportIRId, ImportIRInstId, - LocId, BoolValue, IntKind, NameId, NameScopeId, InstBlockId, TypeId, - TypeBlockId, ElementIndex, LibraryNameId, FloatKind>; + LocId, BoolValue, IntKind, NameId, NameScopeId, InstBlockId, + StructTypeFieldsId, TypeId, TypeBlockId, ElementIndex, LibraryNameId, + FloatKind>; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index c52e66cbe8dd..fbd95f0e784d 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -29,6 +29,7 @@ struct ImportIRInst; struct Impl; struct Interface; struct NameScope; +struct StructTypeField; struct TypeInfo; // The ID of an instruction. @@ -722,6 +723,25 @@ constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(3); constexpr InstBlockId InstBlockId::Invalid = InstBlockId(InvalidIndex); constexpr InstBlockId InstBlockId::Unreachable = InstBlockId(InvalidIndex - 1); +// The ID of a type block. +struct StructTypeFieldsId : public IdBase, + public Printable { + using ElementType = StructTypeField; + using ValueType = llvm::MutableArrayRef; + + // An explicitly invalid ID. + static const StructTypeFieldsId Invalid; + + using IdBase::IdBase; + auto Print(llvm::raw_ostream& out) const -> void { + out << "type_block"; + IdBase::Print(out); + } +}; + +constexpr StructTypeFieldsId StructTypeFieldsId::Invalid = + StructTypeFieldsId(InvalidIndex); + // The ID of a type. struct TypeId : public IdBase, public Printable { // `StringifyTypeExpr` is used for diagnostics. However, where possible, an diff --git a/toolchain/sem_ir/inst_kind.def b/toolchain/sem_ir/inst_kind.def index 5120c02fcb72..37109a278928 100644 --- a/toolchain/sem_ir/inst_kind.def +++ b/toolchain/sem_ir/inst_kind.def @@ -91,7 +91,6 @@ CARBON_SEM_IR_INST_KIND(StructAccess) CARBON_SEM_IR_INST_KIND(StructInit) CARBON_SEM_IR_INST_KIND(StructLiteral) CARBON_SEM_IR_INST_KIND(StructType) -CARBON_SEM_IR_INST_KIND(StructTypeField) CARBON_SEM_IR_INST_KIND(StructValue) CARBON_SEM_IR_INST_KIND(SymbolicBindingPattern) CARBON_SEM_IR_INST_KIND(TemporaryStorage) diff --git a/toolchain/sem_ir/stringify_type.cpp b/toolchain/sem_ir/stringify_type.cpp index c47ef4ef6d50..34daa24261ff 100644 --- a/toolchain/sem_ir/stringify_type.cpp +++ b/toolchain/sem_ir/stringify_type.cpp @@ -206,26 +206,22 @@ auto StringifyTypeExpr(const SemIR::File& outer_sem_ir, InstId outer_inst_id) break; } case CARBON_KIND(StructType inst): { - auto refs = sem_ir.inst_blocks().Get(inst.fields_id); - if (refs.empty()) { + auto fields = sem_ir.struct_type_fields().Get(inst.fields_id); + if (fields.empty()) { out << "{}"; break; - } else if (step.index == 0) { - out << "{"; - } else if (step.index < static_cast(refs.size())) { - out << ", "; - } else { + } + + if (step.index >= static_cast(fields.size())) { out << "}"; break; } + const auto& field = fields[step.index]; + out << (step.index == 0 ? "{" : ", ") << "." + << sem_ir.names().GetFormatted(field.name_id) << ": "; steps.push_back(step.Next()); - push_inst_id(refs[step.index]); - break; - } - case CARBON_KIND(StructTypeField inst): { - out << "." << sem_ir.names().GetFormatted(inst.name_id) << ": "; - push_inst_id(sem_ir.types().GetInstId(inst.field_type_id)); + push_inst_id(sem_ir.types().GetInstId(field.type_id)); break; } case CARBON_KIND(TupleType inst): { diff --git a/toolchain/sem_ir/struct_type_field.h b/toolchain/sem_ir/struct_type_field.h new file mode 100644 index 000000000000..83720fbda6e9 --- /dev/null +++ b/toolchain/sem_ir/struct_type_field.h @@ -0,0 +1,39 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_SEM_IR_STRUCT_TYPE_FIELD_H_ +#define CARBON_TOOLCHAIN_SEM_IR_STRUCT_TYPE_FIELD_H_ + +#include "toolchain/sem_ir/block_value_store.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::SemIR { + +// A field in a struct's type, such as `.a: i32` in `{.a: i32}`. +struct StructTypeField : Printable { + auto Print(llvm::raw_ostream& out) const -> void { + out << "{name_id: " << name_id << ", type_id: " << type_id << "}"; + } + + friend auto operator==(StructTypeField lhs, StructTypeField rhs) -> bool { + return std::memcmp(&lhs, &rhs, sizeof(StructTypeField)) == 0; + } + + NameId name_id; + TypeId type_id; +}; + +using StructTypeFieldsStore = BlockValueStore; + +// See common/hashing.h. Supports canonicalization of fields. +inline auto CarbonHashValue(const StructTypeField& value, uint64_t seed) + -> HashCode { + Hasher hasher(seed); + hasher.HashRaw(value); + return static_cast(hasher); +} + +} // namespace Carbon::SemIR + +#endif // CARBON_TOOLCHAIN_SEM_IR_STRUCT_TYPE_FIELD_H_ diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index 4b42a0253be1..d4b03133c816 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -1117,22 +1117,7 @@ struct StructType { .constant_kind = InstConstantKind::Conditional}); TypeId type_id; - InstBlockId fields_id; -}; - -// A field in a struct's type, such as `.a: i32` in `{.a: i32}`. -// -// This instruction is an implementation detail of `StructType`, and doesn't -// produce a value. As a consequence, although there's a type for the field, the -// instruction has no type. -struct StructTypeField { - // TODO: Make Parse::NodeId more specific. - static constexpr auto Kind = InstKind::StructTypeField.Define( - {.ir_name = "struct_type_field", - .constant_kind = InstConstantKind::Conditional}); - - NameId name_id; - TypeId field_type_id; + StructTypeFieldsId fields_id; }; // A struct value. diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index 34456d1c4eb7..6d9126542be9 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -63,6 +63,7 @@ TEST(SemIRTest, YAML) { Pair("classes", Yaml::Mapping(SizeIs(0))), Pair("generics", Yaml::Mapping(SizeIs(0))), Pair("specifics", Yaml::Mapping(SizeIs(0))), + Pair("struct_type_fields", Yaml::Mapping(SizeIs(0))), Pair("types", Yaml::Mapping(Each(type_builtin))), Pair("type_blocks", Yaml::Mapping(SizeIs(Ge(1)))), Pair("insts",