From 311b4ff03d33b38c01be6fdc94fd363a0c257928 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 14 Feb 2025 11:44:36 -0800 Subject: [PATCH] Refactor AddInst-family functions to their own file (#4941) This in particular uses free functions because it's likely to end up more consistent with types (versus a wrapper object for InstStore). Note, this is unlikely to have a performance impact, but if it does, we can look into related approaches (and we've already discussed using LTO). Renames `PendingBlock::AddInst` to `PendingBlock::Add` because `MakeElementAccessInst` expects the matching name to exist. --- toolchain/check/BUILD | 2 + toolchain/check/call.cpp | 25 +-- toolchain/check/check_unit.cpp | 28 +-- toolchain/check/context.cpp | 116 ------------- toolchain/check/context.h | 136 +-------------- toolchain/check/control_flow.cpp | 13 +- toolchain/check/convert.cpp | 187 +++++++++++---------- toolchain/check/global_init.cpp | 3 +- toolchain/check/handle_alias.cpp | 9 +- toolchain/check/handle_array.cpp | 9 +- toolchain/check/handle_binding_pattern.cpp | 59 ++++--- toolchain/check/handle_class.cpp | 44 ++--- toolchain/check/handle_export.cpp | 10 +- toolchain/check/handle_function.cpp | 21 +-- toolchain/check/handle_if_statement.cpp | 3 +- toolchain/check/handle_impl.cpp | 13 +- toolchain/check/handle_index.cpp | 15 +- toolchain/check/handle_interface.cpp | 13 +- toolchain/check/handle_let_and_var.cpp | 20 ++- toolchain/check/handle_literal.cpp | 22 +-- toolchain/check/handle_loop_statement.cpp | 11 +- toolchain/check/handle_name.cpp | 26 +-- toolchain/check/handle_namespace.cpp | 7 +- toolchain/check/handle_operator.cpp | 52 +++--- toolchain/check/handle_struct.cpp | 9 +- toolchain/check/handle_tuple_literal.cpp | 5 +- toolchain/check/handle_where.cpp | 33 ++-- toolchain/check/impl.cpp | 4 +- toolchain/check/import.cpp | 20 ++- toolchain/check/import_cpp.cpp | 5 +- toolchain/check/import_ref.cpp | 178 +++++++++++++------- toolchain/check/import_ref.h | 24 +++ toolchain/check/inst.cpp | 136 +++++++++++++++ toolchain/check/inst.h | 120 +++++++++++++ toolchain/check/interface.cpp | 5 +- toolchain/check/literal.cpp | 9 +- toolchain/check/member_access.cpp | 72 ++++---- toolchain/check/pattern_match.cpp | 48 +++--- toolchain/check/pending_block.h | 13 +- toolchain/check/pointer_dereference.cpp | 5 +- toolchain/check/return.cpp | 12 +- toolchain/check/subpattern.cpp | 7 +- toolchain/check/type_completion.cpp | 13 +- toolchain/docs/adding_features.md | 8 +- 44 files changed, 875 insertions(+), 695 deletions(-) create mode 100644 toolchain/check/inst.cpp create mode 100644 toolchain/check/inst.h diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 5baa617b34c5..f07994f3e7c3 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -29,6 +29,7 @@ cc_library( "import.cpp", "import_cpp.cpp", "import_ref.cpp", + "inst.cpp", "inst_block_stack.cpp", "interface.cpp", "literal.cpp", @@ -62,6 +63,7 @@ cc_library( "import.h", "import_cpp.h", "import_ref.h", + "inst.h", "inst_block_stack.h", "interface.h", "keyword_modifier_set.h", diff --git a/toolchain/check/call.cpp b/toolchain/check/call.cpp index 2f8cd71a6616..5916c4ddc5a2 100644 --- a/toolchain/check/call.cpp +++ b/toolchain/check/call.cpp @@ -98,10 +98,11 @@ static auto PerformCallToGenericClass(Context& context, SemIR::LocId loc_id, if (!callee_specific_id) { return SemIR::ErrorInst::SingletonInstId; } - return context.GetOrAddInst( - loc_id, {.type_id = SemIR::TypeType::SingletonTypeId, - .class_id = class_id, - .specific_id = *callee_specific_id}); + return GetOrAddInst( + context, loc_id, + {.type_id = SemIR::TypeType::SingletonTypeId, + .class_id = class_id, + .specific_id = *callee_specific_id}); } // Performs a call where the callee is the name of a generic interface, such as @@ -119,8 +120,8 @@ static auto PerformCallToGenericInterface( if (!callee_specific_id) { return SemIR::ErrorInst::SingletonInstId; } - return context.GetOrAddInst( - loc_id, + return GetOrAddInst( + context, loc_id, FacetTypeFromInterface(context, interface_id, *callee_specific_id)); } @@ -163,8 +164,8 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id, return SemIR::ErrorInst::SingletonInstId; } if (callee_specific_id->has_value()) { - callee_id = context.GetOrAddInst( - context.insts().GetLocId(callee_id), + callee_id = GetOrAddInst( + context, context.insts().GetLocId(callee_id), SemIR::SpecificFunction{ .type_id = GetSingletonType( context, SemIR::SpecificFunctionType::SingletonInstId), @@ -196,8 +197,8 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id, case SemIR::InitRepr::InPlace: // Tentatively put storage for a temporary in the function's return slot. // This will be replaced if necessary when we perform initialization. - return_slot_arg_id = context.AddInst( - loc_id, {.type_id = return_info.type_id}); + return_slot_arg_id = AddInst( + context, loc_id, {.type_id = return_info.type_id}); break; case SemIR::InitRepr::None: // For functions with an implicit return type, the return type is the @@ -220,8 +221,8 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id, context, loc_id, callee_function.self_id, arg_ids, return_slot_arg_id, context.functions().Get(callee_function.function_id), *callee_specific_id); - auto call_inst_id = - context.GetOrAddInst(loc_id, {.type_id = return_info.type_id, + auto call_inst_id = GetOrAddInst(context, loc_id, + {.type_id = return_info.type_id, .callee_id = callee_id, .args_id = converted_args_id}); diff --git a/toolchain/check/check_unit.cpp b/toolchain/check/check_unit.cpp index 2d3f10c8f328..a191139c54f8 100644 --- a/toolchain/check/check_unit.cpp +++ b/toolchain/check/check_unit.cpp @@ -17,6 +17,7 @@ #include "toolchain/check/import.h" #include "toolchain/check/import_cpp.h" #include "toolchain/check/import_ref.h" +#include "toolchain/check/inst.h" #include "toolchain/check/node_id_traversal.h" #include "toolchain/check/type.h" @@ -102,18 +103,19 @@ auto CheckUnit::InitPackageScopeAndImports() -> void { SemIR::NameScopeId::None); CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package); - auto package_inst_id = context_.AddInst( - Parse::NodeId::None, {.type_id = namespace_type_id, - .name_scope_id = SemIR::NameScopeId::Package, - .import_id = SemIR::InstId::None}); + auto package_inst_id = + AddInst(context_, Parse::NodeId::None, + {.type_id = namespace_type_id, + .name_scope_id = SemIR::NameScopeId::Package, + .import_id = SemIR::InstId::None}); CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId); // If there is an implicit `api` import, set it first so that it uses the // ImportIRId::ApiForImpl when processed for imports. if (unit_and_imports_->api_for_impl) { const auto& names = context_.parse_tree().packaging_decl()->names; - auto import_decl_id = context_.AddInst( - names.node_id, + auto import_decl_id = AddInst( + context_, names.node_id, {.package_id = SemIR::NameId::ForPackageName(names.package_id)}); SetApiImportIR(context_, {.decl_id = import_decl_id, @@ -128,9 +130,10 @@ auto CheckUnit::InitPackageScopeAndImports() -> void { // are handled separately. for (auto& package_imports : unit_and_imports_->package_imports) { CARBON_CHECK(!package_imports.import_decl_id.has_value()); - package_imports.import_decl_id = context_.AddInst( - package_imports.node_id, {.package_id = SemIR::NameId::ForPackageName( - package_imports.package_id)}); + package_imports.import_decl_id = AddInst( + context_, package_imports.node_id, + {.package_id = + SemIR::NameId::ForPackageName(package_imports.package_id)}); } // Process the imports. if (unit_and_imports_->api_for_impl) { @@ -327,9 +330,10 @@ auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void { {.ir_id = SemIR::ImportIRId::ApiForImpl, .inst_id = api_imports->import_decl_id}); import_decl_id = - context_.AddInst(context_.MakeImportedLocAndInst( - import_ir_inst_id, {.package_id = SemIR::NameId::ForPackageName( - api_imports_entry.first)})); + AddInst(context_, MakeImportedLocIdAndInst( + context_, import_ir_inst_id, + {.package_id = SemIR::NameId::ForPackageName( + api_imports_entry.first)})); package_id = api_imports_entry.first; } has_load_error |= api_imports->has_load_error; diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 15d0f4cf12d1..607954a3bed2 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -98,122 +98,6 @@ auto Context::VerifyOnFinish() -> void { // TODO: Add verification for generic_region_stack_. } -auto Context::GetOrAddInst(SemIR::LocIdAndInst loc_id_and_inst) - -> SemIR::InstId { - if (loc_id_and_inst.loc_id.is_implicit()) { - auto const_id = - TryEvalInst(*this, SemIR::InstId::None, loc_id_and_inst.inst); - if (const_id.has_value()) { - CARBON_VLOG("GetOrAddInst: constant: {0}\n", loc_id_and_inst.inst); - return constant_values().GetInstId(const_id); - } - } - // TODO: For an implicit instruction, this reattempts evaluation. - return AddInst(loc_id_and_inst); -} - -// Finish producing an instruction. Set its constant value, and register it in -// any applicable instruction lists. -auto Context::FinishInst(SemIR::InstId inst_id, SemIR::Inst inst) -> void { - GenericRegionStack::DependencyKind dep_kind = - GenericRegionStack::DependencyKind::None; - - // If the instruction has a symbolic constant type, track that we need to - // substitute into it. - if (constant_values().DependsOnGenericParameter( - types().GetConstantId(inst.type_id()))) { - dep_kind |= GenericRegionStack::DependencyKind::SymbolicType; - } - - // If the instruction has a constant value, compute it. - auto const_id = TryEvalInst(*this, inst_id, inst); - constant_values().Set(inst_id, const_id); - if (const_id.is_constant()) { - CARBON_VLOG("Constant: {0} -> {1}\n", inst, - constant_values().GetInstId(const_id)); - - // If the constant value is symbolic, track that we need to substitute into - // it. - if (constant_values().DependsOnGenericParameter(const_id)) { - dep_kind |= GenericRegionStack::DependencyKind::SymbolicConstant; - } - } - - // Keep track of dependent instructions. - if (dep_kind != GenericRegionStack::DependencyKind::None) { - // TODO: Also check for template-dependent instructions. - generic_region_stack().AddDependentInst( - {.inst_id = inst_id, .kind = dep_kind}); - } -} - -// Returns whether a parse node associated with an imported instruction of kind -// `imported_kind` is usable as the location of a corresponding local -// instruction of kind `local_kind`. -static auto HasCompatibleImportedNodeKind(SemIR::InstKind imported_kind, - SemIR::InstKind local_kind) -> bool { - if (imported_kind == local_kind) { - return true; - } - if (imported_kind == SemIR::ImportDecl::Kind && - local_kind == SemIR::Namespace::Kind) { - static_assert( - std::is_convertible_v); - return true; - } - return false; -} - -auto Context::CheckCompatibleImportedNodeKind( - SemIR::ImportIRInstId imported_loc_id, SemIR::InstKind kind) -> void { - auto& import_ir_inst = import_ir_insts().Get(imported_loc_id); - const auto* import_ir = import_irs().Get(import_ir_inst.ir_id).sem_ir; - auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id).kind(); - CARBON_CHECK( - HasCompatibleImportedNodeKind(imported_kind, kind), - "Node of kind {0} created with location of imported node of kind {1}", - kind, imported_kind); -} - -auto Context::AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst) - -> SemIR::InstId { - auto inst_id = sem_ir().insts().AddInNoBlock(loc_id_and_inst); - CARBON_VLOG("AddPlaceholderInst: {0}\n", loc_id_and_inst.inst); - constant_values().Set(inst_id, SemIR::ConstantId::None); - return inst_id; -} - -auto Context::AddPlaceholderInst(SemIR::LocIdAndInst loc_id_and_inst) - -> SemIR::InstId { - auto inst_id = AddPlaceholderInstInNoBlock(loc_id_and_inst); - inst_block_stack_.AddInstId(inst_id); - return 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); - CARBON_VLOG("ReplaceInst: {0} -> {1}\n", inst_id, loc_id_and_inst.inst); - FinishInst(inst_id, loc_id_and_inst.inst); -} - -auto Context::ReplaceInstBeforeConstantUse(SemIR::InstId inst_id, - SemIR::Inst inst) -> void { - sem_ir().insts().Set(inst_id, inst); - CARBON_VLOG("ReplaceInst: {0} -> {1}\n", inst_id, inst); - FinishInst(inst_id, inst); -} - -auto Context::ReplaceInstPreservingConstantValue(SemIR::InstId inst_id, - SemIR::Inst inst) -> void { - auto old_const_id = sem_ir().constant_values().Get(inst_id); - sem_ir().insts().Set(inst_id, inst); - CARBON_VLOG("ReplaceInst: {0} -> {1}\n", inst_id, inst); - auto new_const_id = TryEvalInst(*this, inst_id, inst); - CARBON_CHECK(old_const_id == new_const_id); -} - auto Context::Finalize() -> void { // Pop information for the file-level scope. sem_ir().set_top_inst_block_id(inst_block_stack().Pop()); diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 21a5f4ed957f..233edc7235b7 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -55,129 +55,6 @@ class Context { // Runs verification that the processing cleanly finished. auto VerifyOnFinish() -> void; - // Adds an instruction to the current block, returning the produced ID. - auto AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId { - auto inst_id = AddInstInNoBlock(loc_id_and_inst); - inst_block_stack_.AddInstId(inst_id); - return inst_id; - } - - // Convenience for AddInst with typed nodes. - template - auto AddInst(LocT loc, InstT inst) - -> decltype(AddInst(SemIR::LocIdAndInst(loc, inst))) { - return AddInst(SemIR::LocIdAndInst(loc, inst)); - } - - // Returns a LocIdAndInst for an instruction with an imported location. Checks - // that the imported location is compatible with the kind of instruction being - // created. - template - requires SemIR::Internal::HasNodeId - auto MakeImportedLocAndInst(SemIR::ImportIRInstId imported_loc_id, InstT inst) - -> SemIR::LocIdAndInst { - if constexpr (!SemIR::Internal::HasUntypedNodeId) { - CheckCompatibleImportedNodeKind(imported_loc_id, InstT::Kind); - } - return SemIR::LocIdAndInst::UncheckedLoc(imported_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 { - auto inst_id = sem_ir().insts().AddInNoBlock(loc_id_and_inst); - CARBON_VLOG("AddInst: {0}\n", loc_id_and_inst.inst); - FinishInst(inst_id, loc_id_and_inst.inst); - return inst_id; - } - - // Convenience for AddInstInNoBlock with typed nodes. - template - auto AddInstInNoBlock(LocT loc, InstT inst) - -> decltype(AddInstInNoBlock(SemIR::LocIdAndInst(loc, inst))) { - return AddInstInNoBlock(SemIR::LocIdAndInst(loc, inst)); - } - - // If the instruction has an implicit location and a constant value, returns - // the constant value's instruction ID. Otherwise, same as AddInst. - auto GetOrAddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; - - // Convenience for GetOrAddInst with typed nodes. - template - auto GetOrAddInst(LocT loc, InstT inst) - -> decltype(GetOrAddInst(SemIR::LocIdAndInst(loc, inst))) { - return GetOrAddInst(SemIR::LocIdAndInst(loc, 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`. - auto AddPlaceholderInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; - - // Adds an instruction in no block, returning the produced ID. Should be used - // rarely. The instruction is a placeholder that is expected to be replaced by - // `ReplaceInstBeforeConstantUse`. - auto AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst) - -> SemIR::InstId; - - // Adds an instruction to the current pattern block, returning the produced - // ID. - // TODO: Is it possible to remove this and pattern_block_stack, now that - // we have BeginSubpattern etc. instead? - auto AddPatternInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId { - auto inst_id = AddInstInNoBlock(loc_id_and_inst); - pattern_block_stack_.AddInstId(inst_id); - return inst_id; - } - - // Convenience for AddPatternInst with typed nodes. - template - requires(SemIR::Internal::HasNodeId) - auto AddPatternInst(decltype(InstT::Kind)::TypedNodeId node_id, InstT inst) - -> SemIR::InstId { - return AddPatternInst(SemIR::LocIdAndInst(node_id, inst)); - } - - // Pushes a parse tree node onto the stack, storing the SemIR::Inst as the - // result. - template - requires(SemIR::Internal::HasNodeId) - auto AddInstAndPush(decltype(InstT::Kind)::TypedNodeId node_id, InstT inst) - -> void { - node_stack_.Push(node_id, AddInst(node_id, inst)); - } - - // Replaces the instruction at `inst_id` with `loc_id_and_inst`. The - // instruction is required to not have been used in any constant evaluation, - // either because it's newly created and entirely unused, or because it's only - // used in a position that constant evaluation ignores, such as a return slot. - auto ReplaceLocIdAndInstBeforeConstantUse(SemIR::InstId inst_id, - SemIR::LocIdAndInst loc_id_and_inst) - -> void; - - // Replaces the instruction at `inst_id` with `inst`, not affecting location. - // The instruction is required to not have been used in any constant - // evaluation, either because it's newly created and entirely unused, or - // because it's only used in a position that constant evaluation ignores, such - // as a return slot. - auto ReplaceInstBeforeConstantUse(SemIR::InstId inst_id, SemIR::Inst inst) - -> void; - - // Replaces the instruction at `inst_id` with `inst`, not affecting location. - // The instruction is required to not change its constant value. - auto ReplaceInstPreservingConstantValue(SemIR::InstId inst_id, - SemIR::Inst inst) -> void; - - // Sets only the parse node of an instruction. This is only used when setting - // the parse node of an imported namespace. Versus - // ReplaceInstBeforeConstantUse, it is safe to use after the namespace is used - // in constant evaluation. It's exposed this way mainly so that `insts()` can - // remain const. - auto SetNamespaceNodeId(SemIR::InstId inst_id, Parse::NodeId node_id) - -> void { - sem_ir().insts().SetLocId(inst_id, SemIR::LocId(node_id)); - } - // Adds an exported name. auto AddExport(SemIR::InstId inst_id) -> void { exports_.push_back(inst_id); } @@ -313,8 +190,8 @@ class Context { auto type_blocks() -> SemIR::BlockValueStore& { return sem_ir().type_blocks(); } - // Instructions should be added with `AddInst` or `AddInstInNoBlock`. This is - // `const` to prevent accidental misuse. + // Instructions should be added with `AddInst` or `AddInstInNoBlock` from + // `inst.h`. This is `const` to prevent accidental misuse. auto insts() -> const SemIR::InstStore& { return sem_ir().insts(); } auto constant_values() -> SemIR::ConstantValueStore& { return sem_ir().constant_values(); @@ -373,15 +250,6 @@ class Context { SemIR::TypeId type_id_; }; - // Checks that the provided imported location has a node kind that is - // compatible with that of the given instruction. - auto CheckCompatibleImportedNodeKind(SemIR::ImportIRInstId imported_loc_id, - SemIR::InstKind kind) -> void; - - // Finish producing an instruction. Set its constant value, and register it in - // any applicable instruction lists. - auto FinishInst(SemIR::InstId inst_id, SemIR::Inst inst) -> void; - // Handles diagnostics. DiagnosticEmitter* emitter_; diff --git a/toolchain/check/control_flow.cpp b/toolchain/check/control_flow.cpp index c0ccbfbafffa..fddc62505385 100644 --- a/toolchain/check/control_flow.cpp +++ b/toolchain/check/control_flow.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/control_flow.h" +#include "toolchain/check/inst.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -16,7 +17,7 @@ static auto AddDominatedBlockAndBranchImpl(Context& context, return SemIR::InstBlockId::Unreachable; } auto block_id = context.inst_blocks().AddDefaultValue(); - context.AddInst(node_id, {block_id, args...}); + AddInst(context, node_id, {block_id, args...}); return block_id; } @@ -49,7 +50,7 @@ auto AddConvergenceBlockAndPush(Context& context, Parse::NodeId node_id, new_block_id = context.inst_blocks().AddDefaultValue(); } CARBON_CHECK(node_id.has_value()); - context.AddInst(node_id, {.target_id = new_block_id}); + AddInst(context, node_id, {.target_id = new_block_id}); } context.inst_block_stack().Pop(); } @@ -68,8 +69,8 @@ auto AddConvergenceBlockWithArgAndPush( if (new_block_id == SemIR::InstBlockId::Unreachable) { new_block_id = context.inst_blocks().AddDefaultValue(); } - context.AddInst( - node_id, {.target_id = new_block_id, .arg_id = arg_id}); + AddInst( + context, node_id, {.target_id = new_block_id, .arg_id = arg_id}); } context.inst_block_stack().Pop(); } @@ -79,8 +80,8 @@ auto AddConvergenceBlockWithArgAndPush( // Acquire the result value. SemIR::TypeId result_type_id = context.insts().Get(*block_args.begin()).type_id(); - return context.AddInst( - node_id, {.type_id = result_type_id, .block_id = new_block_id}); + return AddInst( + context, node_id, {.type_id = result_type_id, .block_id = new_block_id}); } auto SetBlockArgResultBeforeConstantUse(Context& context, diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 060375ef6fee..4367769b5b3f 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -14,6 +14,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/impl_lookup.h" +#include "toolchain/check/inst.h" #include "toolchain/check/operator.h" #include "toolchain/check/pattern_match.h" #include "toolchain/check/type.h" @@ -114,10 +115,10 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id, "initialized multiple times? Have {0}", sem_ir.insts().Get(return_slot_arg_id)); auto init = sem_ir.insts().Get(init_id); - return context.AddInst(sem_ir.insts().GetLocId(init_id), - {.type_id = init.type_id(), - .storage_id = return_slot_arg_id, - .init_id = init_id}); + return AddInst(context, sem_ir.insts().GetLocId(init_id), + {.type_id = init.type_id(), + .storage_id = return_slot_arg_id, + .init_id = init_id}); } if (discarded) { @@ -131,11 +132,12 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id, // initialize a temporary, rather than two separate 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, {.type_id = init.type_id()}); - return context.AddInst(loc_id, {.type_id = init.type_id(), - .storage_id = temporary_id, - .init_id = init_id}); + auto temporary_id = AddInst( + context, loc_id, {.type_id = init.type_id()}); + return AddInst(context, 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 @@ -149,12 +151,20 @@ static auto MaterializeIfInitializing(Context& context, SemIR::InstId expr_id) return expr_id; } +// Helper to allow `MakeElementAccessInst` to call `AddInst` with either a +// `PendingBlock` or `Context` (defined in `inst.h`). +template +static auto AddInst(PendingBlock& block, SemIR::LocId loc_id, AccessInstT inst) + -> SemIR::InstId { + return block.AddInst(loc_id, inst); +} + // Creates and adds an instruction to perform element access into an aggregate. template static auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id, SemIR::InstId aggregate_id, SemIR::TypeId elem_type_id, InstBlockT& block, - size_t i) { + size_t i) -> SemIR::InstId { if constexpr (std::is_same_v) { // 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 @@ -163,11 +173,11 @@ static auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id, loc_id, {.type_id = GetSingletonType( context, SemIR::IntLiteralType::SingletonInstId), .int_id = context.ints().Add(static_cast(i))}); - return block.template AddInst( - loc_id, {elem_type_id, aggregate_id, index_id}); + return AddInst(block, loc_id, + {elem_type_id, aggregate_id, index_id}); } else { - return block.template AddInst( - loc_id, {elem_type_id, aggregate_id, SemIR::ElementIndex(i)}); + return AddInst( + block, loc_id, {elem_type_id, aggregate_id, SemIR::ElementIndex(i)}); } } @@ -191,7 +201,7 @@ static auto ConvertAggregateElement( llvm::ArrayRef src_literal_elems, ConversionTarget::Kind kind, SemIR::InstId target_id, SemIR::TypeId target_elem_type, PendingBlock* target_block, - size_t src_field_index, size_t target_field_index) { + size_t src_field_index, size_t target_field_index) -> SemIR::InstId { // Compute the location of the source element. This goes into the current code // block, not into the target block. // TODO: Ideally we would discard this instruction if it's unused. @@ -303,10 +313,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, {.type_id = target.type_id, - .inits_id = sem_ir.inst_blocks().Add(inits), - .dest_id = return_slot_arg_id}); + return AddInst(context, value_loc_id, + {.type_id = target.type_id, + .inits_id = sem_ir.inst_blocks().Add(inits), + .dest_id = return_slot_arg_id}); } // Performs a conversion from a tuple to a tuple type. This function only @@ -383,13 +393,13 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type, if (is_init) { target.init_block->InsertHere(); - return context.AddInst(value_loc_id, - {.type_id = target.type_id, - .elements_id = new_block.id(), - .dest_id = target.init_id}); + return AddInst(context, 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, + return AddInst( + context, value_loc_id, {.type_id = target.type_id, .elements_id = new_block.id()}); } } @@ -478,16 +488,18 @@ static auto ConvertStructToStructOrClass(Context& context, for (auto [i, dest_field] : llvm::enumerate(dest_elem_fields)) { if (dest_field.name_id == SemIR::NameId::Vptr) { // CARBON_CHECK(ToClass, "Only classes should have vptrs."); - auto dest_id = context.AddInst( - value_loc_id, {.type_id = dest_field.type_id, - .base_id = target.init_id, - .index = SemIR::ElementIndex(i)}); - auto vtable_ptr_id = context.AddInst( - value_loc_id, {.type_id = dest_field.type_id}); - auto init_id = context.AddInst( - value_loc_id, {.type_id = dest_field.type_id, - .src_id = vtable_ptr_id, - .dest_id = dest_id}); + auto dest_id = + AddInst(context, value_loc_id, + {.type_id = dest_field.type_id, + .base_id = target.init_id, + .index = SemIR::ElementIndex(i)}); + auto vtable_ptr_id = AddInst( + context, value_loc_id, {.type_id = dest_field.type_id}); + auto init_id = + AddInst(context, value_loc_id, + {.type_id = dest_field.type_id, + .src_id = vtable_ptr_id, + .dest_id = dest_id}); new_block.Set(i, init_id); continue; } @@ -536,19 +548,19 @@ 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, - {.type_id = target.type_id, - .elements_id = new_block.id(), - .dest_id = target.init_id}); + return AddInst(context, 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, - {.type_id = target.type_id, - .elements_id = new_block.id(), - .dest_id = target.init_id}); + return AddInst(context, 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, + return AddInst( + context, value_loc_id, {.type_id = target.type_id, .elements_id = new_block.id()}); } } @@ -597,10 +609,11 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type, if (need_temporary) { target_block.InsertHere(); - result_id = context.AddInst( - context.insts().GetLocId(value_id), {.type_id = target.type_id, - .storage_id = target.init_id, - .init_id = result_id}); + result_id = + AddInst(context, context.insts().GetLocId(value_id), + {.type_id = target.type_id, + .storage_id = target.init_id, + .init_id = result_id}); } return result_id; } @@ -657,10 +670,10 @@ static auto ConvertDerivedToBase(Context& context, SemIR::LocId loc_id, // Add a series of `.base` accesses. for (auto [base_id, base_type_id] : path) { auto base_decl = context.insts().GetAs(base_id); - value_id = context.AddInst( - loc_id, {.type_id = base_type_id, - .base_id = value_id, - .index = base_decl.index}); + value_id = AddInst(context, loc_id, + {.type_id = base_type_id, + .base_id = value_id, + .index = base_decl.index}); } return value_id; } @@ -672,15 +685,16 @@ static auto ConvertDerivedPointerToBasePointer( const InheritancePath& path) -> SemIR::InstId { // Form `*p`. ptr_id = ConvertToValueExpr(context, ptr_id); - auto ref_id = context.AddInst( - loc_id, {.type_id = src_ptr_type.pointee_id, .pointer_id = ptr_id}); + auto ref_id = AddInst( + context, 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, {.type_id = dest_ptr_type_id, .lvalue_id = ref_id}); + return AddInst( + context, loc_id, {.type_id = dest_ptr_type_id, .lvalue_id = ref_id}); } // Returns whether `category` is a valid expression category to produce as a @@ -801,8 +815,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, // value right out of it. if (value_cat == SemIR::ExprCategory::Initializing && CanUseValueOfInitializer(sem_ir, value_type_id, target.kind)) { - return context.AddInst( - loc_id, {.type_id = value_type_id, .init_id = value_id}); + return AddInst( + context, loc_id, {.type_id = value_type_id, .init_id = value_id}); } // PerformBuiltinConversion converts each part of a tuple or struct, even @@ -825,8 +839,9 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, foundation_type_id != value_type_id && (context.types().Is(foundation_type_id) || context.types().Is(foundation_type_id))) { - auto foundation_value_id = context.AddInst( - loc_id, {.type_id = foundation_type_id, .source_id = value_id}); + auto foundation_value_id = AddInst( + context, loc_id, + {.type_id = foundation_type_id, .source_id = value_id}); auto foundation_init_id = target.init_id; if (foundation_init_id != SemIR::InstId::None) { @@ -858,8 +873,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, } } - return context.AddInst( - loc_id, + return AddInst( + context, loc_id, {.type_id = target.type_id, .source_id = foundation_value_id}); } } @@ -880,8 +895,8 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, ConversionTarget{.kind = ConversionTarget::Value, .type_id = value_type_id}); } - return context.AddInst( - loc_id, {.type_id = target.type_id, .source_id = value_id}); + return AddInst( + context, loc_id, {.type_id = target.type_id, .source_id = value_id}); } } @@ -986,8 +1001,9 @@ 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, {.type_id = target.type_id, .facet_value_inst_id = value_id}); + return AddInst( + context, loc_id, + {.type_id = target.type_id, .facet_value_inst_id = value_id}); } } @@ -1040,12 +1056,13 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, context.constant_values().Get(lookup_inst_id), context.types().GetConstantId(target.type_id)); if (witness_inst_id != SemIR::InstId::None) { - return context.AddInst( - loc_id, { - .type_id = target.type_id, - .type_inst_id = lookup_inst_id, - .witness_inst_id = witness_inst_id, - }); + return AddInst( + context, loc_id, + { + .type_id = target.type_id, + .type_inst_id = lookup_inst_id, + .witness_inst_id = witness_inst_id, + }); } } } @@ -1168,17 +1185,17 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, // Pull a value directly out of the initializer if possible and wanted. if (expr_id != SemIR::ErrorInst::SingletonInstId && CanUseValueOfInitializer(sem_ir, target.type_id, target.kind)) { - expr_id = context.AddInst( - loc_id, {.type_id = target.type_id, .init_id = expr_id}); + expr_id = AddInst( + context, loc_id, {.type_id = target.type_id, .init_id = 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, {.type_id = target.type_id, - .original_id = orig_expr_id, - .result_id = expr_id}); + expr_id = AddInst(context, 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 @@ -1228,8 +1245,8 @@ 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), + expr_id = AddInst( + context, context.insts().GetLocId(expr_id), {.type_id = target.type_id, .value_id = expr_id}); // We now have a value expression. [[fallthrough]]; @@ -1247,10 +1264,10 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, if (auto init_rep = SemIR::InitRepr::ForType(sem_ir, target.type_id); init_rep.kind == SemIR::InitRepr::ByCopy) { target.init_block->InsertHere(); - expr_id = context.AddInst( - loc_id, {.type_id = target.type_id, - .src_id = expr_id, - .dest_id = target.init_id}); + expr_id = AddInst(context, loc_id, + {.type_id = target.type_id, + .src_id = expr_id, + .dest_id = target.init_id}); } } diff --git a/toolchain/check/global_init.cpp b/toolchain/check/global_init.cpp index 3639a122b1c4..a85a36f98190 100644 --- a/toolchain/check/global_init.cpp +++ b/toolchain/check/global_init.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/global_init.h" #include "toolchain/check/context.h" +#include "toolchain/check/inst.h" namespace Carbon::Check { @@ -29,7 +30,7 @@ auto GlobalInit::Finalize() -> void { } Resume(); - context_->AddInst(Parse::NodeId::None, {}); + AddInst(*context_, Parse::NodeId::None, {}); // Pop the GlobalInit block here to finalize it. context_->inst_block_stack().Pop(); diff --git a/toolchain/check/handle_alias.cpp b/toolchain/check/handle_alias.cpp index a611234157c2..20d2cca90a65 100644 --- a/toolchain/check/handle_alias.cpp +++ b/toolchain/check/handle_alias.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" #include "toolchain/parse/node_ids.h" @@ -58,10 +59,10 @@ auto HandleParseNode(Context& context, Parse::AliasId /*node_id*/) -> bool { alias_type_id = SemIR::ErrorInst::SingletonTypeId; alias_value_id = SemIR::ErrorInst::SingletonInstId; } - auto alias_id = context.AddInst( - name_context.loc_id, {.type_id = alias_type_id, - .entity_name_id = entity_name_id, - .value_id = alias_value_id}); + auto alias_id = AddInst(context, name_context.loc_id, + {.type_id = alias_type_id, + .entity_name_id = entity_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 56b3bafe3c5b..943334cd46af 100644 --- a/toolchain/check/handle_array.cpp +++ b/toolchain/check/handle_array.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" #include "toolchain/parse/node_kind.h" @@ -53,10 +54,10 @@ auto HandleParseNode(Context& context, Parse::ArrayExprId node_id) -> bool { bound_inst_id = ConvertToValueOfType( context, context.insts().GetLocId(bound_inst_id), bound_inst_id, GetSingletonType(context, SemIR::IntLiteralType::SingletonInstId)); - context.AddInstAndPush( - node_id, {.type_id = SemIR::TypeType::SingletonTypeId, - .bound_id = bound_inst_id, - .element_type_id = element_type_id}); + AddInstAndPush(context, node_id, + {.type_id = SemIR::TypeType::SingletonTypeId, + .bound_id = bound_inst_id, + .element_type_id = element_type_id}); return true; } diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 77014076b7db..f4c53ad8e8c0 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/interface.h" #include "toolchain/check/name_lookup.h" #include "toolchain/check/return.h" @@ -54,21 +55,24 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, : SemIR::CompileTimeBindIndex::None, is_template); if (is_generic) { - bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst( - name_node, SemIR::BindSymbolicName{.type_id = cast_type_id, + bind_id = AddInstInNoBlock( + context, + SemIR::LocIdAndInst(name_node, SemIR::BindSymbolicName{ + .type_id = cast_type_id, .entity_name_id = entity_name_id, .value_id = SemIR::InstId::None})); - binding_pattern_id = - context.AddPatternInst( - name_node, - {.type_id = cast_type_id, .entity_name_id = entity_name_id}); + binding_pattern_id = AddPatternInst( + context, name_node, + {.type_id = cast_type_id, .entity_name_id = entity_name_id}); } else { - bind_id = context.AddInstInNoBlock(SemIR::LocIdAndInst( - name_node, SemIR::BindName{.type_id = cast_type_id, - .entity_name_id = entity_name_id, - .value_id = SemIR::InstId::None})); - binding_pattern_id = context.AddPatternInst( - name_node, + bind_id = AddInstInNoBlock( + context, + SemIR::LocIdAndInst( + name_node, SemIR::BindName{.type_id = cast_type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None})); + binding_pattern_id = AddPatternInst( + context, name_node, {.type_id = cast_type_id, .entity_name_id = entity_name_id}); } @@ -126,10 +130,11 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, auto& class_info = context.classes().Get(parent_class_decl->class_id); auto field_type_id = GetUnboundElementType(context, class_info.self_type_id, cast_type_id); - auto field_id = context.AddInst( - binding_id, {.type_id = field_type_id, - .name_id = name_id, - .index = SemIR::ElementIndex::None}); + auto field_id = + AddInst(context, binding_id, + {.type_id = field_type_id, + .name_id = name_id, + .index = SemIR::ElementIndex::None}); context.field_decls_stack().AppendToTop(field_id); context.node_stack().Push(node_id, field_id); @@ -163,16 +168,19 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, .type_id = cast_type_id, .assoc_const_id = SemIR::AssociatedConstantId::None, .decl_block_id = SemIR::InstBlockId::None}; - auto decl_id = context.AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst( - context.parse_tree().As(node_id), - assoc_const_decl)); + auto decl_id = AddPlaceholderInstInNoBlock( + context, + SemIR::LocIdAndInst( + context.parse_tree().As( + node_id), + assoc_const_decl)); assoc_const_decl.assoc_const_id = context.associated_constants().Add( {.name_id = name_id, .parent_scope_id = context.scope_stack().PeekNameScopeId(), .decl_id = decl_id, .generic_id = SemIR::GenericId::None, .default_value_id = SemIR::InstId::None}); - context.ReplaceInstBeforeConstantUse(decl_id, assoc_const_decl); + ReplaceInstBeforeConstantUse(context, decl_id, assoc_const_decl); context.node_stack().Push(node_id, decl_id); return true; @@ -228,8 +236,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, param_pattern_id = SemIR::ErrorInst::SingletonInstId; } else { auto pattern_inst_id = make_binding_pattern(); - param_pattern_id = context.AddPatternInst( - node_id, + param_pattern_id = AddPatternInst( + context, node_id, { .type_id = context.insts().Get(pattern_inst_id).type_id(), .subpattern_id = pattern_inst_id, @@ -332,9 +340,10 @@ auto HandleParseNode(Context& context, Parse::AddrId node_id) -> bool { auto pointer_type = context.types().TryGetAs( context.insts().Get(param_pattern_id).type_id()); if (pointer_type) { - auto addr_pattern_id = context.AddPatternInst( - node_id, {.type_id = SemIR::AutoType::SingletonTypeId, - .inner_id = param_pattern_id}); + auto addr_pattern_id = AddPatternInst( + context, node_id, + {.type_id = SemIR::AutoType::SingletonTypeId, + .inner_id = param_pattern_id}); context.node_stack().Push(node_id, addr_pattern_id); } else { CARBON_DIAGNOSTIC( diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 9728dbf07133..e3c459a0ff42 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -12,6 +12,7 @@ #include "toolchain/check/handle.h" #include "toolchain/check/import.h" #include "toolchain/check/import_ref.h" +#include "toolchain/check/inst.h" #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" @@ -221,7 +222,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, .class_id = SemIR::ClassId::None, .decl_block_id = decl_block_id}; auto class_decl_id = - context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, class_decl)); + AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, class_decl)); // TODO: Store state regarding is_extern. SemIR::Class class_info = { @@ -252,7 +253,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, } // Write the class ID into the ClassDecl. - context.ReplaceInstBeforeConstantUse(class_decl_id, class_decl); + ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl); if (is_new_class) { // Build the `Self` type using the resulting type constant. @@ -416,8 +417,8 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { } // Build a SemIR representation for the declaration. - class_info.adapt_id = context.AddInst( - node_id, {.adapted_type_inst_id = adapted_inst_id}); + class_info.adapt_id = AddInst( + context, node_id, {.adapted_type_inst_id = adapted_inst_id}); // Extend the class scope with the adapted type's scope if requested. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { @@ -546,10 +547,11 @@ auto HandleParseNode(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 = GetUnboundElementType(context, class_info.self_type_id, base_info.type_id); - class_info.base_id = context.AddInst( - node_id, {.type_id = field_type_id, - .base_type_inst_id = base_info.inst_id, - .index = SemIR::ElementIndex::None}); + class_info.base_id = + AddInst(context, node_id, + {.type_id = field_type_id, + .base_type_inst_id = base_info.inst_id, + .index = SemIR::ElementIndex::None}); if (base_info.type_id != SemIR::ErrorInst::SingletonTypeId) { auto base_class_info = context.classes().Get( @@ -629,10 +631,11 @@ static auto CheckCompleteAdapterClassType(Context& context, class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::None); auto object_repr_id = context.types().GetObjectRepr(adapted_type_id); - return context.AddInst( - node_id, {.type_id = GetSingletonType( - context, SemIR::WitnessType::SingletonInstId), - .object_repr_id = object_repr_id}); + return AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::WitnessType::SingletonInstId), + .object_repr_id = object_repr_id}); } static auto AddStructTypeFields( @@ -643,7 +646,7 @@ static auto AddStructTypeFields( auto field_decl = context.insts().GetAs(field_decl_id); field_decl.index = SemIR::ElementIndex{static_cast(struct_type_fields.size())}; - context.ReplaceInstPreservingConstantValue(field_decl_id, field_decl); + ReplaceInstPreservingConstantValue(context, field_decl_id, field_decl); if (field_decl.type_id == SemIR::ErrorInst::SingletonTypeId) { struct_type_fields.push_back( {.name_id = field_decl.name_id, @@ -699,7 +702,7 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id, auto base_decl = context.insts().GetAs(class_info.base_id); base_decl.index = SemIR::ElementIndex{static_cast(struct_type_fields.size())}; - context.ReplaceInstPreservingConstantValue(class_info.base_id, base_decl); + ReplaceInstPreservingConstantValue(context, class_info.base_id, base_decl); struct_type_fields.push_back( {.name_id = SemIR::NameId::Base, .type_id = base_type_id}); } @@ -747,14 +750,15 @@ static auto CheckCompleteClassType(Context& context, Parse::NodeId node_id, vtable.push_back(inst_id); } } - class_info.vtable_id = context.AddInst( - node_id, {.type_id = GetSingletonType( - context, SemIR::VtableType::SingletonInstId), - .virtual_functions_id = context.inst_blocks().Add(vtable)}); + class_info.vtable_id = AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::VtableType::SingletonInstId), + .virtual_functions_id = context.inst_blocks().Add(vtable)}); } - return context.AddInst( - node_id, + return AddInst( + context, node_id, {.type_id = GetSingletonType(context, SemIR::WitnessType::SingletonInstId), .object_repr_id = GetStructType( diff --git a/toolchain/check/handle_export.cpp b/toolchain/check/handle_export.cpp index 2a3afaa7b413..1a11e3900361 100644 --- a/toolchain/check/handle_export.cpp +++ b/toolchain/check/handle_export.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/decl_name_stack.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" #include "toolchain/check/name_lookup.h" @@ -69,10 +70,11 @@ auto HandleParseNode(Context& context, Parse::ExportDeclId node_id) -> bool { return true; } - auto export_id = context.AddInst( - node_id, {.type_id = import_ref->type_id, - .entity_name_id = import_ref->entity_name_id, - .value_id = inst_id}); + auto export_id = + AddInst(context, node_id, + {.type_id = import_ref->type_id, + .entity_name_id = import_ref->entity_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 a0df7396e90c..4f95754d637d 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -13,6 +13,7 @@ #include "toolchain/check/handle.h" #include "toolchain/check/import.h" #include "toolchain/check/import_ref.h" +#include "toolchain/check/inst.h" #include "toolchain/check/interface.h" #include "toolchain/check/literal.h" #include "toolchain/check/merge.h" @@ -62,13 +63,13 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool { FullPatternStack::Kind::ExplicitParamList); } - auto return_slot_pattern_id = - context.AddPatternInst( - node_id, {.type_id = type_id, .type_inst_id = type_inst_id}); - auto param_pattern_id = context.AddPatternInst( - node_id, {.type_id = type_id, - .subpattern_id = return_slot_pattern_id, - .runtime_index = SemIR::RuntimeParamIndex::Unknown}); + auto return_slot_pattern_id = AddPatternInst( + context, node_id, {.type_id = type_id, .type_inst_id = type_inst_id}); + auto param_pattern_id = AddPatternInst( + context, node_id, + {.type_id = type_id, + .subpattern_id = return_slot_pattern_id, + .runtime_index = SemIR::RuntimeParamIndex::Unknown}); context.node_stack().Push(node_id, param_pattern_id); return true; } @@ -258,7 +259,7 @@ static auto BuildFunctionDecl(Context& context, auto function_decl = SemIR::FunctionDecl{ SemIR::TypeId::None, SemIR::FunctionId::None, decl_block_id}; auto decl_id = - context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, function_decl)); + AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, function_decl)); // Find self parameter pattern. // TODO: Do this during initial traversal of implicit params. @@ -316,7 +317,7 @@ static auto BuildFunctionDecl(Context& context, context.scope_stack().PeekSpecificId()); // Write the function ID into the FunctionDecl. - context.ReplaceInstBeforeConstantUse(decl_id, function_decl); + ReplaceInstBeforeConstantUse(context, decl_id, function_decl); // Diagnose 'definition of `abstract` function' using the canonical Function's // modifiers. @@ -478,7 +479,7 @@ auto HandleParseNode(Context& context, Parse::FunctionDefinitionId node_id) "missing `return` at end of function with declared return type"); context.emitter().Emit(TokenOnly(node_id), MissingReturnStatement); } else { - context.AddInst(node_id, {}); + AddInst(context, node_id, {}); } } diff --git a/toolchain/check/handle_if_statement.cpp b/toolchain/check/handle_if_statement.cpp index bef6e4de5acb..534107189747 100644 --- a/toolchain/check/handle_if_statement.cpp +++ b/toolchain/check/handle_if_statement.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" namespace Carbon::Check { @@ -54,7 +55,7 @@ auto HandleParseNode(Context& context, Parse::IfStatementId node_id) -> bool { // block. auto else_block_id = context.node_stack().Pop(); - context.AddInst(node_id, {.target_id = else_block_id}); + AddInst(context, node_id, {.target_id = else_block_id}); context.inst_block_stack().Pop(); context.inst_block_stack().Push(else_block_id); context.region_stack().AddToRegion(else_block_id, node_id); diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index e2fc2c51f8f7..8b17c621af4f 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -8,6 +8,7 @@ #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" #include "toolchain/check/impl.h" +#include "toolchain/check/inst.h" #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_lookup.h" @@ -107,8 +108,8 @@ auto HandleParseNode(Context& context, Parse::DefaultSelfImplAsId node_id) // is a class and found its `Self`, so additionally performing an unqualified // name lookup would be redundant work, but would avoid duplicating the // handling of the `Self` expression. - auto self_inst_id = context.AddInst( - node_id, + auto self_inst_id = AddInst( + context, node_id, SemIR::NameRef{.type_id = SemIR::TypeType::SingletonTypeId, .name_id = SemIR::NameId::SelfType, .value_id = context.types().GetInstId(self_type_id)}); @@ -342,7 +343,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None, .decl_block_id = decl_block_id}; auto impl_decl_id = - context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, impl_decl)); + AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, impl_decl)); SemIR::Impl impl_info = { name_context.MakeEntityWithParamsBase(name, impl_decl_id, @@ -383,15 +384,15 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, } // Write the impl ID into the ImplDecl. - context.ReplaceInstBeforeConstantUse(impl_decl_id, impl_decl); + ReplaceInstBeforeConstantUse(context, impl_decl_id, impl_decl); // For an `extend impl` declaration, mark the impl as extending this `impl`. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { auto extend_node = introducer.modifier_node_id(ModifierOrder::Decl); if (impl_info.generic_id.has_value()) { SemIR::TypeId type_id = context.insts().Get(constraint_inst_id).type_id(); - constraint_inst_id = context.AddInst( - context.insts().GetLocId(constraint_inst_id), + constraint_inst_id = AddInst( + context, context.insts().GetLocId(constraint_inst_id), {.type_id = type_id, .inst_id = constraint_inst_id, .specific_id = diff --git a/toolchain/check/handle_index.cpp b/toolchain/check/handle_index.cpp index 8e495098c475..5f5bb51e6cde 100644 --- a/toolchain/check/handle_index.cpp +++ b/toolchain/check/handle_index.cpp @@ -8,6 +8,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/literal.h" #include "toolchain/check/name_lookup.h" #include "toolchain/check/operator.h" @@ -145,15 +146,17 @@ auto HandleParseNode(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, {.type_id = operand_type_id, .value_id = operand_inst_id}); + operand_inst_id = AddInst( + context, 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, {.type_id = array_type.element_type_id, - .array_id = operand_inst_id, - .index_id = cast_index_id}); + auto elem_id = + AddInst(context, 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. diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index b105eb3f5c6c..f1e6db9aaab8 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/eval.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/merge.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" @@ -54,7 +55,7 @@ static auto BuildInterfaceDecl(Context& context, SemIR::InterfaceDecl{SemIR::TypeType::SingletonTypeId, SemIR::InterfaceId::None, decl_block_id}; auto interface_decl_id = - context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, interface_decl)); + AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, interface_decl)); SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase( name, interface_decl_id, /*is_extern=*/false, @@ -128,7 +129,7 @@ static auto BuildInterfaceDecl(Context& context, } // Write the interface ID into the InterfaceDecl. - context.ReplaceInstBeforeConstantUse(interface_decl_id, interface_decl); + ReplaceInstBeforeConstantUse(context, interface_decl_id, interface_decl); return {interface_decl.interface_id, interface_decl_id}; } @@ -177,10 +178,10 @@ auto HandleParseNode(Context& context, context.scope_stack().AddCompileTimeBinding(), /*is_template=*/false); interface_info.self_param_id = - context.AddInst(SemIR::LocIdAndInst::NoLoc( - {.type_id = self_type_id, - .entity_name_id = entity_name_id, - .value_id = SemIR::InstId::None})); + AddInst(context, SemIR::LocIdAndInst::NoLoc( + {.type_id = self_type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None})); context.scope_stack().PushCompileTimeBinding(interface_info.self_param_id); context.name_scopes().AddRequiredName(interface_info.scope_id, SemIR::NameId::SelfType, diff --git a/toolchain/check/handle_let_and_var.cpp b/toolchain/check/handle_let_and_var.cpp index 052e7991cd6a..d96ddfdd6ef6 100644 --- a/toolchain/check/handle_let_and_var.cpp +++ b/toolchain/check/handle_let_and_var.cpp @@ -7,6 +7,7 @@ #include "toolchain/check/decl_introducer_state.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/interface.h" #include "toolchain/check/keyword_modifier_set.h" #include "toolchain/check/modifiers.h" @@ -124,9 +125,11 @@ static auto GetOrAddStorage(Context& context, SemIR::InstId pattern_id) name_id = context.entity_names().Get(binding_pattern->entity_name_id).name_id; } - return context.AddInst(SemIR::LocIdAndInst::UncheckedLoc( - pattern.loc_id, SemIR::VarStorage{.type_id = pattern.inst.type_id(), - .pretty_name_id = name_id})); + return AddInst( + context, + SemIR::LocIdAndInst::UncheckedLoc( + pattern.loc_id, SemIR::VarStorage{.type_id = pattern.inst.type_id(), + .pretty_name_id = name_id})); } auto HandleParseNode(Context& context, Parse::VariablePatternId node_id) @@ -145,8 +148,8 @@ auto HandleParseNode(Context& context, Parse::VariablePatternId node_id) } auto type_id = context.insts().Get(subpattern_id).type_id(); - auto pattern_id = context.AddPatternInst( - node_id, {.type_id = type_id, .subpattern_id = subpattern_id}); + auto pattern_id = AddPatternInst( + context, node_id, {.type_id = type_id, .subpattern_id = subpattern_id}); context.node_stack().Push(node_id, pattern_id); return true; } @@ -161,9 +164,8 @@ static auto EndFullPattern(Context& context) -> void { return; } auto pattern_block_id = context.pattern_block_stack().Pop(); - context.AddInst( - context.node_stack().PeekNodeId(), - {.pattern_block_id = pattern_block_id}); + AddInst(context, context.node_stack().PeekNodeId(), + {.pattern_block_id = pattern_block_id}); // We need to emit the VarStorage insts early, because they may be output // arguments for the initializer. However, we can't emit them when we emit @@ -331,7 +333,7 @@ static auto FinishAssociatedConstant(Context& context, Parse::LetDeclId node_id, // Store the decl block on the declaration. decl->decl_block_id = context.inst_block_stack().Pop(); - context.ReplaceInstPreservingConstantValue(decl_info.pattern_id, *decl); + ReplaceInstPreservingConstantValue(context, decl_info.pattern_id, *decl); context.inst_block_stack().AddInstId(decl_info.pattern_id); } diff --git a/toolchain/check/handle_literal.cpp b/toolchain/check/handle_literal.cpp index 0cbc60b966d2..c607a56164e6 100644 --- a/toolchain/check/handle_literal.cpp +++ b/toolchain/check/handle_literal.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/call.h" #include "toolchain/check/context.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/literal.h" #include "toolchain/check/name_lookup.h" #include "toolchain/check/type.h" @@ -15,8 +16,8 @@ namespace Carbon::Check { auto HandleParseNode(Context& context, Parse::BoolLiteralFalseId node_id) -> bool { - context.AddInstAndPush( - node_id, + AddInstAndPush( + context, node_id, {.type_id = GetSingletonType(context, SemIR::BoolType::SingletonInstId), .value = SemIR::BoolValue::False}); return true; @@ -24,8 +25,8 @@ auto HandleParseNode(Context& context, Parse::BoolLiteralFalseId node_id) auto HandleParseNode(Context& context, Parse::BoolLiteralTrueId node_id) -> bool { - context.AddInstAndPush( - node_id, + AddInstAndPush( + context, node_id, {.type_id = GetSingletonType(context, SemIR::BoolType::SingletonInstId), .value = SemIR::BoolValue::True}); return true; @@ -76,16 +77,17 @@ auto HandleParseNode(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, {.type_id = GetSingletonType( - context, SemIR::LegacyFloatType::SingletonInstId), - .float_id = float_id}); + AddInstAndPush( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::LegacyFloatType::SingletonInstId), + .float_id = float_id}); return true; } auto HandleParseNode(Context& context, Parse::StringLiteralId node_id) -> bool { - context.AddInstAndPush( - node_id, + AddInstAndPush( + context, node_id, {.type_id = GetSingletonType(context, SemIR::StringType::SingletonInstId), .string_literal_id = context.tokens().GetStringLiteralValue( context.parse_tree().node_token(node_id))}); diff --git a/toolchain/check/handle_loop_statement.cpp b/toolchain/check/handle_loop_statement.cpp index cf88252501fb..48a24219ac47 100644 --- a/toolchain/check/handle_loop_statement.cpp +++ b/toolchain/check/handle_loop_statement.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" namespace Carbon::Check { @@ -60,7 +61,7 @@ auto HandleParseNode(Context& context, Parse::WhileStatementId node_id) context.break_continue_stack().pop_back(); // Add the loop backedge. - context.AddInst(node_id, {.target_id = loop_header_id}); + AddInst(context, node_id, {.target_id = loop_header_id}); context.inst_block_stack().Pop(); // Start emitting the loop exit block. @@ -101,8 +102,8 @@ auto HandleParseNode(Context& context, Parse::BreakStatementStartId node_id) "`break` can only be used in a loop"); context.emitter().Emit(node_id, BreakOutsideLoop); } else { - context.AddInst(node_id, - {.target_id = stack.back().break_target}); + AddInst(context, node_id, + {.target_id = stack.back().break_target}); } context.inst_block_stack().Pop(); @@ -126,8 +127,8 @@ auto HandleParseNode(Context& context, Parse::ContinueStatementStartId node_id) "`continue` can only be used in a loop"); context.emitter().Emit(node_id, ContinueOutsideLoop); } else { - context.AddInst(node_id, - {.target_id = stack.back().continue_target}); + AddInst(context, 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 450be40ecd30..be10cf5f4e4e 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/member_access.h" #include "toolchain/check/name_component.h" #include "toolchain/check/name_lookup.h" @@ -115,14 +116,16 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id, // store the specific too. if (result.specific_id.has_value() && context.constant_values().Get(inst_id).is_symbolic()) { - inst_id = context.AddInst( - node_id, {.type_id = type_id, - .inst_id = inst_id, - .specific_id = result.specific_id}); + inst_id = + AddInst(context, node_id, + {.type_id = type_id, + .inst_id = inst_id, + .specific_id = result.specific_id}); } - return context.AddInst( - node_id, {.type_id = type_id, .name_id = name_id, .value_id = inst_id}); + return AddInst( + context, node_id, + {.type_id = type_id, .name_id = name_id, .value_id = inst_id}); } static auto HandleIdentifierName(Context& context, @@ -238,11 +241,12 @@ auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id) } auto HandleParseNode(Context& context, Parse::PackageExprId node_id) -> bool { - context.AddInstAndPush( - node_id, {.type_id = GetSingletonType( - context, SemIR::NamespaceType::SingletonInstId), - .name_id = SemIR::NameId::PackageNamespace, - .value_id = SemIR::Namespace::PackageInstId}); + AddInstAndPush( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::NamespaceType::SingletonInstId), + .name_id = SemIR::NameId::PackageNamespace, + .value_id = SemIR::Namespace::PackageInstId}); return true; } diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index 6883321178a1..d8784efc6e01 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/decl_introducer_state.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/modifiers.h" #include "toolchain/check/name_component.h" #include "toolchain/check/name_lookup.h" @@ -42,7 +43,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { GetSingletonType(context, SemIR::NamespaceType::SingletonInstId), SemIR::NameScopeId::None, SemIR::InstId::None}; auto namespace_id = - context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, namespace_inst)); + AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, namespace_inst)); SemIR::ScopeLookupResult lookup_result = context.decl_name_stack().LookupOrAddName(name_context, namespace_id, @@ -75,7 +76,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { !context.insts().GetLocId(existing_inst_id).has_value()) { // When the name conflict is an imported namespace, fill the location ID // so that future diagnostics point at this declaration. - context.SetNamespaceNodeId(existing_inst_id, node_id); + SetNamespaceNodeId(context, existing_inst_id, node_id); } } else { DiagnoseDuplicateName(context, name_context.loc_id, existing_inst_id); @@ -96,7 +97,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { } } - context.ReplaceInstBeforeConstantUse(namespace_id, namespace_inst); + ReplaceInstBeforeConstantUse(context, namespace_id, namespace_inst); context.decl_name_stack().PopScope(); return true; diff --git a/toolchain/check/handle_operator.cpp b/toolchain/check/handle_operator.cpp index 02947f30d42f..403fbc3ab750 100644 --- a/toolchain/check/handle_operator.cpp +++ b/toolchain/check/handle_operator.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/operator.h" #include "toolchain/check/pointer_dereference.h" #include "toolchain/check/type.h" @@ -85,7 +86,8 @@ auto HandleParseNode(Context& context, Parse::InfixOperatorEqualId node_id) // 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, {.lhs_id = lhs_id, .rhs_id = rhs_id}); + AddInst(context, 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 @@ -216,9 +218,10 @@ auto HandleParseNode(Context& context, Parse::PostfixOperatorStarId node_id) -> bool { auto value_id = context.node_stack().PopExpr(); auto inner_type_id = ExprAsType(context, node_id, value_id).type_id; - context.AddInstAndPush( - node_id, {.type_id = SemIR::TypeType::SingletonTypeId, - .pointee_id = inner_type_id}); + AddInstAndPush( + context, node_id, + {.type_id = SemIR::TypeType::SingletonTypeId, + .pointee_id = inner_type_id}); return true; } @@ -244,9 +247,10 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorAmpId node_id) value_id = SemIR::ErrorInst::SingletonInstId; break; } - context.AddInstAndPush( - node_id, SemIR::AddrOf{.type_id = GetPointerType(context, type_id), - .lvalue_id = value_id}); + AddInstAndPush( + context, node_id, + SemIR::AddrOf{.type_id = GetPointerType(context, type_id), + .lvalue_id = value_id}); return true; } @@ -269,8 +273,8 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorConstId node_id) context.emitter().Emit(node_id, RepeatedConst); } auto inner_type_id = ExprAsType(context, node_id, value_id).type_id; - context.AddInstAndPush( - node_id, + AddInstAndPush( + context, node_id, {.type_id = SemIR::TypeType::SingletonTypeId, .inner_id = inner_type_id}); return true; } @@ -289,9 +293,10 @@ auto HandleParseNode(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, {.type_id = context.insts().Get(value_id).type_id(), - .operand_id = value_id}); + AddInstAndPush( + context, node_id, + {.type_id = context.insts().Get(value_id).type_id(), + .operand_id = value_id}); return true; } @@ -341,12 +346,12 @@ 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, {.type_id = bool_type_id, .operand_id = cond_value_id}) - : cond_value_id; - auto short_circuit_result_id = context.AddInst( - node_id, + is_or ? AddInst( + context, node_id, + {.type_id = bool_type_id, .operand_id = cond_value_id}) + : cond_value_id; + auto short_circuit_result_id = AddInst( + context, 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. @@ -403,15 +408,16 @@ 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, {.target_id = resume_block_id, .arg_id = rhs_id}); + AddInst( + context, node_id, {.target_id = resume_block_id, .arg_id = rhs_id}); context.inst_block_stack().Pop(); context.region_stack().AddToRegion(resume_block_id, node_id); // Collect the result from either the first or second operand. - auto result_id = context.AddInst( - node_id, {.type_id = context.insts().Get(rhs_id).type_id(), - .block_id = resume_block_id}); + auto result_id = AddInst( + context, node_id, + {.type_id = context.insts().Get(rhs_id).type_id(), + .block_id = resume_block_id}); SetBlockArgResultBeforeConstantUse(context, 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 33ea0a230f9d..e2e02c02a98d 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" #include "toolchain/diagnostics/format_providers.h" @@ -145,8 +146,8 @@ auto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool { auto type_id = GetStructType( context, context.struct_type_fields().AddCanonical(fields)); - auto value_id = context.AddInst( - node_id, {.type_id = type_id, .elements_id = elements_id}); + auto value_id = AddInst( + context, node_id, {.type_id = type_id, .elements_id = elements_id}); context.node_stack().Push(node_id, value_id); } @@ -169,8 +170,8 @@ auto HandleParseNode(Context& context, Parse::StructTypeLiteralId node_id) context.node_stack().Push(node_id, SemIR::ErrorInst::SingletonInstId); } else { auto fields_id = context.struct_type_fields().AddCanonical(fields); - context.AddInstAndPush( - node_id, + AddInstAndPush( + context, node_id, {.type_id = SemIR::TypeType::SingletonTypeId, .fields_id = fields_id}); } diff --git a/toolchain/check/handle_tuple_literal.cpp b/toolchain/check/handle_tuple_literal.cpp index 69e52e33057b..3fce85bd5afe 100644 --- a/toolchain/check/handle_tuple_literal.cpp +++ b/toolchain/check/handle_tuple_literal.cpp @@ -4,6 +4,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" namespace Carbon::Check { @@ -35,8 +36,8 @@ auto HandleParseNode(Context& context, Parse::TupleLiteralId node_id) -> bool { } auto type_id = GetTupleType(context, type_ids); - auto value_id = context.AddInst( - node_id, {.type_id = type_id, .elements_id = refs_id}); + auto value_id = AddInst( + context, 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_where.cpp b/toolchain/check/handle_where.cpp index ca57fc97a508..52a228102f3d 100644 --- a/toolchain/check/handle_where.cpp +++ b/toolchain/check/handle_where.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/convert.h" #include "toolchain/check/generic.h" #include "toolchain/check/handle.h" +#include "toolchain/check/inst.h" namespace Carbon::Check { @@ -32,12 +33,12 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool { auto entity_name_id = context.entity_names().Add( {.name_id = SemIR::NameId::PeriodSelf, .parent_scope_id = context.scope_stack().PeekNameScopeId()}); - auto inst_id = - context.AddInst(SemIR::LocIdAndInst::NoLoc( - {.type_id = self_type_id, - .entity_name_id = entity_name_id, - // `None` because there is no equivalent non-symbolic value. - .value_id = SemIR::InstId::None})); + auto inst_id = AddInst( + context, SemIR::LocIdAndInst::NoLoc( + {.type_id = self_type_id, + .entity_name_id = entity_name_id, + // `None` because there is no equivalent non-symbolic value. + .value_id = SemIR::InstId::None})); auto existing = context.scope_stack().LookupOrAddName(SemIR::NameId::PeriodSelf, inst_id); // Shouldn't have any names in newly created scope. @@ -79,8 +80,8 @@ auto HandleParseNode(Context& context, Parse::RequirementEqualId node_id) // Build up the list of arguments for the `WhereExpr` inst. context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - node_id, {.lhs_id = lhs, .rhs_id = rhs_id})); + AddInstInNoBlock( + context, node_id, {.lhs_id = lhs, .rhs_id = rhs_id})); return true; } @@ -93,8 +94,8 @@ auto HandleParseNode(Context& context, Parse::RequirementEqualEqualId node_id) // Build up the list of arguments for the `WhereExpr` inst. context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - node_id, {.lhs_id = lhs, .rhs_id = rhs})); + AddInstInNoBlock( + context, node_id, {.lhs_id = lhs, .rhs_id = rhs})); return true; } @@ -118,8 +119,8 @@ auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id) // Build up the list of arguments for the `WhereExpr` inst. context.args_type_info_stack().AddInstId( - context.AddInstInNoBlock( - node_id, + AddInstInNoBlock( + context, node_id, {.lhs_id = lhs_as_type.inst_id, .rhs_id = rhs_as_type.inst_id})); return true; } @@ -137,10 +138,10 @@ auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool { SemIR::InstId period_self_id = context.node_stack().Pop(); SemIR::InstBlockId requirements_id = context.args_type_info_stack().Pop(); - context.AddInstAndPush( - node_id, {.type_id = SemIR::TypeType::SingletonTypeId, - .period_self_id = period_self_id, - .requirements_id = requirements_id}); + AddInstAndPush(context, node_id, + {.type_id = SemIR::TypeType::SingletonTypeId, + .period_self_id = period_self_id, + .requirements_id = requirements_id}); return true; } diff --git a/toolchain/check/impl.cpp b/toolchain/check/impl.cpp index 84247be54480..2d2cd033a3f6 100644 --- a/toolchain/check/impl.cpp +++ b/toolchain/check/impl.cpp @@ -133,8 +133,8 @@ auto ImplWitnessForDeclaration(Context& context, const SemIR::Impl& impl) llvm::SmallVector table(assoc_entities.size(), SemIR::InstId::None); auto table_id = context.inst_blocks().Add(table); - return context.AddInst( - context.insts().GetLocId(impl.latest_decl_id()), + return AddInst( + context, context.insts().GetLocId(impl.latest_decl_id()), {.type_id = GetSingletonType(context, SemIR::WitnessType::SingletonInstId), .elements_id = table_id, diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 2bfaae86be85..2df91e14047c 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -9,6 +9,7 @@ #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/import_ref.h" +#include "toolchain/check/inst.h" #include "toolchain/check/merge.h" #include "toolchain/check/name_lookup.h" #include "toolchain/check/type.h" @@ -128,17 +129,17 @@ auto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id, .import_id = import_id}; auto namespace_inst_and_loc = import_loc_id.is_import_ir_inst_id() - ? context.MakeImportedLocAndInst(import_loc_id.import_ir_inst_id(), - namespace_inst) + ? MakeImportedLocIdAndInst(context, import_loc_id.import_ir_inst_id(), + namespace_inst) // TODO: Check that this actually is an `AnyNamespaceId`. : SemIR::LocIdAndInst(Parse::AnyNamespaceId(import_loc_id.node_id()), namespace_inst); auto namespace_id = - context.AddPlaceholderInstInNoBlock(namespace_inst_and_loc); + AddPlaceholderInstInNoBlock(context, namespace_inst_and_loc); context.import_ref_ids().push_back(namespace_id); namespace_inst.name_scope_id = context.name_scopes().Add(namespace_id, name_id, parent_scope_id); - context.ReplaceInstBeforeConstantUse(namespace_id, namespace_inst); + ReplaceInstBeforeConstantUse(context, namespace_id, namespace_inst); // Note we have to get the parent scope freshly, creating the imported // namespace may invalidate the pointer above. @@ -188,11 +189,12 @@ static auto CopySingleNameScopeFromImportIR( {.name_id = name_id, .parent_scope_id = parent_scope_id}); auto import_ir_inst_id = context.import_ir_insts().Add( {.ir_id = ir_id, .inst_id = import_inst_id}); - auto inst_id = context.AddInstInNoBlock( - context.MakeImportedLocAndInst( - import_ir_inst_id, {.type_id = namespace_type_id, - .import_ir_inst_id = import_ir_inst_id, - .entity_name_id = entity_name_id})); + auto inst_id = AddInstInNoBlock( + context, MakeImportedLocIdAndInst( + context, import_ir_inst_id, + {.type_id = namespace_type_id, + .import_ir_inst_id = import_ir_inst_id, + .entity_name_id = entity_name_id})); context.import_ref_ids().push_back(inst_id); return inst_id; }; diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index 005bf6eb7a12..8cdd79ffb628 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -17,6 +17,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/import.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" #include "toolchain/diagnostics/diagnostic.h" #include "toolchain/diagnostics/format_providers.h" @@ -105,8 +106,8 @@ static auto AddNamespace(Context& context, PackageNameId cpp_package_id, SemIR::NameScopeId::Package, /*diagnose_duplicate_namespace=*/false, [&]() { - return context.AddInst( - imports.front().node_id, {}); + return AddInst( + context, imports.front().node_id, {}); }) .name_scope_id; } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index e7db4fabe14d..22c3faedb57c 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/eval.h" #include "toolchain/check/generic.h" +#include "toolchain/check/inst.h" #include "toolchain/check/name_lookup.h" #include "toolchain/check/type.h" #include "toolchain/parse/node_ids.h" @@ -63,8 +64,8 @@ auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst, auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst); SemIR::ImportRefUnloaded inst = {.import_ir_inst_id = import_ir_inst_id, .entity_name_id = entity_name_id}; - auto import_ref_id = context.AddPlaceholderInstInNoBlock( - context.MakeImportedLocAndInst(import_ir_inst_id, inst)); + auto import_ref_id = AddPlaceholderInstInNoBlock( + context, MakeImportedLocIdAndInst(context, import_ir_inst_id, inst)); // ImportRefs have a dedicated block because this may be called during // processing where the instruction shouldn't be inserted in the current inst @@ -84,8 +85,8 @@ static auto AddLoadedImportRef(Context& context, SemIR::TypeId type_id, SemIR::ImportRefLoaded inst = {.type_id = type_id, .import_ir_inst_id = import_ir_inst_id, .entity_name_id = SemIR::EntityNameId::None}; - auto inst_id = context.AddPlaceholderInstInNoBlock( - context.MakeImportedLocAndInst(import_ir_inst_id, inst)); + auto inst_id = AddPlaceholderInstInNoBlock( + context, MakeImportedLocIdAndInst(context, import_ir_inst_id, inst)); context.import_ref_ids().push_back(inst_id); context.constant_values().Set(inst_id, const_id); @@ -1033,10 +1034,9 @@ static auto GetLocalParamPatternsId(ImportContext& context, case SemIR::BindingPattern::Kind: { auto entity_name_id = context.local_entity_names().Add( {.name_id = name_id, .parent_scope_id = SemIR::NameScopeId::None}); - new_param_id = - context.local_context().AddInstInNoBlock( - AddImportIRInst(context, binding_id), - {.type_id = type_id, .entity_name_id = entity_name_id}); + new_param_id = AddInstInNoBlock( + context.local_context(), AddImportIRInst(context, binding_id), + {.type_id = type_id, .entity_name_id = entity_name_id}); break; } case SemIR::SymbolicBindingPattern::Kind: { @@ -1047,8 +1047,9 @@ static auto GetLocalParamPatternsId(ImportContext& context, auto new_binding_inst = context.local_insts().GetAs( context.local_constant_values().GetInstId(bind_const_id)); - new_param_id = context.local_context().AddInstInNoBlock( - AddImportIRInst(context, binding_id), new_binding_inst); + new_param_id = AddInstInNoBlock(context.local_context(), + AddImportIRInst(context, binding_id), + new_binding_inst); context.local_constant_values().Set(new_param_id, bind_const_id); break; } @@ -1056,20 +1057,22 @@ static auto GetLocalParamPatternsId(ImportContext& context, CARBON_FATAL("Unexpected kind: ", binding.kind); } } - new_param_id = context.local_context().AddInstInNoBlock( - context.local_context() - .MakeImportedLocAndInst( - AddImportIRInst(context, param_pattern_id), - {.type_id = type_id, - .subpattern_id = new_param_id, - .runtime_index = param_pattern.runtime_index})); + new_param_id = AddInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, param_pattern_id), + {.type_id = type_id, + .subpattern_id = new_param_id, + .runtime_index = param_pattern.runtime_index})); if (addr_inst) { type_id = context.local_context().types().GetTypeIdForTypeConstantId( GetLocalConstantIdChecked(context, addr_inst->type_id)); - new_param_id = context.local_context().AddInstInNoBlock( - context.local_context().MakeImportedLocAndInst( - AddImportIRInst(context, addr_pattern_id), - {.type_id = type_id, .inner_id = new_param_id})); + new_param_id = + AddInstInNoBlock(context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), + AddImportIRInst(context, addr_pattern_id), + {.type_id = type_id, .inner_id = new_param_id})); } if (self_param_id && context.import_entity_names().Get(binding.entity_name_id).name_id == @@ -1098,12 +1101,16 @@ static auto GetLocalReturnSlotPatternId( auto type_id = context.local_context().types().GetTypeIdForTypeConstantId( GetLocalConstantIdChecked(context, return_slot_pattern.type_id)); - auto new_return_slot_pattern_id = context.local_context().AddInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + auto new_return_slot_pattern_id = AddInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, param_pattern.subpattern_id), {.type_id = type_id, .type_inst_id = SemIR::InstId::None})); - return context.local_context().AddInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + return AddInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, import_return_slot_pattern_id), {.type_id = type_id, .subpattern_id = new_return_slot_pattern_id, @@ -1340,9 +1347,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, inst.adapted_type_inst_id, adapted_type_const_id); // Create a corresponding instruction to represent the declaration. - auto inst_id = resolver.local_context().AddInstInNoBlock( - resolver.local_context().MakeImportedLocAndInst( - AddImportIRInst(resolver, import_inst_id), + auto inst_id = AddInstInNoBlock( + resolver.local_context(), + MakeImportedLocIdAndInst( + resolver.local_context(), AddImportIRInst(resolver, import_inst_id), {.adapted_type_inst_id = adapted_type_inst_id})); return ResolveResult::Done(resolver.local_constant_values().Get(inst_id), inst_id); @@ -1375,11 +1383,12 @@ static auto MakeAssociatedConstant( .type_id = type_id, .assoc_const_id = SemIR::AssociatedConstantId::None, .decl_block_id = SemIR::InstBlockId::Empty}; - auto assoc_const_decl_id = - context.local_context().AddPlaceholderInstInNoBlock( - context.local_context().MakeImportedLocAndInst( - AddImportIRInst(context, import_assoc_const.decl_id), - assoc_const_decl)); + auto assoc_const_decl_id = AddPlaceholderInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), + AddImportIRInst(context, import_assoc_const.decl_id), + assoc_const_decl)); assoc_const_decl.assoc_const_id = context.local_associated_constants().Add({ .name_id = GetLocalNameId(context, import_assoc_const.name_id), .parent_scope_id = SemIR::NameScopeId::None, @@ -1393,8 +1402,8 @@ static auto MakeAssociatedConstant( }); // Write the associated constant ID into the AssociatedConstantDecl. - context.local_context().ReplaceInstBeforeConstantUse(assoc_const_decl_id, - assoc_const_decl); + ReplaceInstBeforeConstantUse(context.local_context(), assoc_const_decl_id, + assoc_const_decl); auto const_id = context.local_constant_values().Get(assoc_const_decl_id); return {assoc_const_decl.assoc_const_id, const_id}; } @@ -1499,9 +1508,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, inst.base_type_inst_id, base_type_const_id); // Create a corresponding instruction to represent the declaration. - auto inst_id = resolver.local_context().AddInstInNoBlock( - resolver.local_context().MakeImportedLocAndInst( - AddImportIRInst(resolver, import_inst_id), + auto inst_id = AddInstInNoBlock( + resolver.local_context(), + MakeImportedLocIdAndInst( + resolver.local_context(), AddImportIRInst(resolver, import_inst_id), {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( type_const_id), @@ -1629,8 +1639,10 @@ static auto MakeIncompleteClass(ImportContext& context, SemIR::ClassDecl class_decl = {.type_id = SemIR::TypeType::SingletonTypeId, .class_id = SemIR::ClassId::None, .decl_block_id = SemIR::InstBlockId::Empty}; - auto class_decl_id = context.local_context().AddPlaceholderInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + auto class_decl_id = AddPlaceholderInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, import_class.latest_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. @@ -1646,8 +1658,8 @@ static auto MakeIncompleteClass(ImportContext& context, } // Write the class ID into the ClassDecl. - context.local_context().ReplaceInstBeforeConstantUse(class_decl_id, - class_decl); + ReplaceInstBeforeConstantUse(context.local_context(), class_decl_id, + class_decl); auto self_const_id = context.local_constant_values().Get(class_decl_id); return {class_decl.class_id, self_const_id}; } @@ -1861,9 +1873,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, if (resolver.HasNewWork()) { return ResolveResult::Retry(); } - auto inst_id = resolver.local_context().AddInstInNoBlock( - resolver.local_context().MakeImportedLocAndInst( - AddImportIRInst(resolver, import_inst_id), + auto inst_id = AddInstInNoBlock( + resolver.local_context(), + MakeImportedLocIdAndInst( + resolver.local_context(), AddImportIRInst(resolver, import_inst_id), {.type_id = resolver.local_context().types().GetTypeIdForTypeConstantId( const_id), @@ -1883,8 +1896,10 @@ static auto MakeFunctionDecl(ImportContext& context, .type_id = SemIR::TypeId::None, .function_id = SemIR::FunctionId::None, .decl_block_id = SemIR::InstBlockId::Empty}; - auto function_decl_id = context.local_context().AddPlaceholderInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + auto function_decl_id = AddPlaceholderInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, import_function.first_decl_id()), function_decl)); @@ -1898,8 +1913,8 @@ static auto MakeFunctionDecl(ImportContext& context, context.local_context(), function_decl.function_id, specific_id); // Write the function ID and type into the FunctionDecl. - context.local_context().ReplaceInstBeforeConstantUse(function_decl_id, - function_decl); + ReplaceInstBeforeConstantUse(context.local_context(), function_decl_id, + function_decl); return {function_decl.function_id, context.local_constant_values().Get(function_decl_id)}; } @@ -2056,8 +2071,10 @@ static auto MakeImplDeclaration(ImportContext& context, -> std::pair { SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None, .decl_block_id = SemIR::InstBlockId::Empty}; - auto impl_decl_id = context.local_context().AddPlaceholderInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + auto impl_decl_id = AddPlaceholderInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, import_impl.latest_decl_id()), impl_decl)); impl_decl.impl_id = context.local_impls().Add( {GetIncompleteLocalEntityBase(context, impl_decl_id, import_impl), @@ -2066,7 +2083,8 @@ static auto MakeImplDeclaration(ImportContext& context, .witness_id = witness_id}}); // Write the impl ID into the ImplDecl. - context.local_context().ReplaceInstBeforeConstantUse(impl_decl_id, impl_decl); + ReplaceInstBeforeConstantUse(context.local_context(), impl_decl_id, + impl_decl); return {impl_decl.impl_id, context.local_constant_values().Get(impl_decl_id)}; } @@ -2203,8 +2221,10 @@ static auto MakeInterfaceDecl(ImportContext& context, .type_id = SemIR::TypeType::SingletonTypeId, .interface_id = SemIR::InterfaceId::None, .decl_block_id = SemIR::InstBlockId::Empty}; - auto interface_decl_id = context.local_context().AddPlaceholderInstInNoBlock( - context.local_context().MakeImportedLocAndInst( + auto interface_decl_id = AddPlaceholderInstInNoBlock( + context.local_context(), + MakeImportedLocIdAndInst( + context.local_context(), AddImportIRInst(context, import_interface.first_owning_decl_id), interface_decl)); @@ -2221,8 +2241,8 @@ static auto MakeInterfaceDecl(ImportContext& context, } // Write the interface ID into the InterfaceDecl. - context.local_context().ReplaceInstBeforeConstantUse(interface_decl_id, - interface_decl); + ReplaceInstBeforeConstantUse(context.local_context(), interface_decl_id, + interface_decl); return {interface_decl.interface_id, context.local_constant_values().Get(interface_decl_id)}; } @@ -2539,9 +2559,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::Namespace{.type_id = namespace_type_id, .name_scope_id = SemIR::NameScopeId::None, .import_id = SemIR::AbsoluteInstId::None}; - auto inst_id = resolver.local_context().AddPlaceholderInstInNoBlock( - resolver.local_context().MakeImportedLocAndInst( - AddImportIRInst(resolver, import_inst_id), namespace_decl)); + auto inst_id = AddPlaceholderInstInNoBlock( + resolver.local_context(), + MakeImportedLocIdAndInst(resolver.local_context(), + AddImportIRInst(resolver, import_inst_id), + namespace_decl)); auto name_id = GetLocalNameId(resolver, name_scope.name_id()); namespace_decl.name_scope_id = @@ -2551,8 +2573,8 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver, resolver.local_name_scopes() .Get(namespace_decl.name_scope_id) .set_is_closed_import(true); - resolver.local_context().ReplaceInstBeforeConstantUse(inst_id, - namespace_decl); + ReplaceInstBeforeConstantUse(resolver.local_context(), inst_id, + namespace_decl); return {.const_id = resolver.local_constant_values().Get(inst_id)}; } @@ -3209,4 +3231,38 @@ auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id, context.generic_region_stack().Pop(); } +// Returns whether a parse node associated with an imported instruction of kind +// `imported_kind` is usable as the location of a corresponding local +// instruction of kind `local_kind`. +static auto HasCompatibleImportedNodeKind(SemIR::InstKind imported_kind, + SemIR::InstKind local_kind) -> bool { + if (imported_kind == local_kind) { + return true; + } + if (imported_kind == SemIR::ImportDecl::Kind && + local_kind == SemIR::Namespace::Kind) { + static_assert( + std::is_convertible_v); + return true; + } + return false; +} + +namespace Internal { + +auto CheckCompatibleImportedNodeKind(Context& context, + SemIR::ImportIRInstId imported_loc_id, + SemIR::InstKind kind) -> void { + auto& import_ir_inst = context.import_ir_insts().Get(imported_loc_id); + const auto* import_ir = context.import_irs().Get(import_ir_inst.ir_id).sem_ir; + auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id).kind(); + CARBON_CHECK( + HasCompatibleImportedNodeKind(imported_kind, kind), + "Node of kind {0} created with location of imported node of kind {1}", + kind, imported_kind); +} + +} // namespace Internal + } // namespace Carbon::Check diff --git a/toolchain/check/import_ref.h b/toolchain/check/import_ref.h index 1f82964f176a..094c7e7b5fdb 100644 --- a/toolchain/check/import_ref.h +++ b/toolchain/check/import_ref.h @@ -48,6 +48,30 @@ auto ImportImplsFromApiFile(Context& context) -> void; auto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id, SemIR::ImplId impl_id) -> void; +namespace Internal { + +// Checks that the provided imported location has a node kind that is +// compatible with that of the given instruction. +auto CheckCompatibleImportedNodeKind(Context& context, + SemIR::ImportIRInstId imported_loc_id, + SemIR::InstKind kind) -> void; +} // namespace Internal + +// Returns a LocIdAndInst for an instruction with an imported location. Checks +// that the imported location is compatible with the kind of instruction being +// created. +template + requires SemIR::Internal::HasNodeId +auto MakeImportedLocIdAndInst(Context& context, + SemIR::ImportIRInstId imported_loc_id, InstT inst) + -> SemIR::LocIdAndInst { + if constexpr (!SemIR::Internal::HasUntypedNodeId) { + Internal::CheckCompatibleImportedNodeKind(context, imported_loc_id, + InstT::Kind); + } + return SemIR::LocIdAndInst::UncheckedLoc(imported_loc_id, inst); +} + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_ diff --git a/toolchain/check/inst.cpp b/toolchain/check/inst.cpp new file mode 100644 index 000000000000..687eee05a9f5 --- /dev/null +++ b/toolchain/check/inst.cpp @@ -0,0 +1,136 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/inst.h" + +#include "common/vlog.h" +#include "toolchain/check/context.h" +#include "toolchain/check/eval.h" + +namespace Carbon::Check { + +// Finish producing an instruction. Set its constant value, and register it in +// any applicable instruction lists. +static auto FinishInst(Context& context, SemIR::InstId inst_id, + SemIR::Inst inst) -> void { + GenericRegionStack::DependencyKind dep_kind = + GenericRegionStack::DependencyKind::None; + + // If the instruction has a symbolic constant type, track that we need to + // substitute into it. + if (context.constant_values().DependsOnGenericParameter( + context.types().GetConstantId(inst.type_id()))) { + dep_kind |= GenericRegionStack::DependencyKind::SymbolicType; + } + + // If the instruction has a constant value, compute it. + auto const_id = TryEvalInst(context, inst_id, inst); + context.constant_values().Set(inst_id, const_id); + if (const_id.is_constant()) { + CARBON_VLOG_TO(context.vlog_stream(), "Constant: {0} -> {1}\n", inst, + context.constant_values().GetInstId(const_id)); + + // If the constant value is symbolic, track that we need to substitute into + // it. + if (context.constant_values().DependsOnGenericParameter(const_id)) { + dep_kind |= GenericRegionStack::DependencyKind::SymbolicConstant; + } + } + + // Keep track of dependent instructions. + if (dep_kind != GenericRegionStack::DependencyKind::None) { + // TODO: Also check for template-dependent instructions. + context.generic_region_stack().AddDependentInst( + {.inst_id = inst_id, .kind = dep_kind}); + } +} + +auto AddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + auto inst_id = AddInstInNoBlock(context, loc_id_and_inst); + context.inst_block_stack().AddInstId(inst_id); + return inst_id; +} + +auto AddInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + auto inst_id = context.sem_ir().insts().AddInNoBlock(loc_id_and_inst); + CARBON_VLOG_TO(context.vlog_stream(), "AddInst: {0}\n", loc_id_and_inst.inst); + FinishInst(context, inst_id, loc_id_and_inst.inst); + return inst_id; +} + +auto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + auto inst_id = AddInstInNoBlock(context, loc_id_and_inst); + context.pattern_block_stack().AddInstId(inst_id); + return inst_id; +} + +auto GetOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + if (loc_id_and_inst.loc_id.is_implicit()) { + auto const_id = + TryEvalInst(context, SemIR::InstId::None, loc_id_and_inst.inst); + if (const_id.has_value()) { + CARBON_VLOG_TO(context.vlog_stream(), "GetOrAddInst: constant: {0}\n", + loc_id_and_inst.inst); + return context.constant_values().GetInstId(const_id); + } + } + // TODO: For an implicit instruction, this reattempts evaluation. + return AddInst(context, loc_id_and_inst); +} + +auto AddPlaceholderInstInNoBlock(Context& context, + SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + auto inst_id = context.sem_ir().insts().AddInNoBlock(loc_id_and_inst); + CARBON_VLOG_TO(context.vlog_stream(), "AddPlaceholderInst: {0}\n", + loc_id_and_inst.inst); + context.constant_values().Set(inst_id, SemIR::ConstantId::None); + return inst_id; +} + +auto AddPlaceholderInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId { + auto inst_id = AddPlaceholderInstInNoBlock(context, loc_id_and_inst); + context.inst_block_stack().AddInstId(inst_id); + return inst_id; +} + +auto ReplaceLocIdAndInstBeforeConstantUse(Context& context, + SemIR::InstId inst_id, + SemIR::LocIdAndInst loc_id_and_inst) + -> void { + context.sem_ir().insts().SetLocIdAndInst(inst_id, loc_id_and_inst); + CARBON_VLOG_TO(context.vlog_stream(), "ReplaceInst: {0} -> {1}\n", inst_id, + loc_id_and_inst.inst); + FinishInst(context, inst_id, loc_id_and_inst.inst); +} + +auto ReplaceInstBeforeConstantUse(Context& context, SemIR::InstId inst_id, + SemIR::Inst inst) -> void { + context.sem_ir().insts().Set(inst_id, inst); + CARBON_VLOG_TO(context.vlog_stream(), "ReplaceInst: {0} -> {1}\n", inst_id, + inst); + FinishInst(context, inst_id, inst); +} + +auto ReplaceInstPreservingConstantValue(Context& context, SemIR::InstId inst_id, + SemIR::Inst inst) -> void { + auto old_const_id = context.constant_values().Get(inst_id); + context.sem_ir().insts().Set(inst_id, inst); + CARBON_VLOG_TO(context.vlog_stream(), "ReplaceInst: {0} -> {1}\n", inst_id, + inst); + auto new_const_id = TryEvalInst(context, inst_id, inst); + CARBON_CHECK(old_const_id == new_const_id); +} + +auto SetNamespaceNodeId(Context& context, SemIR::InstId inst_id, + Parse::NodeId node_id) -> void { + context.sem_ir().insts().SetLocId(inst_id, SemIR::LocId(node_id)); +} + +} // namespace Carbon::Check diff --git a/toolchain/check/inst.h b/toolchain/check/inst.h new file mode 100644 index 000000000000..df51404a1b9c --- /dev/null +++ b/toolchain/check/inst.h @@ -0,0 +1,120 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_INST_H_ +#define CARBON_TOOLCHAIN_CHECK_INST_H_ + +#include "toolchain/check/context.h" +#include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" + +namespace Carbon::Check { + +// Adds an instruction to the current block, returning the produced ID. +auto AddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Convenience for AddInst with typed nodes. +template +auto AddInst(Context& context, LocT loc, InstT inst) + -> decltype(AddInst(context, SemIR::LocIdAndInst(loc, inst))) { + return AddInst(context, SemIR::LocIdAndInst(loc, inst)); +} + +// Pushes a parse tree node onto the stack, storing the SemIR::Inst as the +// result. +template + requires(SemIR::Internal::HasNodeId) +auto AddInstAndPush(Context& context, + typename decltype(InstT::Kind)::TypedNodeId node_id, + InstT inst) -> void { + context.node_stack().Push(node_id, AddInst(context, node_id, inst)); +} + +// Adds an instruction in no block, returning the produced ID. Should be used +// rarely. +auto AddInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Convenience for AddInstInNoBlock with typed nodes. +template +auto AddInstInNoBlock(Context& context, LocT loc, InstT inst) + -> decltype(AddInstInNoBlock(context, SemIR::LocIdAndInst(loc, inst))) { + return AddInstInNoBlock(context, SemIR::LocIdAndInst(loc, inst)); +} + +// If the instruction has an implicit location and a constant value, returns +// the constant value's instruction ID. Otherwise, same as AddInst. +auto GetOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Convenience for GetOrAddInst with typed nodes. +template +auto GetOrAddInst(Context& context, LocT loc, InstT inst) + -> decltype(GetOrAddInst(context, SemIR::LocIdAndInst(loc, inst))) { + return GetOrAddInst(context, SemIR::LocIdAndInst(loc, inst)); +} + +// Adds an instruction to the current pattern block, returning the produced +// ID. +// TODO: Is it possible to remove this and pattern_block_stack, now that +// we have BeginSubpattern etc. instead? +auto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Convenience for AddPatternInst with typed nodes. +template + requires(SemIR::Internal::HasNodeId) +auto AddPatternInst(Context& context, + typename decltype(InstT::Kind)::TypedNodeId node_id, + InstT inst) -> SemIR::InstId { + return AddPatternInst(context, SemIR::LocIdAndInst(node_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`. +auto AddPlaceholderInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Adds an instruction in no block, returning the produced ID. Should be used +// rarely. The instruction is a placeholder that is expected to be replaced by +// `ReplaceInstBeforeConstantUse`. +auto AddPlaceholderInstInNoBlock(Context& context, + SemIR::LocIdAndInst loc_id_and_inst) + -> SemIR::InstId; + +// Replaces the instruction at `inst_id` with `loc_id_and_inst`. The +// instruction is required to not have been used in any constant evaluation, +// either because it's newly created and entirely unused, or because it's only +// used in a position that constant evaluation ignores, such as a return slot. +auto ReplaceLocIdAndInstBeforeConstantUse(Context& context, + SemIR::InstId inst_id, + SemIR::LocIdAndInst loc_id_and_inst) + -> void; + +// Replaces the instruction at `inst_id` with `inst`, not affecting location. +// The instruction is required to not have been used in any constant +// evaluation, either because it's newly created and entirely unused, or +// because it's only used in a position that constant evaluation ignores, such +// as a return slot. +auto ReplaceInstBeforeConstantUse(Context& context, SemIR::InstId inst_id, + SemIR::Inst inst) -> void; + +// Replaces the instruction at `inst_id` with `inst`, not affecting location. +// The instruction is required to not change its constant value. +auto ReplaceInstPreservingConstantValue(Context& context, SemIR::InstId inst_id, + SemIR::Inst inst) -> void; + +// Sets only the parse node of an instruction. This is only used when setting +// the parse node of an imported namespace. Versus +// ReplaceInstBeforeConstantUse, it is safe to use after the namespace is used +// in constant evaluation. It's exposed this way mainly so that `insts()` can +// remain const. +auto SetNamespaceNodeId(Context& context, SemIR::InstId inst_id, + Parse::NodeId node_id) -> void; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_INST_H_ diff --git a/toolchain/check/interface.cpp b/toolchain/check/interface.cpp index 4a925755895a..1417617fa18d 100644 --- a/toolchain/check/interface.cpp +++ b/toolchain/check/interface.cpp @@ -7,6 +7,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/eval.h" #include "toolchain/check/generic.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" @@ -36,8 +37,8 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id, // Name lookup for the declaration's name should name the associated entity, // not the declaration itself. auto type_id = GetAssociatedEntityType(context, self_type_id); - return context.AddInst( - context.insts().GetLocId(decl_id), + return AddInst( + context, context.insts().GetLocId(decl_id), {.type_id = type_id, .index = index, .decl_id = decl_id}); } diff --git a/toolchain/check/literal.cpp b/toolchain/check/literal.cpp index 310e87b1c145..afc928abd4be 100644 --- a/toolchain/check/literal.cpp +++ b/toolchain/check/literal.cpp @@ -14,10 +14,11 @@ namespace Carbon::Check { auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id) -> SemIR::InstId { - return context.AddInst( - node_id, {.type_id = GetSingletonType( - context, SemIR::IntLiteralType::SingletonInstId), - .int_id = int_id}); + return AddInst( + context, node_id, + {.type_id = + GetSingletonType(context, SemIR::IntLiteralType::SingletonInstId), + .int_id = int_id}); } auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id, diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index cb9c463f257c..d62925630086 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -173,10 +173,10 @@ static auto AccessMemberOfImplWitness(Context& context, SemIR::LocId loc_id, context, loc_id, interface_specific_id, assoc_entity->decl_id, self_type_id, witness_id); - return context.GetOrAddInst( - loc_id, {.type_id = assoc_type_id, - .witness_id = witness_id, - .index = assoc_entity->index}); + return GetOrAddInst(context, loc_id, + {.type_id = assoc_type_id, + .witness_id = witness_id, + .index = assoc_entity->index}); } // Performs impl lookup for a member name expression. This finds the relevant @@ -262,19 +262,21 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, .Get(result.scope_result.target_inst_id()) .is_symbolic()) { result.scope_result = SemIR::ScopeLookupResult::MakeFound( - context.GetOrAddInst( - loc_id, {.type_id = type_id, - .inst_id = result.scope_result.target_inst_id(), - .specific_id = result.specific_id}), + GetOrAddInst( + context, loc_id, + {.type_id = type_id, + .inst_id = result.scope_result.target_inst_id(), + .specific_id = result.specific_id}), SemIR::AccessKind::Public); } // TODO: Use a different kind of instruction that also references the // `base_id` so that `SemIR` consumers can find it. - auto member_id = context.GetOrAddInst( - loc_id, {.type_id = type_id, - .name_id = name_id, - .value_id = result.scope_result.target_inst_id()}); + auto member_id = GetOrAddInst( + context, loc_id, + {.type_id = type_id, + .name_id = name_id, + .value_id = result.scope_result.target_inst_id()}); // If member name lookup finds an associated entity name, and the scope is not // a facet type, perform impl lookup. @@ -308,10 +310,11 @@ static auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id, for (auto base_interface : facet_type_info.impls_constraints) { // Get the witness that `T` implements `base_type_id`. if (base_interface == *assoc_interface) { - witness_inst_id = context.GetOrAddInst( - loc_id, {.type_id = GetSingletonType( - context, SemIR::WitnessType::SingletonInstId), - .facet_value_inst_id = base_id}); + witness_inst_id = GetOrAddInst( + context, loc_id, + {.type_id = GetSingletonType( + context, SemIR::WitnessType::SingletonInstId), + .facet_value_inst_id = base_id}); // TODO: Result will eventually be a facet type witness instead of // an interface witness. Will need to use the index // `*assoc_interface` was found in @@ -366,11 +369,12 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id, return member_id; } - return context.GetOrAddInst( - loc_id, {.type_id = GetSingletonType( - context, SemIR::BoundMethodType::SingletonInstId), - .object_id = base_id, - .function_decl_id = member_id}); + return GetOrAddInst( + context, loc_id, + {.type_id = + GetSingletonType(context, SemIR::BoundMethodType::SingletonInstId), + .object_id = base_id, + .function_decl_id = member_id}); } // Otherwise, if it's a field, form a class element access. @@ -388,10 +392,11 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id, "Non-constant value {0} of unbound element type", context.insts().Get(member_id)); auto index = GetClassElementIndex(context, element_id); - auto access_id = context.GetOrAddInst( - loc_id, {.type_id = unbound_element_type->element_type_id, - .base_id = base_id, - .index = index}); + auto access_id = GetOrAddInst( + context, loc_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) != @@ -477,10 +482,11 @@ auto PerformMemberAccess(Context& context, SemIR::LocId loc_id, if (name_id == field.name_id) { // TODO: Model this as producing a lookup result, and do instance // binding separately. Perhaps a struct type should be a name scope. - return context.GetOrAddInst( - loc_id, {.type_id = field.type_id, - .struct_id = base_id, - .index = SemIR::ElementIndex(i)}); + return GetOrAddInst( + context, loc_id, + {.type_id = field.type_id, + .struct_id = base_id, + .index = SemIR::ElementIndex(i)}); } } CARBON_DIAGNOSTIC(QualifiedExprNameNotFound, Error, @@ -613,10 +619,10 @@ auto PerformTupleAccess(Context& context, SemIR::LocId loc_id, element_type_id = type_block[index_val->getZExtValue()]; auto tuple_index = SemIR::ElementIndex(index_val->getZExtValue()); - return context.GetOrAddInst(loc_id, - {.type_id = element_type_id, - .tuple_id = tuple_inst_id, - .index = tuple_index}); + return GetOrAddInst(context, loc_id, + {.type_id = element_type_id, + .tuple_id = tuple_inst_id, + .index = tuple_index}); } } // namespace Carbon::Check diff --git a/toolchain/check/pattern_match.cpp b/toolchain/check/pattern_match.cpp index 119d70cb7c18..548a9b48a608 100644 --- a/toolchain/check/pattern_match.cpp +++ b/toolchain/check/pattern_match.cpp @@ -146,10 +146,11 @@ static auto InsertHere(Context& context, SemIR::ExprRegionId region_id) context.inst_block_stack().AddInstId(exit_block.front()); return region.result_id; } - return context.AddInst( - loc_id, {.type_id = context.insts().Get(region.result_id).type_id(), - .block_id = region.block_ids.front(), - .result_id = region.result_id}); + return AddInst( + context, loc_id, + {.type_id = context.insts().Get(region.result_id).type_id(), + .block_id = region.block_ids.front(), + .result_id = region.result_id}); } if (context.region_stack().empty()) { context.TODO(loc_id, @@ -157,8 +158,8 @@ static auto InsertHere(Context& context, SemIR::ExprRegionId region_id) "functions."); return SemIR::ErrorInst::SingletonInstId; } - context.AddInst(SemIR::LocIdAndInst::NoLoc( - {.target_id = region.block_ids.front()})); + AddInst(context, SemIR::LocIdAndInst::NoLoc( + {.target_id = region.block_ids.front()})); context.inst_block_stack().Pop(); // TODO: this will cumulatively cost O(MN) running time for M blocks // at the Nth level of the stack. Figure out how to do better. @@ -219,7 +220,7 @@ auto MatchContext::EmitPatternMatch(Context& context, auto bind_name = context.insts().GetAs(bind_name_id); CARBON_CHECK(!bind_name.value_id.has_value()); bind_name.value_id = value_id; - context.ReplaceInstBeforeConstantUse(bind_name_id, bind_name); + ReplaceInstBeforeConstantUse(context, bind_name_id, bind_name); context.inst_block_stack().AddInstId(bind_name_id); break; } @@ -251,8 +252,8 @@ auto MatchContext::EmitPatternMatch(Context& context, return; } auto scrutinee_ref = context.insts().Get(scrutinee_ref_id); - auto new_scrutinee = context.AddInst( - context.insts().GetLocId(scrutinee_ref_id), + auto new_scrutinee = AddInst( + context, context.insts().GetLocId(scrutinee_ref_id), {.type_id = GetPointerType(context, scrutinee_ref.type_id()), .lvalue_id = scrutinee_ref_id}); AddWork( @@ -285,13 +286,13 @@ auto MatchContext::EmitPatternMatch(Context& context, if (param_pattern.runtime_index == SemIR::RuntimeParamIndex::Unknown) { param_pattern.runtime_index = NextRuntimeIndex(); - context.ReplaceInstBeforeConstantUse(entry.pattern_id, - param_pattern); + ReplaceInstBeforeConstantUse(context, entry.pattern_id, + param_pattern); } AddWork( {.pattern_id = param_pattern.subpattern_id, - .scrutinee_id = context.AddInst( - pattern.loc_id, + .scrutinee_id = AddInst( + context, pattern.loc_id, {.type_id = param_pattern.type_id, .runtime_index = param_pattern.runtime_index, .pretty_name_id = GetPrettyName(context, param_pattern)})}); @@ -322,13 +323,13 @@ auto MatchContext::EmitPatternMatch(Context& context, if (param_pattern.runtime_index == SemIR::RuntimeParamIndex::Unknown) { param_pattern.runtime_index = NextRuntimeIndex(); - context.ReplaceInstBeforeConstantUse(entry.pattern_id, - param_pattern); + ReplaceInstBeforeConstantUse(context, entry.pattern_id, + param_pattern); } AddWork( {.pattern_id = param_pattern.subpattern_id, - .scrutinee_id = context.AddInst( - pattern.loc_id, + .scrutinee_id = AddInst( + context, pattern.loc_id, {.type_id = param_pattern.type_id, .runtime_index = param_pattern.runtime_index, .pretty_name_id = GetPrettyName(context, param_pattern)})}); @@ -342,10 +343,11 @@ auto MatchContext::EmitPatternMatch(Context& context, } case CARBON_KIND(SemIR::ReturnSlotPattern return_slot_pattern): { CARBON_CHECK(kind_ == MatchKind::Callee); - auto return_slot_id = context.AddInst( - pattern.loc_id, {.type_id = return_slot_pattern.type_id, - .type_inst_id = return_slot_pattern.type_inst_id, - .storage_id = entry.scrutinee_id}); + auto return_slot_id = AddInst( + context, pattern.loc_id, + {.type_id = return_slot_pattern.type_id, + .type_inst_id = return_slot_pattern.type_inst_id, + .storage_id = entry.scrutinee_id}); bool already_in_lookup = context.scope_stack() .LookupOrAddName(SemIR::NameId::ReturnSlot, return_slot_id) @@ -367,8 +369,8 @@ auto MatchContext::EmitPatternMatch(Context& context, Initialize(context, pattern.loc_id, var_id, entry.scrutinee_id); // TODO: Consider using different instruction kinds for assignment // versus initialization. - context.AddInst(pattern.loc_id, - {.lhs_id = var_id, .rhs_id = init_id}); + AddInst(context, pattern.loc_id, + {.lhs_id = var_id, .rhs_id = init_id}); } AddWork( {.pattern_id = var_pattern.subpattern_id, .scrutinee_id = var_id}); diff --git a/toolchain/check/pending_block.h b/toolchain/check/pending_block.h index 8999cbd591a4..aa19c78763cc 100644 --- a/toolchain/check/pending_block.h +++ b/toolchain/check/pending_block.h @@ -7,6 +7,7 @@ #include "llvm/ADT/SmallVector.h" #include "toolchain/check/context.h" +#include "toolchain/check/inst.h" #include "toolchain/sem_ir/inst.h" namespace Carbon::Check { @@ -42,7 +43,7 @@ class PendingBlock { template auto AddInst(LocT loc_id, InstT inst) -> SemIR::InstId { - auto inst_id = context_.AddInstInNoBlock(loc_id, inst); + auto inst_id = AddInstInNoBlock(context_, loc_id, inst); insts_.push_back(inst_id); return inst_id; } @@ -65,8 +66,8 @@ class PendingBlock { if (insts_.empty()) { // 1) The block is empty. Replace `target_id` with an empty splice // pointing at `value_id`. - context_.ReplaceLocIdAndInstBeforeConstantUse( - target_id, + ReplaceLocIdAndInstBeforeConstantUse( + context_, target_id, SemIR::LocIdAndInst( value.loc_id, SemIR::SpliceBlock{.type_id = value.inst.type_id(), @@ -75,11 +76,11 @@ class PendingBlock { } else if (insts_.size() == 1 && insts_[0] == value_id) { // 2) The block is {value_id}. Replace `target_id` with the instruction // referred to by `value_id`. This is intended to be the common case. - context_.ReplaceLocIdAndInstBeforeConstantUse(target_id, value); + ReplaceLocIdAndInstBeforeConstantUse(context_, target_id, value); } else { // 3) Anything else: splice it into the IR, replacing `target_id`. - context_.ReplaceLocIdAndInstBeforeConstantUse( - target_id, + ReplaceLocIdAndInstBeforeConstantUse( + context_, target_id, SemIR::LocIdAndInst( value.loc_id, SemIR::SpliceBlock{.type_id = value.inst.type_id(), diff --git a/toolchain/check/pointer_dereference.cpp b/toolchain/check/pointer_dereference.cpp index 8f437110a420..2bfb74f45763 100644 --- a/toolchain/check/pointer_dereference.cpp +++ b/toolchain/check/pointer_dereference.cpp @@ -7,6 +7,7 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" +#include "toolchain/check/inst.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/ids.h" @@ -32,8 +33,8 @@ auto PerformPointerDereference( } else if (type_id != SemIR::ErrorInst::SingletonTypeId) { diagnose_not_pointer(type_id); } - return context.AddInst( - node_id, {.type_id = result_type_id, .pointer_id = base_id}); + return AddInst( + context, 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 2088ad0ccdd2..2ab0d1de133e 100644 --- a/toolchain/check/return.cpp +++ b/toolchain/check/return.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/convert.h" +#include "toolchain/check/inst.h" namespace Carbon::Check { @@ -126,7 +127,7 @@ auto BuildReturnWithNoExpr(Context& context, Parse::ReturnStatementId node_id) diag.Emit(); } - context.AddInst(node_id, {}); + AddInst(context, node_id, {}); } auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, @@ -167,8 +168,8 @@ auto BuildReturnWithExpr(Context& context, Parse::ReturnStatementId node_id, ConvertToValueOfType(context, node_id, expr_id, return_info.type_id); } - context.AddInst( - node_id, {.expr_id = expr_id, .dest_id = return_slot_id}); + AddInst(context, node_id, + {.expr_id = expr_id, .dest_id = return_slot_id}); } auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id) @@ -192,8 +193,9 @@ auto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id) return_slot_id = SemIR::InstId::None; } - context.AddInst( - node_id, {.expr_id = returned_var_id, .dest_id = return_slot_id}); + AddInst( + context, node_id, + {.expr_id = returned_var_id, .dest_id = return_slot_id}); } } // namespace Carbon::Check diff --git a/toolchain/check/subpattern.cpp b/toolchain/check/subpattern.cpp index e49b418fa91e..c400c92f23b0 100644 --- a/toolchain/check/subpattern.cpp +++ b/toolchain/check/subpattern.cpp @@ -4,6 +4,8 @@ #include "toolchain/check/subpattern.h" +#include "toolchain/check/inst.h" + namespace Carbon::Check { auto BeginSubpattern(Context& context) -> void { @@ -16,8 +18,9 @@ auto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id) if (context.region_stack().PeekRegion().size() > 1) { // End the exit block with a branch to a successor block, whose contents // will be determined later. - context.AddInst(SemIR::LocIdAndInst::NoLoc( - {.target_id = context.inst_blocks().AddDefaultValue()})); + AddInst(context, + SemIR::LocIdAndInst::NoLoc( + {.target_id = context.inst_blocks().AddDefaultValue()})); } else { // This single-block region will be inserted as a SpliceBlock, so we don't // need control flow out of it. diff --git a/toolchain/check/type_completion.cpp b/toolchain/check/type_completion.cpp index 95b6ecc386c9..887a844bf432 100644 --- a/toolchain/check/type_completion.cpp +++ b/toolchain/check/type_completion.cpp @@ -7,6 +7,7 @@ #include "llvm/ADT/SmallVector.h" #include "toolchain/base/kind_switch.h" #include "toolchain/check/generic.h" +#include "toolchain/check/inst.h" #include "toolchain/check/type.h" namespace Carbon::Check { @@ -489,11 +490,13 @@ auto RequireCompleteType(Context& context, SemIR::TypeId type_id, // specific type to be complete. if (type_id.AsConstantId().is_symbolic()) { // TODO: Deduplicate these. - context.AddInstInNoBlock(SemIR::LocIdAndInst( - loc_id, SemIR::RequireCompleteType{ - .type_id = GetSingletonType( - context, SemIR::WitnessType::SingletonInstId), - .complete_type_id = type_id})); + AddInstInNoBlock( + context, + SemIR::LocIdAndInst( + loc_id, SemIR::RequireCompleteType{ + .type_id = GetSingletonType( + context, SemIR::WitnessType::SingletonInstId), + .complete_type_id = type_id})); } return true; diff --git a/toolchain/docs/adding_features.md b/toolchain/docs/adding_features.md index 099841c98558..be62da9fd268 100644 --- a/toolchain/docs/adding_features.md +++ b/toolchain/docs/adding_features.md @@ -285,7 +285,7 @@ If the resulting SemIR needs a new instruction: field, as in: ``` - SemIR::InstId inst_id = context.AddInst( + SemIR::InstId inst_id = AddInst(context, node_id, {.type_id = SemIR::TypeType::SingletonTypeId, ...}); ``` @@ -302,9 +302,9 @@ If the resulting SemIR needs a new instruction: ``` SemIR::TypeId witness_type_id = - GetSingletonType(context,SemIR::WitnessType::SingletonInstId); - SemIR::InstId inst_id = context.AddInst( - node_id, {.type_id = witness_type_id, ...}); + GetSingletonType(context, SemIR::WitnessType::SingletonInstId); + SemIR::InstId inst_id = AddInst( + context, node_id, {.type_id = witness_type_id, ...}); ``` - Instructions without types may still be used as arguments to