diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 41891b8630d6..cfb416f165a5 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -63,18 +63,16 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, is_template); if (is_generic) { 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})); + context, name_node, + SemIR::BindSymbolicName{.type_id = cast_type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None}); } else { - 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})); + bind_id = + AddInstInNoBlock(context, name_node, + SemIR::BindName{.type_id = cast_type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::None}); } } @@ -195,10 +193,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id, .decl_block_id = SemIR::InstBlockId::None}; auto decl_id = AddPlaceholderInstInNoBlock( context, - SemIR::LocIdAndInst( - context.parse_tree().As( - node_id), - assoc_const_decl)); + 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(), diff --git a/toolchain/check/handle_choice.cpp b/toolchain/check/handle_choice.cpp index 245d4debe229..abde191eec56 100644 --- a/toolchain/check/handle_choice.cpp +++ b/toolchain/check/handle_choice.cpp @@ -54,8 +54,7 @@ auto HandleParseNode(Context& context, Parse::ChoiceDefinitionStartId node_id) SemIR::ClassDecl{.type_id = SemIR::TypeType::SingletonTypeId, .class_id = SemIR::ClassId::None, .decl_block_id = decl_block_id}; - auto class_decl_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, class_decl)); + auto class_decl_id = AddPlaceholderInst(context, node_id, class_decl); context.decl_name_stack().AddNameOrDiagnose(name_context, class_decl_id, SemIR::AccessKind::Public); @@ -193,12 +192,11 @@ static auto MakeLetBinding(Context& context, const ChoiceInfo& choice_info, -> void { SemIR::InstId discriminant_value_id = [&] { if (choice_info.num_alternative_bits == 0) { - return AddInst(context, SemIR::LocIdAndInst( - binding.node_id, - SemIR::TupleLiteral{ - .type_id = GetTupleType(context, {}), - .elements_id = SemIR::InstBlockId::Empty, - })); + return AddInst(context, binding.node_id, + SemIR::TupleLiteral{ + .type_id = GetTupleType(context, {}), + .elements_id = SemIR::InstBlockId::Empty, + }); } else { return MakeIntLiteral(context, binding.node_id, context.ints().Add(alternative_index)); @@ -210,30 +208,28 @@ static auto MakeLetBinding(Context& context, const ChoiceInfo& choice_info, auto self_value_id = ConvertToValueOfType( context, binding.node_id, - AddInst(context, SemIR::LocIdAndInst( - binding.node_id, - SemIR::StructLiteral{ - .type_id = choice_info.self_struct_type_id, - .elements_id = - [&] { - context.inst_block_stack().Push(); - context.inst_block_stack().AddInstId( - discriminant_value_id); - return context.inst_block_stack().Pop(); - }(), - })), + AddInst(context, binding.node_id, + SemIR::StructLiteral{ + .type_id = choice_info.self_struct_type_id, + .elements_id = + [&] { + context.inst_block_stack().Push(); + context.inst_block_stack().AddInstId( + discriminant_value_id); + return context.inst_block_stack().Pop(); + }(), + }), choice_info.self_type_id); auto entity_name_id = context.entity_names().Add( {.name_id = binding.name_component.name_id, .parent_scope_id = choice_info.name_scope_id}); - auto bind_name_id = AddInst( - context, SemIR::LocIdAndInst(binding.node_id, - SemIR::BindName{ - .type_id = choice_info.self_type_id, - .entity_name_id = entity_name_id, - .value_id = self_value_id, - })); + auto bind_name_id = AddInst(context, binding.node_id, + SemIR::BindName{ + .type_id = choice_info.self_type_id, + .entity_name_id = entity_name_id, + .value_id = self_value_id, + }); context.name_scopes() .Get(choice_info.name_scope_id) .AddRequired({.name_id = binding.name_component.name_id, diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 173c578e1901..598dc38346fd 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -222,8 +222,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, SemIR::ClassDecl{.type_id = SemIR::TypeType::SingletonTypeId, .class_id = SemIR::ClassId::None, .decl_block_id = decl_block_id}; - auto class_decl_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, class_decl)); + auto class_decl_id = AddPlaceholderInst(context, node_id, class_decl); // TODO: Store state regarding is_extern. SemIR::Class class_info = { diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index ed5cb998ba64..e6e069a1905b 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -464,8 +464,7 @@ static auto BuildFunctionDecl(Context& context, SemIR::FunctionDecl function_decl = {SemIR::TypeId::None, SemIR::FunctionId::None, context.inst_block_stack().Pop()}; - auto decl_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, function_decl)); + auto decl_id = AddPlaceholderInst(context, node_id, function_decl); RequestVtableIfVirtual(context, node_id, virtual_modifier, parent_scope_inst, decl_id); diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 63e1becabee2..f896b7fd21d5 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -380,8 +380,7 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id, // Add the impl declaration. SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None, .decl_block_id = decl_block_id}; - auto impl_decl_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, impl_decl)); + auto impl_decl_id = AddPlaceholderInst(context, node_id, impl_decl); SemIR::Impl impl_info = {name_context.MakeEntityWithParamsBase( name, impl_decl_id, diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index a7390bf33200..a17adadc64f5 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -55,8 +55,7 @@ static auto BuildInterfaceDecl(Context& context, auto interface_decl = SemIR::InterfaceDecl{SemIR::TypeType::SingletonTypeId, SemIR::InterfaceId::None, decl_block_id}; - auto interface_decl_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, interface_decl)); + auto interface_decl_id = AddPlaceholderInst(context, node_id, interface_decl); SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase( name, interface_decl_id, /*is_extern=*/false, diff --git a/toolchain/check/handle_let_and_var.cpp b/toolchain/check/handle_let_and_var.cpp index f24627435c3c..e9bdb4a60e4e 100644 --- a/toolchain/check/handle_let_and_var.cpp +++ b/toolchain/check/handle_let_and_var.cpp @@ -119,15 +119,12 @@ static auto GetOrAddStorage(Context& context, SemIR::InstId var_pattern_id) } auto pattern = context.insts().GetWithLocId(var_pattern_id); - return AddInst( - context, - SemIR::LocIdAndInst( - pattern.loc_id, - SemIR::VarStorage{ - .type_id = pattern.inst.type_id(), - .pretty_name_id = SemIR::GetPrettyNameFromPatternId( - context.sem_ir(), - pattern.inst.As().subpattern_id)})); + return AddInst(context, pattern.loc_id, + SemIR::VarStorage{ + .type_id = pattern.inst.type_id(), + .pretty_name_id = SemIR::GetPrettyNameFromPatternId( + context.sem_ir(), + pattern.inst.As().subpattern_id)}); } auto HandleParseNode(Context& context, Parse::VariablePatternId node_id) diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index bd1028776506..32dc9394e942 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -42,8 +42,7 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { auto namespace_inst = SemIR::Namespace{ GetSingletonType(context, SemIR::NamespaceType::SingletonInstId), SemIR::NameScopeId::None, SemIR::InstId::None}; - auto namespace_id = - AddPlaceholderInst(context, SemIR::LocIdAndInst(node_id, namespace_inst)); + auto namespace_id = AddPlaceholderInst(context, node_id, namespace_inst); SemIR::ScopeLookupResult lookup_result = context.decl_name_stack().LookupOrAddName(name_context, namespace_id, diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index 8656266f4d56..355c946e112d 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -226,8 +226,8 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, auto function_decl = SemIR::FunctionDecl{ SemIR::TypeId::None, SemIR::FunctionId::None, SemIR::InstBlockId::Empty}; - auto decl_id = AddPlaceholderInst( - context, SemIR::LocIdAndInst(Parse::NodeId::None, function_decl)); + auto decl_id = + AddPlaceholderInst(context, Parse::NodeId::None, function_decl); auto function_info = SemIR::Function{ {.name_id = name_id, diff --git a/toolchain/check/inst.h b/toolchain/check/inst.h index e0c105deedcf..f69c17ce31e1 100644 --- a/toolchain/check/inst.h +++ b/toolchain/check/inst.h @@ -90,6 +90,13 @@ auto AddPatternInst(Context& context, auto AddPlaceholderInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; +// Convenience for AddPlaceholderInst with typed nodes. +template +auto AddPlaceholderInst(Context& context, LocT loc, InstT inst) + -> SemIR::InstId { + return AddPlaceholderInst(context, SemIR::LocIdAndInst(loc, inst)); +} + // 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`. @@ -97,6 +104,13 @@ auto AddPlaceholderInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId; +// Convenience for AddPlaceholderInstInNoBlock with typed nodes. +template +auto AddPlaceholderInstInNoBlock(Context& context, LocT loc, InstT inst) + -> SemIR::InstId { + return AddPlaceholderInstInNoBlock(context, SemIR::LocIdAndInst(loc, 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 diff --git a/toolchain/check/pending_block.h b/toolchain/check/pending_block.h index aa19c78763cc..3475e083a987 100644 --- a/toolchain/check/pending_block.h +++ b/toolchain/check/pending_block.h @@ -8,6 +8,7 @@ #include "llvm/ADT/SmallVector.h" #include "toolchain/check/context.h" #include "toolchain/check/inst.h" +#include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" namespace Carbon::Check { @@ -59,35 +60,22 @@ class PendingBlock { // Replace the instruction at target_id with the instructions in this block. // The new value for target_id should be value_id. auto MergeReplacing(SemIR::InstId target_id, SemIR::InstId value_id) -> void { - auto value = context_.insts().GetWithLocId(value_id); + SemIR::LocIdAndInst value = context_.insts().GetWithLocId(value_id); - // There are three cases here: - - if (insts_.empty()) { - // 1) The block is empty. Replace `target_id` with an empty splice - // pointing at `value_id`. - ReplaceLocIdAndInstBeforeConstantUse( - context_, target_id, - SemIR::LocIdAndInst( - value.loc_id, - SemIR::SpliceBlock{.type_id = value.inst.type_id(), - .block_id = SemIR::InstBlockId::Empty, - .result_id = value_id})); - } else if (insts_.size() == 1 && insts_[0] == value_id) { - // 2) The block is {value_id}. Replace `target_id` with the instruction + if (insts_.size() == 1 && insts_[0] == value_id) { + // The block is {value_id}. Replace `target_id` with the instruction // referred to by `value_id`. This is intended to be the common case. - ReplaceLocIdAndInstBeforeConstantUse(context_, target_id, value); } else { - // 3) Anything else: splice it into the IR, replacing `target_id`. - ReplaceLocIdAndInstBeforeConstantUse( - context_, target_id, - SemIR::LocIdAndInst( - value.loc_id, - SemIR::SpliceBlock{.type_id = value.inst.type_id(), - .block_id = context_.inst_blocks().Add(insts_), - .result_id = value_id})); + // Anything else: splice it into the IR, replacing `target_id`. This + // includes empty blocks, which `Add` handles. + value.inst = + SemIR::SpliceBlock{.type_id = value.inst.type_id(), + .block_id = context_.inst_blocks().Add(insts_), + .result_id = value_id}; } + ReplaceLocIdAndInstBeforeConstantUse(context_, target_id, value); + // Prepare to stash more pending instructions. insts_.clear(); } diff --git a/toolchain/check/type_completion.cpp b/toolchain/check/type_completion.cpp index 68c18299357c..0ffce0fe1b18 100644 --- a/toolchain/check/type_completion.cpp +++ b/toolchain/check/type_completion.cpp @@ -557,13 +557,11 @@ auto RequireCompleteType(Context& context, SemIR::TypeId type_id, // specific type to be complete. if (type_id.is_symbolic()) { // TODO: Deduplicate these. - AddInstInNoBlock( - context, - SemIR::LocIdAndInst( - loc_id, SemIR::RequireCompleteType{ - .type_id = GetSingletonType( - context, SemIR::WitnessType::SingletonInstId), - .complete_type_id = type_id})); + AddInstInNoBlock(context, loc_id, + SemIR::RequireCompleteType{ + .type_id = GetSingletonType( + context, SemIR::WitnessType::SingletonInstId), + .complete_type_id = type_id}); } return true;