diff --git a/toolchain/check/call.cpp b/toolchain/check/call.cpp index c63dc3d49433..01639efd1715 100644 --- a/toolchain/check/call.cpp +++ b/toolchain/check/call.cpp @@ -25,9 +25,10 @@ static auto PerformCallToGenericClass(Context& context, Parse::NodeId node_id, context, node_id, /*self_id=*/SemIR::InstId::Invalid, arg_ids, /*return_storage_id=*/SemIR::InstId::Invalid, class_info.decl_id, class_info.implicit_param_refs_id, class_info.param_refs_id); - return context.AddInst( - {node_id, - SemIR::ClassType{SemIR::TypeId::TypeType, class_id, converted_args_id}}); + return context.AddInst(node_id, + {.type_id = SemIR::TypeId::TypeType, + .class_id = class_id, + .args_id = converted_args_id}); } auto PerformCall(Context& context, Parse::NodeId node_id, @@ -73,8 +74,8 @@ auto PerformCall(Context& context, Parse::NodeId node_id, case SemIR::Function::ReturnSlot::Present: // Tentatively put storage for a temporary in the function's return slot. // This will be replaced if necessary when we perform initialization. - return_storage_id = context.AddInst( - {node_id, SemIR::TemporaryStorage{callable.return_type_id}}); + return_storage_id = context.AddInst( + node_id, {.type_id = callable.return_type_id}); break; case SemIR::Function::ReturnSlot::Absent: break; @@ -91,8 +92,10 @@ auto PerformCall(Context& context, Parse::NodeId node_id, ConvertCallArgs(context, node_id, callee_function.self_id, arg_ids, return_storage_id, callable.decl_id, callable.implicit_param_refs_id, callable.param_refs_id); - auto call_inst_id = context.AddInst( - {node_id, SemIR::Call{type_id, callee_id, converted_args_id}}); + auto call_inst_id = + context.AddInst(node_id, {.type_id = type_id, + .callee_id = callee_id, + .args_id = converted_args_id}); return call_inst_id; } diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index adc2b1c29625..528ebc518f07 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -323,10 +323,10 @@ static auto InitPackageScopeAndImports(Context& context, UnitInfo& unit_info, SemIR::NameScopeId::Invalid); CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package); - auto package_inst_id = context.AddInst( - {Parse::NodeId::Invalid, - SemIR::Namespace{namespace_type_id, SemIR::NameScopeId::Package, - SemIR::InstId::Invalid}}); + auto package_inst_id = context.AddInst( + Parse::NodeId::Invalid, {.type_id = namespace_type_id, + .name_scope_id = SemIR::NameScopeId::Package, + .import_id = SemIR::InstId::Invalid}); CARBON_CHECK(package_inst_id == SemIR::InstId::PackageNamespace); // If there is an implicit `api` import, set it first so that it uses the diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 29a774d52fd1..33844c85f93c 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -114,11 +114,6 @@ auto Context::AddConstant(SemIR::Inst inst, bool is_symbolic) return const_id; } -auto Context::AddInstAndPush(SemIR::LocIdAndInst loc_id_and_inst) -> void { - auto inst_id = AddInst(loc_id_and_inst); - node_stack_.Push(loc_id_and_inst.loc_id.node_id(), inst_id); -} - auto Context::ReplaceLocIdAndInstBeforeConstantUse( SemIR::InstId inst_id, SemIR::LocIdAndInst loc_id_and_inst) -> void { sem_ir().insts().SetLocIdAndInst(inst_id, loc_id_and_inst); @@ -479,7 +474,7 @@ static auto AddDominatedBlockAndBranchImpl(Context& context, return SemIR::InstBlockId::Unreachable; } auto block_id = context.inst_blocks().AddDefaultValue(); - context.AddInst({node_id, BranchNode{block_id, args...}}); + context.AddInst(node_id, {block_id, args...}); return block_id; } @@ -512,7 +507,7 @@ auto Context::AddConvergenceBlockAndPush(Parse::NodeId node_id, int num_blocks) if (new_block_id == SemIR::InstBlockId::Unreachable) { new_block_id = inst_blocks().AddDefaultValue(); } - AddInst({node_id, SemIR::Branch{new_block_id}}); + AddInst(node_id, {.target_id = new_block_id}); } inst_block_stack().Pop(); } @@ -530,7 +525,8 @@ auto Context::AddConvergenceBlockWithArgAndPush( if (new_block_id == SemIR::InstBlockId::Unreachable) { new_block_id = inst_blocks().AddDefaultValue(); } - AddInst({node_id, SemIR::BranchWithArg{new_block_id, arg_id}}); + AddInst( + node_id, {.target_id = new_block_id, .arg_id = arg_id}); } inst_block_stack().Pop(); } @@ -538,7 +534,8 @@ auto Context::AddConvergenceBlockWithArgAndPush( // Acquire the result value. SemIR::TypeId result_type_id = insts().Get(*block_args.begin()).type_id(); - return AddInst({node_id, SemIR::BlockArg{result_type_id, new_block_id}}); + return AddInst( + node_id, {.type_id = result_type_id, .block_id = new_block_id}); } auto Context::SetBlockArgResultBeforeConstantUse(SemIR::InstId select_id, @@ -616,7 +613,7 @@ auto Context::is_current_position_reachable() -> bool { auto Context::FinalizeGlobalInit() -> void { inst_block_stack().PushGlobalInit(); if (!inst_block_stack().PeekCurrentBlockContents().empty()) { - AddInst({Parse::NodeId::Invalid, SemIR::Return{}}); + AddInst(Parse::NodeId::Invalid, {}); // Pop the GlobalInit block here to finalize it. inst_block_stack().Pop(); diff --git a/toolchain/check/context.h b/toolchain/check/context.h index ef36969ed5fd..95276d19a062 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -44,10 +44,22 @@ class Context { // Adds an instruction to the current block, returning the produced ID. auto AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; + // Convenience for AddInst on specific instruction types. + template + auto AddInst(LocT loc_id, InstT inst) -> SemIR::InstId { + return AddInst(SemIR::LocIdAndInst(loc_id, inst)); + } + // Adds an instruction in no block, returning the produced ID. Should be used // rarely. auto AddInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; + // Convenience for AddInstInNoBlock on specific instruction types. + template + auto AddInstInNoBlock(LocT loc_id, InstT inst) -> SemIR::InstId { + return AddInstInNoBlock(SemIR::LocIdAndInst(loc_id, inst)); + } + // Adds an instruction to the current block, returning the produced ID. The // instruction is a placeholder that is expected to be replaced by // `ReplaceInstBeforeConstantUse`. @@ -64,7 +76,12 @@ class Context { // Pushes a parse tree node onto the stack, storing the SemIR::Inst as the // result. Only valid if the LocId is for a NodeId. - auto AddInstAndPush(SemIR::LocIdAndInst loc_id_and_inst) -> void; + template + auto AddInstAndPush(LocT loc_id, InstT inst) -> void { + SemIR::LocIdAndInst arg(loc_id, inst); + auto inst_id = AddInst(arg); + node_stack_.Push(arg.loc_id.node_id(), inst_id); + } // Replaces the instruction `inst_id` with `loc_id_and_inst`. The instruction // is required to not have been used in any constant evaluation, either diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 4c588e7e1edc..d94497bdefbd 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -100,9 +100,10 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id, << "initialized multiple times? Have " << sem_ir.insts().Get(return_slot_id); auto init = sem_ir.insts().Get(init_id); - return context.AddInst( - {sem_ir.insts().GetLocId(init_id), - SemIR::Temporary{init.type_id(), return_slot_id, init_id}}); + return context.AddInst(sem_ir.insts().GetLocId(init_id), + {.type_id = init.type_id(), + .storage_id = return_slot_id, + .init_id = init_id}); } if (discarded) { @@ -117,10 +118,11 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id, // instructions. auto init = sem_ir.insts().Get(init_id); auto loc_id = sem_ir.insts().GetLocId(init_id); - auto temporary_id = - context.AddInst({loc_id, SemIR::TemporaryStorage{init.type_id()}}); - return context.AddInst( - {loc_id, SemIR::Temporary{init.type_id(), temporary_id, init_id}}); + auto temporary_id = context.AddInst( + loc_id, {.type_id = init.type_id()}); + return context.AddInst(loc_id, {.type_id = init.type_id(), + .storage_id = temporary_id, + .init_id = init_id}); } // Materialize a temporary to hold the result of the given expression if it is @@ -144,15 +146,14 @@ static auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id, // TODO: Add a new instruction kind for indexing an array at a constant // index so that we don't need an integer literal instruction here, and // remove this special case. - auto index_id = block.AddInst( - {loc_id, - SemIR::IntLiteral{context.GetBuiltinType(SemIR::BuiltinKind::IntType), - context.ints().Add(llvm::APInt(32, i))}}); - return block.AddInst( - {loc_id, AccessInstT{elem_type_id, aggregate_id, index_id}}); + auto index_id = block.template AddInst( + loc_id, {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::IntType), + .int_id = context.ints().Add(llvm::APInt(32, i))}); + return block.template AddInst( + loc_id, {elem_type_id, aggregate_id, index_id}); } else { - return block.AddInst({loc_id, AccessInstT{elem_type_id, aggregate_id, - SemIR::ElementIndex(i)}}); + return block.template AddInst( + loc_id, {elem_type_id, aggregate_id, SemIR::ElementIndex(i)}); } } @@ -250,8 +251,8 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type, // destination for the array initialization if we weren't given one. SemIR::InstId return_slot_id = target.init_id; if (!target.init_id.is_valid()) { - return_slot_id = target_block->AddInst( - {value_loc_id, SemIR::TemporaryStorage{target.type_id}}); + return_slot_id = target_block->AddInst( + value_loc_id, {.type_id = target.type_id}); } // Initialize each element of the array from the corresponding element of the @@ -277,10 +278,10 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type, // Flush the temporary here if we didn't insert it earlier, so we can add a // reference to the return slot. target_block->InsertHere(); - return context.AddInst( - {value_loc_id, - SemIR::ArrayInit{target.type_id, sem_ir.inst_blocks().Add(inits), - return_slot_id}}); + return context.AddInst( + value_loc_id, {.type_id = target.type_id, + .inits_id = sem_ir.inst_blocks().Add(inits), + .dest_id = return_slot_id}); } // Performs a conversion from a tuple to a tuple type. This function only @@ -357,12 +358,14 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type, if (is_init) { target.init_block->InsertHere(); - return context.AddInst( - {value_loc_id, - SemIR::TupleInit{target.type_id, new_block.id(), target.init_id}}); + return context.AddInst(value_loc_id, + {.type_id = target.type_id, + .elements_id = new_block.id(), + .dest_id = target.init_id}); } else { - return context.AddInst( - {value_loc_id, SemIR::TupleValue{target.type_id, new_block.id()}}); + return context.AddInst( + value_loc_id, + {.type_id = target.type_id, .elements_id = new_block.id()}); } } @@ -488,17 +491,20 @@ static auto ConvertStructToStructOrClass(Context& context, target.init_block->InsertHere(); CARBON_CHECK(is_init) << "Converting directly to a class value is not supported"; - return context.AddInst( - {value_loc_id, - SemIR::ClassInit{target.type_id, new_block.id(), target.init_id}}); + return context.AddInst(value_loc_id, + {.type_id = target.type_id, + .elements_id = new_block.id(), + .dest_id = target.init_id}); } else if (is_init) { target.init_block->InsertHere(); - return context.AddInst( - {value_loc_id, - SemIR::StructInit{target.type_id, new_block.id(), target.init_id}}); + return context.AddInst(value_loc_id, + {.type_id = target.type_id, + .elements_id = new_block.id(), + .dest_id = target.init_id}); } else { - return context.AddInst( - {value_loc_id, SemIR::StructValue{target.type_id, new_block.id()}}); + return context.AddInst( + value_loc_id, + {.type_id = target.type_id, .elements_id = new_block.id()}); } } @@ -543,9 +549,8 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type, if (need_temporary) { target.kind = ConversionTarget::Initializer; target.init_block = &target_block; - target.init_id = - target_block.AddInst({context.insts().GetLocId(value_id), - SemIR::TemporaryStorage{target.type_id}}); + target.init_id = target_block.AddInst( + context.insts().GetLocId(value_id), {.type_id = target.type_id}); } auto result_id = ConvertStructToStructOrClass( @@ -553,9 +558,10 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type, if (need_temporary) { target_block.InsertHere(); - result_id = context.AddInst( - {context.insts().GetLocId(value_id), - SemIR::Temporary{target.type_id, target.init_id, result_id}}); + result_id = context.AddInst( + context.insts().GetLocId(value_id), {.type_id = target.type_id, + .storage_id = target.init_id, + .init_id = result_id}); } return result_id; } @@ -610,9 +616,10 @@ static auto ConvertDerivedToBase(Context& context, SemIR::LocId loc_id, // Add a series of `.base` accesses. for (auto base_id : path) { auto base_decl = context.insts().GetAs(base_id); - value_id = context.AddInst( - {loc_id, SemIR::ClassElementAccess{base_decl.base_type_id, value_id, - base_decl.index}}); + value_id = context.AddInst( + loc_id, {.type_id = base_decl.base_type_id, + .base_id = value_id, + .index = base_decl.index}); } return value_id; } @@ -624,14 +631,15 @@ static auto ConvertDerivedPointerToBasePointer( const InheritancePath& path) -> SemIR::InstId { // Form `*p`. ptr_id = ConvertToValueExpr(context, ptr_id); - auto ref_id = - context.AddInst({loc_id, SemIR::Deref{src_ptr_type.pointee_id, ptr_id}}); + auto ref_id = context.AddInst( + loc_id, {.type_id = src_ptr_type.pointee_id, .pointer_id = ptr_id}); // Convert as a reference expression. ref_id = ConvertDerivedToBase(context, loc_id, ref_id, path); // Take the address. - return context.AddInst({loc_id, SemIR::AddrOf{dest_ptr_type_id, ref_id}}); + return context.AddInst( + loc_id, {.type_id = dest_ptr_type_id, .lvalue_id = ref_id}); } // Returns whether `category` is a valid expression category to produce as a @@ -729,8 +737,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, // The initializer produces an object representation by copy, and the // value representation is a copy of the object representation, so we // already have a value of the right form. - return context.AddInst( - {loc_id, SemIR::ValueOfInitializer{value_type_id, value_id}}); + return context.AddInst( + loc_id, {.type_id = value_type_id, .init_id = value_id}); } } } @@ -750,8 +758,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, ConversionTarget{.kind = ConversionTarget::Value, .type_id = value_type_id}); } - return context.AddInst( - {loc_id, SemIR::AsCompatible{target.type_id, value_id}}); + return context.AddInst( + loc_id, {.type_id = target.type_id, .source_id = value_id}); } } @@ -856,8 +864,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, // TODO: Support converting tuple and struct values to facet types, // combining the above conversions and this one in a single conversion. if (sem_ir.types().Is(value_type_id)) { - return context.AddInst( - {loc_id, SemIR::FacetTypeAccess{target.type_id, value_id}}); + return context.AddInst( + loc_id, {.type_id = target.type_id, .facet_id = value_id}); } } @@ -967,8 +975,10 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, // Track that we performed a type conversion, if we did so. if (orig_expr_id != expr_id) { - expr_id = context.AddInst( - {loc_id, SemIR::Converted{target.type_id, orig_expr_id, expr_id}}); + expr_id = + context.AddInst(loc_id, {.type_id = target.type_id, + .original_id = orig_expr_id, + .result_id = expr_id}); } // For `as`, don't perform any value category conversions. In particular, an @@ -1018,8 +1028,9 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, // If we have a reference and don't want one, form a value binding. // TODO: Support types with custom value representations. - expr_id = context.AddInst({context.insts().GetLocId(expr_id), - SemIR::BindValue{expr.type_id(), expr_id}}); + expr_id = context.AddInst( + context.insts().GetLocId(expr_id), + {.type_id = expr.type_id(), .value_id = expr_id}); // We now have a value expression. [[fallthrough]]; @@ -1036,9 +1047,10 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, if (auto init_rep = SemIR::GetInitRepr(sem_ir, target.type_id); init_rep.kind == SemIR::InitRepr::ByCopy) { target.init_block->InsertHere(); - expr_id = context.AddInst( - {loc_id, - SemIR::InitializeFrom{target.type_id, expr_id, target.init_id}}); + expr_id = context.AddInst( + loc_id, {.type_id = target.type_id, + .src_id = expr_id, + .dest_id = target.init_id}); } } @@ -1143,9 +1155,9 @@ static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id, return SemIR::InstId::BuiltinError; } auto loc_id = context.insts().GetLocId(self_or_addr_id); - self_or_addr_id = context.AddInst( - {loc_id, SemIR::AddrOf{context.GetPointerType(self.type_id()), - self_or_addr_id}}); + self_or_addr_id = context.AddInst( + loc_id, {.type_id = context.GetPointerType(self.type_id()), + .lvalue_id = self_or_addr_id}); } return ConvertToValueOfType(context, call_loc_id, self_or_addr_id, diff --git a/toolchain/check/handle_alias.cpp b/toolchain/check/handle_alias.cpp index 9e402f3e3840..c38a43618fea 100644 --- a/toolchain/check/handle_alias.cpp +++ b/toolchain/check/handle_alias.cpp @@ -44,30 +44,30 @@ auto HandleAlias(Context& context, Parse::AliasId /*node_id*/) -> bool { .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(), .bind_index = SemIR::CompileTimeBindIndex::Invalid}); - auto alias_id = SemIR::InstId::Invalid; + auto alias_type_id = SemIR::TypeId::Invalid; + auto alias_value_id = SemIR::InstId::Invalid; if (expr_id.is_builtin()) { // Type (`bool`) and value (`false`) literals provided by the builtin // structure should be turned into name references. // TODO: Look into handling `false`, this doesn't do it right now because it // sees a value instruction instead of a builtin. - alias_id = context.AddInst( - {name_context.loc_id, - SemIR::BindAlias{context.insts().Get(expr_id).type_id(), bind_name_id, - expr_id}}); + alias_type_id = context.insts().Get(expr_id).type_id(); + alias_value_id = expr_id; } else if (auto inst = context.insts().TryGetAs(expr_id)) { // Pass through name references, albeit changing the name in use. - alias_id = context.AddInst( - {name_context.loc_id, - SemIR::BindAlias{inst->type_id, bind_name_id, inst->value_id}}); + alias_type_id = inst->type_id; + alias_value_id = inst->value_id; } else { CARBON_DIAGNOSTIC(AliasRequiresNameRef, Error, "Alias initializer must be a name reference."); context.emitter().Emit(expr_node, AliasRequiresNameRef); - alias_id = - context.AddInst({name_context.loc_id, - SemIR::BindAlias{SemIR::TypeId::Error, bind_name_id, - SemIR::InstId::BuiltinError}}); + alias_type_id = SemIR::TypeId::Error; + alias_value_id = SemIR::InstId::BuiltinError; } + auto alias_id = context.AddInst( + name_context.loc_id, {.type_id = alias_type_id, + .bind_name_id = bind_name_id, + .value_id = alias_value_id}); // Add the name of the binding to the current scope. context.decl_name_stack().PopScope(); diff --git a/toolchain/check/handle_array.cpp b/toolchain/check/handle_array.cpp index e1fef509f183..8b0e907b8d3e 100644 --- a/toolchain/check/handle_array.cpp +++ b/toolchain/check/handle_array.cpp @@ -46,10 +46,11 @@ auto HandleArrayExpr(Context& context, Parse::ArrayExprId node_id) -> bool { return true; } - context.AddInstAndPush( - {node_id, SemIR::ArrayType{SemIR::TypeId::TypeType, bound_inst_id, - ExprAsType(context, element_type_node_id, - element_type_inst_id)}}); + context.AddInstAndPush( + node_id, {.type_id = SemIR::TypeId::TypeType, + .bound_id = bound_inst_id, + .element_type_id = ExprAsType(context, element_type_node_id, + element_type_inst_id)}); return true; } diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 4ab73fa83b31..f09e6b5251f9 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/convert.h" #include "toolchain/check/return.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" namespace Carbon::Check { @@ -45,10 +46,15 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, : SemIR::CompileTimeBindIndex::Invalid}); if (is_generic) { // TODO: Create a `BindTemplateName` instead inside a `template` pattern. - return {name_node, - SemIR::BindSymbolicName{type_id, bind_name_id, value_id}}; + return SemIR::LocIdAndInst( + name_node, SemIR::BindSymbolicName{.type_id = type_id, + .bind_name_id = bind_name_id, + .value_id = value_id}); } else { - return {name_node, SemIR::BindName{type_id, bind_name_id, value_id}}; + return SemIR::LocIdAndInst(name_node, + SemIR::BindName{.type_id = type_id, + .bind_name_id = bind_name_id, + .value_id = value_id}); } }; @@ -98,16 +104,19 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, context.classes().Get(enclosing_class_decl->class_id); auto field_type_id = context.GetUnboundElementType( class_info.self_type_id, cast_type_id); - auto field_id = context.AddInst( - {binding_id, SemIR::FieldDecl{ - field_type_id, name_id, - SemIR::ElementIndex(context.args_type_info_stack() - .PeekCurrentBlockContents() - .size())}}); + auto field_id = context.AddInst( + binding_id, + {.type_id = field_type_id, + .name_id = name_id, + .index = SemIR::ElementIndex(context.args_type_info_stack() + .PeekCurrentBlockContents() + .size())}); // Add a corresponding field to the object representation of the class. - context.args_type_info_stack().AddInstId(context.AddInstInNoBlock( - {binding_id, SemIR::StructTypeField{name_id, cast_type_id}})); + context.args_type_info_stack().AddInstId( + context.AddInstInNoBlock( + binding_id, + {.name_id = name_id, .field_type_id = cast_type_id})); context.node_stack().Push(node_id, field_id); break; } @@ -120,8 +129,8 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, CheckReturnedVar(context, context.node_stack().PeekNodeId(), name_node, name_id, type_node, cast_type_id); } else { - value_id = context.AddInst( - {name_node, SemIR::VarStorage{cast_type_id, name_id}}); + value_id = context.AddInst( + name_node, {.type_id = cast_type_id, .name_id = name_id}); } auto bind_id = context.AddInst(make_bind_name(cast_type_id, value_id)); context.node_stack().Push(node_id, bind_id); @@ -138,8 +147,8 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, // in a function definition. We don't know which kind we have here. // TODO: A tuple pattern can appear in other places than function // parameters. - auto param_id = - context.AddInst({name_node, SemIR::Param{cast_type_id, name_id}}); + auto param_id = context.AddInst( + name_node, {.type_id = cast_type_id, .name_id = name_id}); auto bind_id = context.AddInst(make_bind_name(cast_type_id, param_id)); // TODO: Bindings should come into scope immediately in other contexts // too. @@ -192,8 +201,8 @@ auto HandleAddr(Context& context, Parse::AddrId node_id) -> bool { SemIR::NameId::SelfValue) { // TODO: The type of an `addr_pattern` should probably be the non-pointer // type, because that's the type that the pattern matches. - context.AddInstAndPush( - {node_id, SemIR::AddrPattern{self_param->type_id, self_param_id}}); + context.AddInstAndPush( + node_id, {.type_id = self_param->type_id, .inner_id = self_param_id}); } else { CARBON_DIAGNOSTIC(AddrOnNonSelfParam, Error, "`addr` can only be applied to a `self` parameter."); diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 62e573d69379..677768867b4c 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -11,6 +11,7 @@ #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -211,9 +212,11 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, auto decl_block_id = context.inst_block_stack().Pop(); // Add the class declaration. - auto class_decl = SemIR::ClassDecl{SemIR::TypeId::TypeType, - SemIR::ClassId::Invalid, decl_block_id}; - auto class_decl_id = context.AddPlaceholderInst({node_id, class_decl}); + auto class_decl = SemIR::ClassDecl{.type_id = SemIR::TypeId::TypeType, + .class_id = SemIR::ClassId::Invalid, + .decl_block_id = decl_block_id}; + auto class_decl_id = + context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, class_decl)); // TODO: Store state regarding is_extern. SemIR::Class class_info = { @@ -388,8 +391,8 @@ auto HandleAdaptDecl(Context& context, Parse::AdaptDeclId node_id) -> bool { }); // Build a SemIR representation for the declaration. - class_info.adapt_id = - context.AddInst({node_id, SemIR::AdaptDecl{adapted_type_id}}); + class_info.adapt_id = context.AddInst( + node_id, {.adapted_type_id = adapted_type_id}); // Extend the class scope with the adapted type's scope if requested. if (modifiers.HasAnyOf(KeywordModifierSet::Extend)) { @@ -520,19 +523,20 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool { // binding will be performed when it's found by name lookup into an instance. auto field_type_id = context.GetUnboundElementType(class_info.self_type_id, base_info.type_id); - class_info.base_id = context.AddInst( - {node_id, - SemIR::BaseDecl{field_type_id, base_info.type_id, - SemIR::ElementIndex(context.args_type_info_stack() - .PeekCurrentBlockContents() - .size())}}); + 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())}); // 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, - SemIR::StructTypeField{SemIR::NameId::Base, base_info.type_id}})); + context.args_type_info_stack().AddInstId( + context.AddInstInNoBlock( + node_id, {.name_id = SemIR::NameId::Base, + .field_type_id = base_info.type_id})); // Bind the name `base` in the class to the base field. context.decl_name_stack().AddNameOrDiagnoseDuplicate( diff --git a/toolchain/check/handle_export.cpp b/toolchain/check/handle_export.cpp index db2c589ce208..c51d389c17ac 100644 --- a/toolchain/check/handle_export.cpp +++ b/toolchain/check/handle_export.cpp @@ -67,10 +67,10 @@ auto HandleExportDecl(Context& context, Parse::ExportDeclId node_id) -> bool { return true; } - auto export_id = context.AddInst( - {node_id, SemIR::ExportDecl{.type_id = import_ref->type_id, - .bind_name_id = import_ref->bind_name_id, - .value_id = inst_id}}); + auto export_id = context.AddInst( + node_id, {.type_id = import_ref->type_id, + .bind_name_id = import_ref->bind_name_id, + .value_id = inst_id}); context.AddExport(export_id); // Replace the ImportRef in name lookup, both for the above duplicate diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index cc621d65fe9a..fa84c528ec49 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -39,8 +39,8 @@ auto HandleReturnType(Context& context, Parse::ReturnTypeId node_id) -> bool { auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId(); auto type_id = ExprAsType(context, type_node_id, type_inst_id); // TODO: Use a dedicated instruction rather than VarStorage here. - context.AddInstAndPush( - {node_id, SemIR::VarStorage{type_id, SemIR::NameId::ReturnSlot}}); + context.AddInstAndPush( + node_id, {.type_id = type_id, .name_id = SemIR::NameId::ReturnSlot}); return true; } @@ -254,7 +254,8 @@ static auto BuildFunctionDecl(Context& context, auto function_info = SemIR::Function{ .name_id = name_context.name_id_for_new_inst(), .enclosing_scope_id = name_context.enclosing_scope_id_for_new_inst(), - .decl_id = context.AddPlaceholderInst({node_id, function_decl}), + .decl_id = context.AddPlaceholderInst( + SemIR::LocIdAndInst(node_id, function_decl)), .implicit_param_refs_id = name.implicit_params_id, .param_refs_id = name.params_id, .return_type_id = return_type_id, @@ -406,7 +407,7 @@ auto HandleFunctionDefinition(Context& context, "Missing `return` at end of function with declared return type."); context.emitter().Emit(TokenOnly(node_id), MissingReturnStatement); } else { - context.AddInst({node_id, SemIR::Return{}}); + context.AddInst(node_id, {}); } } diff --git a/toolchain/check/handle_if_statement.cpp b/toolchain/check/handle_if_statement.cpp index 12a0cf5a8e49..d611e5e75ccd 100644 --- a/toolchain/check/handle_if_statement.cpp +++ b/toolchain/check/handle_if_statement.cpp @@ -52,7 +52,7 @@ auto HandleIfStatement(Context& context, Parse::IfStatementId node_id) -> bool { // block. auto else_block_id = context.node_stack().Pop(); - context.AddInst({node_id, SemIR::Branch{else_block_id}}); + context.AddInst(node_id, {.target_id = else_block_id}); context.inst_block_stack().Pop(); context.inst_block_stack().Push(else_block_id); break; diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index ddb4d452379f..fa73ef1cf2e5 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -208,8 +208,9 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id) // TODO: Does lookup in an impl file need to look for a prior impl declaration // in the api file? auto impl_id = context.impls().LookupOrAdd(self_type_id, constraint_type_id); - auto impl_decl = SemIR::ImplDecl{impl_id, decl_block_id}; - auto impl_decl_id = context.AddInst({node_id, impl_decl}); + SemIR::ImplDecl impl_decl = {.impl_id = impl_id, + .decl_block_id = decl_block_id}; + auto impl_decl_id = context.AddInst(node_id, impl_decl); // For an `extend impl` declaration, mark the impl as extending this `impl`. if (context.decl_state_stack().innermost().modifier_set.HasAnyOf( diff --git a/toolchain/check/handle_index.cpp b/toolchain/check/handle_index.cpp index 49e13718542f..b62d8ba9579a 100644 --- a/toolchain/check/handle_index.cpp +++ b/toolchain/check/handle_index.cpp @@ -52,14 +52,15 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool { if (array_cat == SemIR::ExprCategory::Value) { // If the operand is an array value, convert it to an ephemeral // reference to an array so we can perform a primitive indexing into it. - operand_inst_id = context.AddInst( - {node_id, SemIR::ValueAsRef{operand_type_id, operand_inst_id}}); + operand_inst_id = context.AddInst( + node_id, {.type_id = operand_type_id, .value_id = operand_inst_id}); } // Constant evaluation will perform a bounds check on this array indexing // if the index is constant. - auto elem_id = context.AddInst( - {node_id, SemIR::ArrayIndex{array_type.element_type_id, - operand_inst_id, cast_index_id}}); + auto elem_id = context.AddInst( + node_id, {.type_id = array_type.element_type_id, + .array_id = operand_inst_id, + .index_id = cast_index_id}); if (array_cat != SemIR::ExprCategory::DurableRef) { // Indexing a durable reference gives a durable reference expression. // Indexing anything else gives a value expression. @@ -97,9 +98,10 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool { index_inst_id = SemIR::InstId::BuiltinError; } } - context.AddInstAndPush( - {node_id, - SemIR::TupleIndex{element_type_id, operand_inst_id, index_inst_id}}); + context.AddInstAndPush(node_id, + {.type_id = element_type_id, + .tuple_id = operand_inst_id, + .index_id = index_inst_id}); return true; } default: { diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index 61aa1036ad5d..6b092a16112b 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -57,7 +57,7 @@ static auto BuildInterfaceDecl(Context& context, auto interface_decl = SemIR::InterfaceDecl{ SemIR::TypeId::TypeType, SemIR::InterfaceId::Invalid, decl_block_id}; auto interface_decl_id = - context.AddPlaceholderInst({node_id, interface_decl}); + context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, interface_decl)); // Check whether this is a redeclaration. auto existing_id = context.decl_name_stack().LookupOrAddName( diff --git a/toolchain/check/handle_literal.cpp b/toolchain/check/handle_literal.cpp index 5a1d822cfb87..2dd1d2a493d4 100644 --- a/toolchain/check/handle_literal.cpp +++ b/toolchain/check/handle_literal.cpp @@ -10,19 +10,17 @@ namespace Carbon::Check { auto HandleBoolLiteralFalse(Context& context, Parse::BoolLiteralFalseId node_id) -> bool { - context.AddInstAndPush( - {node_id, - SemIR::BoolLiteral{context.GetBuiltinType(SemIR::BuiltinKind::BoolType), - SemIR::BoolValue::False}}); + context.AddInstAndPush( + node_id, {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::BoolType), + .value = SemIR::BoolValue::False}); return true; } auto HandleBoolLiteralTrue(Context& context, Parse::BoolLiteralTrueId node_id) -> bool { - context.AddInstAndPush( - {node_id, - SemIR::BoolLiteral{context.GetBuiltinType(SemIR::BuiltinKind::BoolType), - SemIR::BoolValue::True}}); + context.AddInstAndPush( + node_id, {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::BoolType), + .value = SemIR::BoolValue::True}); return true; } @@ -41,10 +39,9 @@ static auto MakeI32Literal(Context& context, Parse::NodeId node_id, } // Literals are always represented as unsigned, so zero-extend if needed. auto i32_val = val.zextOrTrunc(32); - return context.AddInst( - {node_id, - SemIR::IntLiteral{context.GetBuiltinType(SemIR::BuiltinKind::IntType), - context.ints().Add(i32_val)}}); + return context.AddInst( + node_id, {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::IntType), + .int_id = context.ints().Add(i32_val)}); } auto HandleIntLiteral(Context& context, Parse::IntLiteralId node_id) -> bool { @@ -94,20 +91,20 @@ auto HandleRealLiteral(Context& context, Parse::RealLiteralId node_id) -> bool { real_value.exponent.getSExtValue()); auto float_id = context.sem_ir().floats().Add(llvm::APFloat(double_val)); - context.AddInstAndPush( - {node_id, - SemIR::FloatLiteral{ - context.GetBuiltinType(SemIR::BuiltinKind::FloatType), float_id}}); + context.AddInstAndPush( + node_id, + {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::FloatType), + .float_id = float_id}); return true; } auto HandleStringLiteral(Context& context, Parse::StringLiteralId node_id) -> bool { - context.AddInstAndPush( - {node_id, SemIR::StringLiteral{ - context.GetBuiltinType(SemIR::BuiltinKind::StringType), - context.tokens().GetStringLiteralValue( - context.parse_tree().node_token(node_id))}}); + context.AddInstAndPush( + node_id, + {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::StringType), + .string_literal_id = context.tokens().GetStringLiteralValue( + context.parse_tree().node_token(node_id))}); return true; } diff --git a/toolchain/check/handle_loop_statement.cpp b/toolchain/check/handle_loop_statement.cpp index 3bb56f632ca9..36574e77bf98 100644 --- a/toolchain/check/handle_loop_statement.cpp +++ b/toolchain/check/handle_loop_statement.cpp @@ -58,7 +58,7 @@ auto HandleWhileStatement(Context& context, Parse::WhileStatementId node_id) context.break_continue_stack().pop_back(); // Add the loop backedge. - context.AddInst({node_id, SemIR::Branch{loop_header_id}}); + context.AddInst(node_id, {.target_id = loop_header_id}); context.inst_block_stack().Pop(); // Start emitting the loop exit block. @@ -100,7 +100,8 @@ auto HandleBreakStatementStart(Context& context, "`break` can only be used in a loop."); context.emitter().Emit(node_id, BreakOutsideLoop); } else { - context.AddInst({node_id, SemIR::Branch{stack.back().break_target}}); + context.AddInst(node_id, + {.target_id = stack.back().break_target}); } context.inst_block_stack().Pop(); @@ -125,7 +126,8 @@ auto HandleContinueStatementStart(Context& context, "`continue` can only be used in a loop."); context.emitter().Emit(node_id, ContinueOutsideLoop); } else { - context.AddInst({node_id, SemIR::Branch{stack.back().continue_target}}); + context.AddInst(node_id, + {.target_id = stack.back().continue_target}); } context.inst_block_stack().Pop(); diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index cbe801d8eed6..3335de86c6d9 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -80,8 +80,9 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id, SemIR::NameId name_id) -> bool { auto value_id = context.LookupUnqualifiedName(node_id, name_id); auto value = context.insts().Get(value_id); - context.AddInstAndPush( - {node_id, SemIR::NameRef{value.type_id(), name_id, value_id}}); + context.AddInstAndPush( + node_id, + {.type_id = value.type_id(), .name_id = name_id, .value_id = value_id}); return true; } @@ -133,11 +134,11 @@ auto HandleNameQualifier(Context& context, Parse::NameQualifierId /*node_id*/) } auto HandlePackageExpr(Context& context, Parse::PackageExprId node_id) -> bool { - context.AddInstAndPush( - {node_id, - SemIR::NameRef{context.GetBuiltinType(SemIR::BuiltinKind::NamespaceType), - SemIR::NameId::PackageNamespace, - SemIR::InstId::PackageNamespace}}); + context.AddInstAndPush( + node_id, + {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::NamespaceType), + .name_id = SemIR::NameId::PackageNamespace, + .value_id = SemIR::InstId::PackageNamespace}); return true; } diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index 7d6d4e1218cd..5d7dcbddb36d 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -7,6 +7,7 @@ #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" namespace Carbon::Check { @@ -26,7 +27,8 @@ auto HandleNamespace(Context& context, Parse::NamespaceId node_id) -> bool { auto namespace_inst = SemIR::Namespace{ context.GetBuiltinType(SemIR::BuiltinKind::NamespaceType), SemIR::NameScopeId::Invalid, SemIR::InstId::Invalid}; - auto namespace_id = context.AddPlaceholderInst({node_id, namespace_inst}); + auto namespace_id = + context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, namespace_inst)); namespace_inst.name_scope_id = context.name_scopes().Add( namespace_id, name_context.name_id_for_new_inst(), name_context.enclosing_scope_id_for_new_inst()); diff --git a/toolchain/check/handle_operator.cpp b/toolchain/check/handle_operator.cpp index 7d5248533805..1a65a3e8a315 100644 --- a/toolchain/check/handle_operator.cpp +++ b/toolchain/check/handle_operator.cpp @@ -84,7 +84,7 @@ auto HandleInfixOperatorEqual(Context& context, // TODO: Destroy the old value before reinitializing. This will require // building the destruction code before we build the RHS subexpression. rhs_id = Initialize(context, node_id, lhs_id, rhs_id); - context.AddInst({node_id, SemIR::Assign{lhs_id, rhs_id}}); + context.AddInst(node_id, {.lhs_id = lhs_id, .rhs_id = rhs_id}); // We model assignment as an expression, so we need to push a value for // it, even though it doesn't produce a value. // TODO: Consider changing our parse tree to model assignment as a @@ -226,8 +226,9 @@ auto HandlePostfixOperatorStar(Context& context, Parse::PostfixOperatorStarId node_id) -> bool { auto value_id = context.node_stack().PopExpr(); auto inner_type_id = ExprAsType(context, node_id, value_id); - context.AddInstAndPush( - {node_id, SemIR::PointerType{SemIR::TypeId::TypeType, inner_type_id}}); + context.AddInstAndPush( + node_id, + {.type_id = SemIR::TypeId::TypeType, .pointee_id = inner_type_id}); return true; } @@ -253,8 +254,9 @@ auto HandlePrefixOperatorAmp(Context& context, value_id = SemIR::InstId::BuiltinError; break; } - context.AddInstAndPush( - {node_id, SemIR::AddrOf{context.GetPointerType(type_id), value_id}}); + context.AddInstAndPush( + node_id, SemIR::AddrOf{.type_id = context.GetPointerType(type_id), + .lvalue_id = value_id}); return true; } @@ -277,8 +279,8 @@ auto HandlePrefixOperatorConst(Context& context, context.emitter().Emit(node_id, RepeatedConst); } auto inner_type_id = ExprAsType(context, node_id, value_id); - context.AddInstAndPush( - {node_id, SemIR::ConstType{SemIR::TypeId::TypeType, inner_type_id}}); + context.AddInstAndPush( + node_id, {.type_id = SemIR::TypeId::TypeType, .inner_id = inner_type_id}); return true; } @@ -297,9 +299,9 @@ auto HandlePrefixOperatorNot(Context& context, Parse::PrefixOperatorNotId node_id) -> bool { auto value_id = context.node_stack().PopExpr(); value_id = ConvertToBoolValue(context, node_id, value_id); - context.AddInstAndPush( - {node_id, SemIR::UnaryOperatorNot{context.insts().Get(value_id).type_id(), - value_id}}); + context.AddInstAndPush( + node_id, {.type_id = context.insts().Get(value_id).type_id(), + .operand_id = value_id}); return true; } @@ -349,12 +351,13 @@ static auto HandleShortCircuitOperand(Context& context, Parse::NodeId node_id, // Compute the branch value: the condition for `and`, inverted for `or`. SemIR::InstId branch_value_id = - is_or ? context.AddInst({node_id, SemIR::UnaryOperatorNot{bool_type_id, - cond_value_id}}) - : cond_value_id; - auto short_circuit_result_id = context.AddInst( - {node_id, - SemIR::BoolLiteral{bool_type_id, SemIR::BoolValue::From(is_or)}}); + is_or + ? context.AddInst( + node_id, {.type_id = bool_type_id, .operand_id = cond_value_id}) + : cond_value_id; + auto short_circuit_result_id = context.AddInst( + node_id, + {.type_id = bool_type_id, .value = SemIR::BoolValue::From(is_or)}); // Create a block for the right-hand side and for the continuation. auto rhs_block_id = @@ -407,14 +410,15 @@ static auto HandleShortCircuitOperator(Context& context, Parse::NodeId node_id) // When the second operand is evaluated, the result of `and` and `or` is // its value. auto resume_block_id = context.inst_block_stack().PeekOrAdd(/*depth=*/1); - context.AddInst({node_id, SemIR::BranchWithArg{resume_block_id, rhs_id}}); + context.AddInst( + node_id, {.target_id = resume_block_id, .arg_id = rhs_id}); context.inst_block_stack().Pop(); context.AddCurrentCodeBlockToFunction(node_id); // Collect the result from either the first or second operand. - auto result_id = context.AddInst( - {node_id, SemIR::BlockArg{context.insts().Get(rhs_id).type_id(), - resume_block_id}}); + auto result_id = context.AddInst( + node_id, {.type_id = context.insts().Get(rhs_id).type_id(), + .block_id = resume_block_id}); context.SetBlockArgResultBeforeConstantUse(result_id, branch_value_id, rhs_id, short_circuit_result_id); context.node_stack().Push(node_id, result_id); diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 000415a1ad31..cd28630e7167 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -44,9 +44,11 @@ auto HandleStructField(Context& context, Parse::StructFieldId node_id) -> bool { auto [name_node, name_id] = context.node_stack().PopNameWithNodeId(); // Store the name for the type. - context.args_type_info_stack().AddInstId(context.AddInstInNoBlock( - {name_node, SemIR::StructTypeField{ - name_id, context.insts().Get(value_inst_id).type_id()}})); + 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()})); // Push the value back on the stack as an argument. context.node_stack().Push(node_id, value_inst_id); @@ -60,8 +62,8 @@ auto HandleStructTypeField(Context& context, Parse::StructTypeFieldId node_id) auto [name_node, name_id] = context.node_stack().PopNameWithNodeId(); - auto inst_id = context.AddInst( - {name_node, SemIR::StructTypeField{name_id, cast_type_id}}); + 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); return true; } @@ -109,8 +111,8 @@ auto HandleStructLiteral(Context& context, Parse::StructLiteralId node_id) auto type_id = context.GetStructType(type_block_id); - auto value_id = - context.AddInst({node_id, SemIR::StructLiteral{type_id, refs_id}}); + auto value_id = context.AddInst( + node_id, {.type_id = type_id, .elements_id = refs_id}); context.node_stack().Push(node_id, value_id); return true; } @@ -131,8 +133,8 @@ auto HandleStructTypeLiteral(Context& context, context.node_stack().Push(node_id, SemIR::InstId::BuiltinError); return true; } - context.AddInstAndPush( - {node_id, SemIR::StructType{SemIR::TypeId::TypeType, refs_id}}); + context.AddInstAndPush( + node_id, {.type_id = SemIR::TypeId::TypeType, .fields_id = refs_id}); return true; } diff --git a/toolchain/check/handle_tuple_literal.cpp b/toolchain/check/handle_tuple_literal.cpp index 6d2b231dcb7e..3082aa2811ac 100644 --- a/toolchain/check/handle_tuple_literal.cpp +++ b/toolchain/check/handle_tuple_literal.cpp @@ -34,8 +34,8 @@ auto HandleTupleLiteral(Context& context, Parse::TupleLiteralId node_id) } auto type_id = context.GetTupleType(type_ids); - auto value_id = - context.AddInst({node_id, SemIR::TupleLiteral{type_id, refs_id}}); + auto value_id = context.AddInst( + node_id, {.type_id = type_id, .elements_id = refs_id}); context.node_stack().Push(node_id, value_id); return true; } diff --git a/toolchain/check/handle_variable.cpp b/toolchain/check/handle_variable.cpp index 25188508b624..e8f092dce470 100644 --- a/toolchain/check/handle_variable.cpp +++ b/toolchain/check/handle_variable.cpp @@ -84,7 +84,8 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id) init_id = Initialize(context, node_id, value_id, *init_id); // TODO: Consider using different instruction kinds for assignment versus // initialization. - context.AddInst({node_id, SemIR::Assign{value_id, *init_id}}); + context.AddInst(node_id, + {.lhs_id = value_id, .rhs_id = *init_id}); } if (context.scope_stack().PeekIndex() == ScopeIndex::Package) { context.inst_block_stack().PopGlobalInit(); diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 94ff97d2044a..1425c4c289d7 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -138,8 +138,9 @@ static auto BuildInterfaceWitness( } auto table_id = context.inst_blocks().Add(table); - return context.AddInst(SemIR::LocIdAndInst::NoLoc(SemIR::InterfaceWitness{ - context.GetBuiltinType(SemIR::BuiltinKind::WitnessType), table_id})); + return context.AddInst(SemIR::LocIdAndInst::NoLoc( + {.type_id = context.GetBuiltinType(SemIR::BuiltinKind::WitnessType), + .elements_id = table_id})); } auto BuildImplWitness(Context& context, SemIR::ImplId impl_id) diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 1ea767221fee..43380721452f 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -103,7 +103,8 @@ static auto AddNamespace( auto namespace_inst = SemIR::Namespace{ namespace_type_id, SemIR::NameScopeId::Invalid, import_id}; // Use the invalid node because there's no node to associate with. - auto namespace_id = context.AddPlaceholderInst({node_id, namespace_inst}); + auto namespace_id = + context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, namespace_inst)); namespace_inst.name_scope_id = context.name_scopes().Add(namespace_id, name_id, enclosing_scope_id); context.ReplaceInstBeforeConstantUse(namespace_id, namespace_inst); @@ -147,11 +148,10 @@ static auto CopySingleNameScopeFromImportIR( .bind_index = SemIR::CompileTimeBindIndex::Invalid}); auto import_ir_inst_id = context.import_ir_insts().Add( {.ir_id = ir_id, .inst_id = import_inst_id}); - return context.AddInst( - {import_ir_inst_id, - SemIR::ImportRefLoaded{.type_id = namespace_type_id, - .import_ir_inst_id = import_ir_inst_id, - .bind_name_id = bind_name_id}}); + return context.AddInst( + import_ir_inst_id, {.type_id = namespace_type_id, + .import_ir_inst_id = import_ir_inst_id, + .bind_name_id = bind_name_id}); }; auto [namespace_scope_id, namespace_const_id, _] = AddNamespace(context, namespace_type_id, Parse::NodeId::Invalid, name_id, diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 308408cb5b97..08e257b7705f 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -56,10 +56,10 @@ auto AddImportIR(Context& context, SemIR::ImportIR import_ir) auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst, SemIR::BindNameId bind_name_id) -> SemIR::InstId { auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst); + SemIR::ImportRefUnloaded inst = {.import_ir_inst_id = import_ir_inst_id, + .bind_name_id = bind_name_id}; auto import_ref_id = context.AddPlaceholderInstInNoBlock( - {import_ir_inst_id, - SemIR::ImportRefUnloaded{.import_ir_inst_id = import_ir_inst_id, - .bind_name_id = bind_name_id}}); + SemIR::LocIdAndInst(import_ir_inst_id, inst)); // We can't insert this instruction into whatever block we happen to be in, // because this function is typically called by name lookup in the middle of @@ -438,8 +438,8 @@ class ImportRefResolver { auto name_id = GetLocalNameId(param_inst.name_id); auto type_id = context_.GetTypeIdForTypeConstant(const_id); - auto new_param_id = context_.AddInstInNoBlock( - {AddImportIRInst(param_id), SemIR::Param{type_id, name_id}}); + auto new_param_id = context_.AddInstInNoBlock( + AddImportIRInst(param_id), {.type_id = type_id, .name_id = name_id}); if (bind_inst) { switch (bind_inst->kind) { case SemIR::BindName::Kind: { @@ -447,9 +447,10 @@ class ImportRefResolver { {.name_id = name_id, .enclosing_scope_id = SemIR::NameScopeId::Invalid, .bind_index = SemIR::CompileTimeBindIndex::Invalid}); - new_param_id = context_.AddInstInNoBlock( - {AddImportIRInst(bind_id), - SemIR::BindName{type_id, bind_name_id, new_param_id}}); + new_param_id = context_.AddInstInNoBlock( + AddImportIRInst(bind_id), {.type_id = type_id, + .bind_name_id = bind_name_id, + .value_id = new_param_id}); break; } case SemIR::BindSymbolicName::Kind: { @@ -473,9 +474,9 @@ class ImportRefResolver { } } if (addr_inst) { - new_param_id = context_.AddInstInNoBlock( - {AddImportIRInst(ref_id), - SemIR::AddrPattern{type_id, new_param_id}}); + new_param_id = context_.AddInstInNoBlock( + AddImportIRInst(ref_id), + {.type_id = type_id, .inner_id = new_param_id}); } new_param_refs.push_back(new_param_id); } @@ -669,11 +670,11 @@ class ImportRefResolver { context_, {.ir_id = import_ir_id_, .inst_id = inst.decl_id}, SemIR::BindNameId::Invalid); - auto inst_id = context_.AddInstInNoBlock( - {AddImportIRInst(inst.decl_id), - SemIR::AssociatedEntity{ - context_.GetTypeIdForTypeConstant(type_const_id), inst.index, - decl_id}}); + auto inst_id = context_.AddInstInNoBlock( + AddImportIRInst(inst.decl_id), + {.type_id = context_.GetTypeIdForTypeConstant(type_const_id), + .index = inst.index, + .decl_id = decl_id}); return {context_.constant_values().Get(inst_id)}; } @@ -709,11 +710,11 @@ class ImportRefResolver { } // Import the instruction in order to update contained base_type_id. - auto inst_id = context_.AddInstInNoBlock( - {AddImportIRInst(import_inst_id), - SemIR::BaseDecl{context_.GetTypeIdForTypeConstant(type_const_id), - context_.GetTypeIdForTypeConstant(base_type_const_id), - inst.index}}); + auto inst_id = context_.AddInstInNoBlock( + AddImportIRInst(import_inst_id), + {.type_id = context_.GetTypeIdForTypeConstant(type_const_id), + .base_type_id = context_.GetTypeIdForTypeConstant(base_type_const_id), + .index = inst.index}); return {context_.constant_values().Get(inst_id)}; } @@ -741,10 +742,11 @@ class ImportRefResolver { {.name_id = name_id, .enclosing_scope_id = SemIR::NameScopeId::Invalid, .bind_index = import_bind_info.bind_index}); - auto new_bind_id = context_.AddInstInNoBlock( - {AddImportIRInst(import_inst_id), - SemIR::BindSymbolicName{context_.GetTypeIdForTypeConstant(type_id), - bind_name_id, SemIR::InstId::Invalid}}); + auto new_bind_id = context_.AddInstInNoBlock( + AddImportIRInst(import_inst_id), + {.type_id = context_.GetTypeIdForTypeConstant(type_id), + .bind_name_id = bind_name_id, + .value_id = SemIR::InstId::Invalid}); return {context_.constant_values().Get(new_bind_id)}; } @@ -757,7 +759,7 @@ class ImportRefResolver { SemIR::ClassDecl{SemIR::TypeId::TypeType, SemIR::ClassId::Invalid, SemIR::InstBlockId::Empty}; auto class_decl_id = context_.AddPlaceholderInstInNoBlock( - {AddImportIRInst(import_class.decl_id), class_decl}); + SemIR::LocIdAndInst(AddImportIRInst(import_class.decl_id), class_decl)); // Regardless of whether ClassDecl is a complete type, we first need an // incomplete type so that any references have something to point at. class_decl.class_id = context_.classes().Add({ @@ -929,10 +931,11 @@ class ImportRefResolver { if (HasNewWork(initial_work)) { return ResolveResult::Retry(); } - auto inst_id = context_.AddInstInNoBlock( - {AddImportIRInst(import_inst_id), - SemIR::FieldDecl{context_.GetTypeIdForTypeConstant(const_id), - GetLocalNameId(inst.name_id), inst.index}}); + auto inst_id = context_.AddInstInNoBlock( + AddImportIRInst(import_inst_id), + {.type_id = context_.GetTypeIdForTypeConstant(const_id), + .name_id = GetLocalNameId(inst.name_id), + .index = inst.index}); return {context_.constant_values().Get(inst_id)}; } @@ -963,7 +966,7 @@ class ImportRefResolver { ? function.definition_id : function.decl_id); auto function_decl_id = context_.AddPlaceholderInstInNoBlock( - {import_ir_inst_id, function_decl}); + SemIR::LocIdAndInst(import_ir_inst_id, function_decl)); auto new_return_type_id = return_type_const_id.is_valid() @@ -974,9 +977,10 @@ class ImportRefResolver { // Recreate the return slot from scratch. // TODO: Once we import function definitions, we'll need to make sure we // use the same return storage variable in the declaration and definition. - new_return_storage = context_.AddInstInNoBlock( - {AddImportIRInst(function.return_storage_id), - SemIR::VarStorage{new_return_type_id, SemIR::NameId::ReturnSlot}}); + new_return_storage = context_.AddInstInNoBlock( + AddImportIRInst(function.return_storage_id), + {.type_id = new_return_type_id, + .name_id = SemIR::NameId::ReturnSlot}); } function_decl.function_id = context_.functions().Add( {.name_id = GetLocalNameId(function.name_id), @@ -1056,8 +1060,9 @@ class ImportRefResolver { auto interface_decl = SemIR::InterfaceDecl{SemIR::TypeId::TypeType, SemIR::InterfaceId::Invalid, SemIR::InstBlockId::Empty}; - auto interface_decl_id = context_.AddPlaceholderInstInNoBlock( - {AddImportIRInst(import_interface.decl_id), interface_decl}); + auto interface_decl_id = + context_.AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst( + AddImportIRInst(import_interface.decl_id), interface_decl)); // Start with an incomplete interface. SemIR::Interface new_interface = { @@ -1207,10 +1212,9 @@ class ImportRefResolver { auto field = import_ir_.insts().GetAs(field_id); auto name_id = GetLocalNameId(field.name_id); auto field_type_id = context_.GetTypeIdForTypeConstant(field_const_id); - fields.push_back(context_.AddInstInNoBlock( - {AddImportIRInst(import_inst_id), - SemIR::StructTypeField{.name_id = name_id, - .field_type_id = field_type_id}})); + fields.push_back(context_.AddInstInNoBlock( + AddImportIRInst(import_inst_id), + {.name_id = name_id, .field_type_id = field_type_id})); } return {context_.types().GetConstantId( diff --git a/toolchain/check/interface.cpp b/toolchain/check/interface.cpp index 410113207bbc..38b049965c19 100644 --- a/toolchain/check/interface.cpp +++ b/toolchain/check/interface.cpp @@ -30,8 +30,9 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id, // not the declaration itself. auto type_id = context.GetAssociatedEntityType( interface_id, context.insts().Get(decl_id).type_id()); - return context.AddInst({context.insts().GetLocId(decl_id), - SemIR::AssociatedEntity{type_id, index, decl_id}}); + return context.AddInst( + context.insts().GetLocId(decl_id), + {.type_id = type_id, .index = index, .decl_id = decl_id}); } } // namespace Carbon::Check diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 02718a92f841..8aa3e77f11d2 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -197,8 +197,10 @@ static auto PerformImplLookup(Context& context, Parse::NodeId node_id, SubstType(context, assoc_type.entity_type_id, substitutions); return context.AddInst( - SemIR::LocIdAndInst::NoLoc(SemIR::InterfaceWitnessAccess{ - subst_type_id, witness_id, assoc_entity->index})); + SemIR::LocIdAndInst::NoLoc( + {.type_id = subst_type_id, + .witness_id = witness_id, + .index = assoc_entity->index})); } // Performs a member name lookup into the specified scope, including performing @@ -216,8 +218,9 @@ static auto LookupMemberNameInScope(Context& context, Parse::NodeId node_id, auto inst = context.insts().Get(inst_id); // TODO: Use a different kind of instruction that also references the // `base_id` so that `SemIR` consumers can find it. - auto member_id = context.AddInst( - {node_id, SemIR::NameRef{inst.type_id(), name_id, inst_id}}); + auto member_id = context.AddInst( + node_id, + {.type_id = inst.type_id(), .name_id = name_id, .value_id = inst_id}); // If member name lookup finds an associated entity name, and the scope is not // a facet type, perform impl lookup. @@ -256,9 +259,10 @@ static auto PerformInstanceBinding(Context& context, Parse::NodeId node_id, << "Non-constant value " << context.insts().Get(member_id) << " of unbound element type"; auto index = GetClassElementIndex(context, element_id.inst_id()); - auto access_id = context.AddInst( - {node_id, SemIR::ClassElementAccess{ - unbound_element_type.element_type_id, base_id, index}}); + auto access_id = context.AddInst( + node_id, {.type_id = unbound_element_type.element_type_id, + .base_id = base_id, + .index = index}); if (SemIR::GetExprCategory(context.sem_ir(), base_id) == SemIR::ExprCategory::Value && SemIR::GetExprCategory(context.sem_ir(), access_id) != @@ -274,11 +278,11 @@ static auto PerformInstanceBinding(Context& context, Parse::NodeId node_id, } case CARBON_KIND(SemIR::FunctionType fn_type): { if (IsInstanceMethod(context.sem_ir(), fn_type.function_id)) { - return context.AddInst( - {node_id, - SemIR::BoundMethod{ - context.GetBuiltinType(SemIR::BuiltinKind::BoundMethodType), - base_id, member_id}}); + return context.AddInst( + node_id, {.type_id = context.GetBuiltinType( + SemIR::BuiltinKind::BoundMethodType), + .object_id = base_id, + .function_id = member_id}); } [[fallthrough]]; } @@ -331,9 +335,10 @@ auto PerformMemberAccess(Context& context, Parse::NodeId node_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.AddInst( - {node_id, SemIR::StructAccess{field.field_type_id, base_id, - SemIR::ElementIndex(i)}}); + return context.AddInst( + node_id, {.type_id = field.field_type_id, + .struct_id = base_id, + .index = SemIR::ElementIndex(i)}); } } CARBON_DIAGNOSTIC(QualifiedExprNameNotFound, Error, diff --git a/toolchain/check/pending_block.h b/toolchain/check/pending_block.h index a99ceae6f341..9f7c3a9f1ad6 100644 --- a/toolchain/check/pending_block.h +++ b/toolchain/check/pending_block.h @@ -39,8 +39,9 @@ class PendingBlock { size_t size_; }; - auto AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId { - auto inst_id = context_.AddInstInNoBlock(loc_id_and_inst); + template + auto AddInst(SemIR::LocId loc_id, InstT inst) -> SemIR::InstId { + auto inst_id = context_.AddInstInNoBlock(loc_id, inst); insts_.push_back(inst_id); return inst_id; } diff --git a/toolchain/check/pointer_dereference.cpp b/toolchain/check/pointer_dereference.cpp index e8371e17c14d..1087094f3fb6 100644 --- a/toolchain/check/pointer_dereference.cpp +++ b/toolchain/check/pointer_dereference.cpp @@ -30,7 +30,8 @@ auto PerformPointerDereference( } else if (type_id != SemIR::TypeId::Error) { diagnose_not_pointer(type_id); } - return context.AddInst({node_id, SemIR::Deref{result_type_id, base_id}}); + return context.AddInst( + node_id, {.type_id = result_type_id, .pointer_id = base_id}); } } // namespace Carbon::Check diff --git a/toolchain/check/return.cpp b/toolchain/check/return.cpp index 4abfc08b46b6..4145c45cf87e 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -84,7 +84,8 @@ auto CheckReturnedVar(Context& context, Parse::NodeId returned_node, if (function.has_return_slot()) { return function.return_storage_id; } - return context.AddInst({name_node, SemIR::VarStorage{type_id, name_id}}); + return context.AddInst( + name_node, {.type_id = type_id, .name_id = name_id}); } auto RegisterReturnedVar(Context& context, SemIR::InstId bind_id) -> void { @@ -111,7 +112,7 @@ auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id) diag.Emit(); } - context.AddInst({node_id, SemIR::Return{}}); + context.AddInst(node_id, {}); } auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, @@ -147,7 +148,8 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, function.return_type_id); } - context.AddInst({node_id, SemIR::ReturnExpr{expr_id, return_slot_id}}); + context.AddInst( + node_id, {.expr_id = expr_id, .dest_id = return_slot_id}); } auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id) @@ -170,8 +172,8 @@ auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id) return_slot_id = SemIR::InstId::Invalid; } - context.AddInst( - {node_id, SemIR::ReturnExpr{returned_var_id, return_slot_id}}); + context.AddInst( + node_id, {.expr_id = returned_var_id, .dest_id = return_slot_id}); } } // namespace Carbon::Check diff --git a/toolchain/sem_ir/inst.h b/toolchain/sem_ir/inst.h index 64b14ff75262..72b6d9ed7958 100644 --- a/toolchain/sem_ir/inst.h +++ b/toolchain/sem_ir/inst.h @@ -301,15 +301,12 @@ inline auto operator<<(llvm::raw_ostream& out, TypedInst inst) // Associates a LocId and Inst in order to provide type-checking that the // TypedNodeId corresponds to the InstT. struct LocIdAndInst { - // For cases with no location. template - requires(!Internal::HasNodeId) static auto NoLoc(InstT inst) -> LocIdAndInst { return LocIdAndInst(LocId::Invalid, inst, /*is_untyped=*/true); } - // For the common case, support construction as: - // context.AddInst({node_id, SemIR::MyInst{...}}); + // Construction for the common case with a typed node. template requires(Internal::HasNodeId) LocIdAndInst(decltype(InstT::Kind)::TypedNodeId node_id, InstT inst) @@ -327,7 +324,6 @@ struct LocIdAndInst { template LocIdAndInst(ImportIRInstId import_ir_inst_id, InstT inst) : loc_id(import_ir_inst_id), inst(inst) {} - LocId loc_id; Inst inst; @@ -335,6 +331,7 @@ struct LocIdAndInst { // Expose the internal constructor for GetWithLocId. friend class InstStore; + // Note `is_untyped` serves to disambiguate from public constructors. explicit LocIdAndInst(LocId loc_id, Inst inst, bool /*is_untyped*/) : loc_id(loc_id), inst(inst) {} };