From 5bb318cae6d64beb6802f7047ca2190ae7206f70 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 31 May 2024 15:49:44 -0700 Subject: [PATCH] Switch AddInst struct init style. (#4012) Trying to conform with #4009. Changes SemIR::LocIdAndInst construction to root out struct init cases with AddInst and related functions. I'm using templating of AddInst functions in order to avoid `AddInst(loc_id, InstName{...})` and instead have `AddInst(loc_id, {...})` with I think similar readability results. There are a couple cases where inst construction is templated and so designated initializers couldn't be used, so this may be better for those in particular due to the extra type enforcement. This probably doesn't clean up every last case, but I was trying to get the bulk at once without bleeding over into less related changes. --------- Co-authored-by: Richard Smith --- toolchain/check/call.cpp | 17 +-- toolchain/check/check.cpp | 8 +- toolchain/check/context.cpp | 17 ++- toolchain/check/context.h | 19 ++- toolchain/check/convert.cpp | 136 +++++++++++---------- toolchain/check/handle_alias.cpp | 24 ++-- toolchain/check/handle_array.cpp | 9 +- toolchain/check/handle_binding_pattern.cpp | 43 ++++--- toolchain/check/handle_class.cpp | 32 ++--- toolchain/check/handle_export.cpp | 8 +- toolchain/check/handle_function.cpp | 9 +- toolchain/check/handle_if_statement.cpp | 2 +- toolchain/check/handle_impl.cpp | 5 +- toolchain/check/handle_index.cpp | 18 +-- toolchain/check/handle_interface.cpp | 2 +- toolchain/check/handle_literal.cpp | 39 +++--- toolchain/check/handle_loop_statement.cpp | 8 +- toolchain/check/handle_name.cpp | 15 +-- toolchain/check/handle_namespace.cpp | 4 +- toolchain/check/handle_operator.cpp | 44 ++++--- toolchain/check/handle_struct.cpp | 20 +-- toolchain/check/handle_tuple_literal.cpp | 4 +- toolchain/check/handle_variable.cpp | 3 +- toolchain/check/impl.cpp | 5 +- toolchain/check/import.cpp | 12 +- toolchain/check/import_ref.cpp | 84 +++++++------ toolchain/check/interface.cpp | 5 +- toolchain/check/member_access.cpp | 35 +++--- toolchain/check/pending_block.h | 5 +- toolchain/check/pointer_dereference.cpp | 3 +- toolchain/check/return.cpp | 12 +- toolchain/sem_ir/inst.h | 7 +- 32 files changed, 361 insertions(+), 293 deletions(-) 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) {} };