Kaynağa Gözat

Rename `SemIR::Node` to `SemIR::Inst` (#3355)

And generally replace "node" by "inst" in the code and "instruction" in
comments.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
josh11b 2 yıl önce
ebeveyn
işleme
7edfd8e02a
63 değiştirilmiş dosya ile 2138 ekleme ve 2117 silme
  1. 4 4
      toolchain/check/BUILD
  2. 2 2
      toolchain/check/check.cpp
  3. 155 155
      toolchain/check/context.cpp
  4. 84 83
      toolchain/check/context.h
  5. 179 179
      toolchain/check/convert.cpp
  6. 21 21
      toolchain/check/convert.h
  7. 23 22
      toolchain/check/declaration_name_stack.cpp
  8. 12 12
      toolchain/check/declaration_name_stack.h
  9. 9 9
      toolchain/check/handle_array.cpp
  10. 10 10
      toolchain/check/handle_call_expression.cpp
  11. 15 14
      toolchain/check/handle_class.cpp
  12. 27 27
      toolchain/check/handle_function.cpp
  13. 4 4
      toolchain/check/handle_if_expression.cpp
  14. 7 7
      toolchain/check/handle_if_statement.cpp
  15. 33 33
      toolchain/check/handle_index.cpp
  16. 5 5
      toolchain/check/handle_let.cpp
  17. 9 9
      toolchain/check/handle_literal.cpp
  18. 13 13
      toolchain/check/handle_loop_statement.cpp
  19. 47 46
      toolchain/check/handle_name.cpp
  20. 2 2
      toolchain/check/handle_namespace.cpp
  21. 29 29
      toolchain/check/handle_operator.cpp
  22. 5 5
      toolchain/check/handle_paren.cpp
  23. 19 19
      toolchain/check/handle_pattern_binding.cpp
  24. 11 11
      toolchain/check/handle_statement.cpp
  25. 8 8
      toolchain/check/handle_struct.cpp
  26. 6 6
      toolchain/check/handle_variable.cpp
  27. 12 13
      toolchain/check/inst_block_stack.cpp
  28. 38 36
      toolchain/check/node_block_stack.h
  29. 3 3
      toolchain/check/node_stack.cpp
  30. 40 38
      toolchain/check/node_stack.h
  31. 31 31
      toolchain/check/pending_block.h
  32. 11 11
      toolchain/check/testdata/basics/builtin_nodes.carbon
  33. 14 14
      toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon
  34. 14 14
      toolchain/check/testdata/basics/multifile_raw_ir.carbon
  35. 52 52
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  36. 52 52
      toolchain/check/testdata/basics/raw_ir.carbon
  37. 4 4
      toolchain/check/testdata/basics/verbose.carbon
  38. 2 2
      toolchain/check/testdata/class/fail_redefinition.carbon
  39. 1 1
      toolchain/check/testdata/class/nested_name.carbon
  40. 2 2
      toolchain/lower/BUILD
  41. 33 33
      toolchain/lower/file_context.cpp
  42. 4 4
      toolchain/lower/file_context.h
  43. 17 17
      toolchain/lower/function_context.cpp
  44. 29 29
      toolchain/lower/function_context.h
  45. 185 185
      toolchain/lower/handle.cpp
  46. 28 28
      toolchain/lower/handle_expression_category.cpp
  47. 21 21
      toolchain/lower/handle_type.cpp
  48. 13 13
      toolchain/sem_ir/BUILD
  49. 1 1
      toolchain/sem_ir/builtin_kind.def
  50. 1 1
      toolchain/sem_ir/builtin_kind.h
  51. 90 89
      toolchain/sem_ir/file.cpp
  52. 56 54
      toolchain/sem_ir/file.h
  53. 168 167
      toolchain/sem_ir/formatter.cpp
  54. 30 30
      toolchain/sem_ir/ids.h
  55. 4 4
      toolchain/sem_ir/inst.cpp
  56. 69 66
      toolchain/sem_ir/inst.h
  57. 11 11
      toolchain/sem_ir/node_kind.cpp
  58. 62 62
      toolchain/sem_ir/node_kind.def
  59. 45 42
      toolchain/sem_ir/node_kind.h
  60. 135 134
      toolchain/sem_ir/typed_insts.h
  61. 71 70
      toolchain/sem_ir/typed_nodes_test.cpp
  62. 35 33
      toolchain/sem_ir/value_stores.h
  63. 15 15
      toolchain/sem_ir/yaml_test.cpp

+ 4 - 4
toolchain/check/BUILD

@@ -23,7 +23,7 @@ cc_library(
         "//common:vlog",
         "//toolchain/parse:node_kind",
         "//toolchain/parse:tree",
-        "//toolchain/sem_ir:node",
+        "//toolchain/sem_ir:inst",
         "@llvm-project//llvm:Support",
     ],
 )
@@ -35,7 +35,7 @@ cc_library(
         "context.cpp",
         "convert.cpp",
         "declaration_name_stack.cpp",
-        "node_block_stack.cpp",
+        "inst_block_stack.cpp",
     ] +
     # Glob handler files to avoid missing any.
     glob([
@@ -66,8 +66,8 @@ cc_library(
         "//toolchain/sem_ir:builtin_kind",
         "//toolchain/sem_ir:entry_point",
         "//toolchain/sem_ir:file",
-        "//toolchain/sem_ir:node",
-        "//toolchain/sem_ir:node_kind",
+        "//toolchain/sem_ir:inst",
+        "//toolchain/sem_ir:inst_kind",
         "@llvm-project//llvm:Support",
     ],
 )

+ 2 - 2
toolchain/check/check.cpp

@@ -27,7 +27,7 @@ auto CheckParseTree(SharedValueStores& value_stores,
       [&](llvm::raw_ostream& output) { context.PrintForStackDump(output); });
 
   // Add a block for the Parse::Tree.
-  context.node_block_stack().Push();
+  context.inst_block_stack().Push();
   context.PushScope();
 
   // Loops over all nodes in the tree. On some errors, this may return early,
@@ -51,7 +51,7 @@ auto CheckParseTree(SharedValueStores& value_stores,
   }
 
   // Pop information for the file-level scope.
-  sem_ir.set_top_node_block_id(context.node_block_stack().Pop());
+  sem_ir.set_top_inst_block_id(context.inst_block_stack().Pop());
   context.PopScope();
 
   context.VerifyOnFinish();

+ 155 - 155
toolchain/check/context.cpp

@@ -15,7 +15,7 @@
 #include "toolchain/lex/tokenized_buffer.h"
 #include "toolchain/parse/node_kind.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Check {
@@ -29,15 +29,15 @@ Context::Context(const Lex::TokenizedBuffer& tokens, DiagnosticEmitter& emitter,
       sem_ir_(&sem_ir),
       vlog_stream_(vlog_stream),
       node_stack_(parse_tree, vlog_stream),
-      node_block_stack_("node_block_stack_", sem_ir, vlog_stream),
+      inst_block_stack_("inst_block_stack_", sem_ir, vlog_stream),
       params_or_args_stack_("params_or_args_stack_", sem_ir, vlog_stream),
       args_type_info_stack_("args_type_info_stack_", sem_ir, vlog_stream),
       declaration_name_stack_(this) {
   // Inserts the "Error" and "Type" types as "used types" so that
   // canonicalization can skip them. We don't emit either for lowering.
-  canonical_types_.insert({SemIR::NodeId::BuiltinError, SemIR::TypeId::Error});
+  canonical_types_.insert({SemIR::InstId::BuiltinError, SemIR::TypeId::Error});
   canonical_types_.insert(
-      {SemIR::NodeId::BuiltinTypeType, SemIR::TypeId::TypeType});
+      {SemIR::InstId::BuiltinTypeType, SemIR::TypeId::TypeType});
 }
 
 auto Context::TODO(Parse::Node parse_node, std::string label) -> bool {
@@ -54,28 +54,28 @@ auto Context::VerifyOnFinish() -> void {
   // node_stack_ will still contain top-level entities.
   CARBON_CHECK(name_lookup_.empty()) << name_lookup_.size();
   CARBON_CHECK(scope_stack_.empty()) << scope_stack_.size();
-  CARBON_CHECK(node_block_stack_.empty()) << node_block_stack_.size();
+  CARBON_CHECK(inst_block_stack_.empty()) << inst_block_stack_.size();
   CARBON_CHECK(params_or_args_stack_.empty()) << params_or_args_stack_.size();
 }
 
-auto Context::AddNode(SemIR::Node node) -> SemIR::NodeId {
-  auto node_id = node_block_stack_.AddNode(node);
-  CARBON_VLOG() << "AddNode: " << node << "\n";
-  return node_id;
+auto Context::AddInst(SemIR::Inst inst) -> SemIR::InstId {
+  auto inst_id = inst_block_stack_.AddInst(inst);
+  CARBON_VLOG() << "AddInst: " << inst << "\n";
+  return inst_id;
 }
 
-auto Context::AddNodeAndPush(Parse::Node parse_node, SemIR::Node node) -> void {
-  auto node_id = AddNode(node);
-  node_stack_.Push(parse_node, node_id);
+auto Context::AddInstAndPush(Parse::Node parse_node, SemIR::Inst inst) -> void {
+  auto inst_id = AddInst(inst);
+  node_stack_.Push(parse_node, inst_id);
 }
 
 auto Context::DiagnoseDuplicateName(Parse::Node parse_node,
-                                    SemIR::NodeId prev_def_id) -> void {
+                                    SemIR::InstId prev_def_id) -> void {
   CARBON_DIAGNOSTIC(NameDeclarationDuplicate, Error,
                     "Duplicate name being declared in the same scope.");
   CARBON_DIAGNOSTIC(NameDeclarationPrevious, Note,
                     "Name is previously declared here.");
-  auto prev_def = nodes().Get(prev_def_id);
+  auto prev_def = insts().Get(prev_def_id);
   emitter_->Build(parse_node, NameDeclarationDuplicate)
       .Note(prev_def.parse_node(), NameDeclarationPrevious)
       .Emit();
@@ -97,16 +97,16 @@ auto Context::NoteIncompleteClass(SemIR::ClassId class_id,
   const auto& class_info = classes().Get(class_id);
   CARBON_CHECK(!class_info.is_defined()) << "Class is not incomplete";
   if (class_info.definition_id.is_valid()) {
-    builder.Note(nodes().Get(class_info.definition_id).parse_node(),
+    builder.Note(insts().Get(class_info.definition_id).parse_node(),
                  ClassIncompleteWithinDefinition);
   } else {
-    builder.Note(nodes().Get(class_info.declaration_id).parse_node(),
+    builder.Note(insts().Get(class_info.declaration_id).parse_node(),
                  ClassForwardDeclaredHere);
   }
 }
 
 auto Context::AddNameToLookup(Parse::Node name_node, StringId name_id,
-                              SemIR::NodeId target_id) -> void {
+                              SemIR::InstId target_id) -> void {
   if (current_scope().names.insert(name_id).second) {
     name_lookup_[name_id].push_back(target_id);
   } else {
@@ -116,14 +116,14 @@ auto Context::AddNameToLookup(Parse::Node name_node, StringId name_id,
 
 auto Context::LookupName(Parse::Node parse_node, StringId name_id,
                          SemIR::NameScopeId scope_id, bool print_diagnostics)
-    -> SemIR::NodeId {
+    -> SemIR::InstId {
   if (scope_id == SemIR::NameScopeId::Invalid) {
     auto it = name_lookup_.find(name_id);
     if (it == name_lookup_.end()) {
       if (print_diagnostics) {
         DiagnoseNameNotFound(parse_node, name_id);
       }
-      return SemIR::NodeId::BuiltinError;
+      return SemIR::InstId::BuiltinError;
     }
     CARBON_CHECK(!it->second.empty())
         << "Should have been erased: " << strings().Get(name_id);
@@ -137,17 +137,17 @@ auto Context::LookupName(Parse::Node parse_node, StringId name_id,
       if (print_diagnostics) {
         DiagnoseNameNotFound(parse_node, name_id);
       }
-      return SemIR::NodeId::BuiltinError;
+      return SemIR::InstId::BuiltinError;
     }
 
     return it->second;
   }
 }
 
-auto Context::PushScope(SemIR::NodeId scope_node_id,
+auto Context::PushScope(SemIR::InstId scope_inst_id,
                         SemIR::NameScopeId scope_id) -> void {
   scope_stack_.push_back(
-      {.scope_node_id = scope_node_id, .scope_id = scope_id});
+      {.scope_inst_id = scope_inst_id, .scope_id = scope_id});
 }
 
 auto Context::PopScope() -> void {
@@ -163,34 +163,34 @@ auto Context::PopScope() -> void {
   }
 }
 
-auto Context::FollowNameReferences(SemIR::NodeId node_id) -> SemIR::NodeId {
-  while (auto name_ref = nodes().Get(node_id).TryAs<SemIR::NameReference>()) {
-    node_id = name_ref->value_id;
+auto Context::FollowNameReferences(SemIR::InstId inst_id) -> SemIR::InstId {
+  while (auto name_ref = insts().Get(inst_id).TryAs<SemIR::NameReference>()) {
+    inst_id = name_ref->value_id;
   }
-  return node_id;
+  return inst_id;
 }
 
-auto Context::GetConstantValue(SemIR::NodeId node_id) -> SemIR::NodeId {
-  // TODO: The constant value of a node should be computed as we build the
-  // node, or at least cached once computed.
+auto Context::GetConstantValue(SemIR::InstId inst_id) -> SemIR::InstId {
+  // TODO: The constant value of an instruction should be computed as we build
+  // the instruction, or at least cached once computed.
   while (true) {
-    auto node = nodes().Get(node_id);
-    switch (node.kind()) {
+    auto inst = insts().Get(inst_id);
+    switch (inst.kind()) {
       case SemIR::NameReference::Kind:
-        node_id = node.As<SemIR::NameReference>().value_id;
+        inst_id = inst.As<SemIR::NameReference>().value_id;
         break;
 
       case SemIR::BindName::Kind:
-        node_id = node.As<SemIR::BindName>().value_id;
+        inst_id = inst.As<SemIR::BindName>().value_id;
         break;
 
       case SemIR::Field::Kind:
       case SemIR::FunctionDeclaration::Kind:
-        return node_id;
+        return inst_id;
 
       default:
         // TODO: Handle the remaining cases.
-        return SemIR::NodeId::Invalid;
+        return SemIR::InstId::Invalid;
     }
   }
 }
@@ -198,30 +198,30 @@ auto Context::GetConstantValue(SemIR::NodeId node_id) -> SemIR::NodeId {
 template <typename BranchNode, typename... Args>
 static auto AddDominatedBlockAndBranchImpl(Context& context,
                                            Parse::Node parse_node, Args... args)
-    -> SemIR::NodeBlockId {
-  if (!context.node_block_stack().is_current_block_reachable()) {
-    return SemIR::NodeBlockId::Unreachable;
+    -> SemIR::InstBlockId {
+  if (!context.inst_block_stack().is_current_block_reachable()) {
+    return SemIR::InstBlockId::Unreachable;
   }
-  auto block_id = context.node_blocks().AddDefaultValue();
-  context.AddNode(BranchNode{parse_node, block_id, args...});
+  auto block_id = context.inst_blocks().AddDefaultValue();
+  context.AddInst(BranchNode{parse_node, block_id, args...});
   return block_id;
 }
 
 auto Context::AddDominatedBlockAndBranch(Parse::Node parse_node)
-    -> SemIR::NodeBlockId {
+    -> SemIR::InstBlockId {
   return AddDominatedBlockAndBranchImpl<SemIR::Branch>(*this, parse_node);
 }
 
 auto Context::AddDominatedBlockAndBranchWithArg(Parse::Node parse_node,
-                                                SemIR::NodeId arg_id)
-    -> SemIR::NodeBlockId {
+                                                SemIR::InstId arg_id)
+    -> SemIR::InstBlockId {
   return AddDominatedBlockAndBranchImpl<SemIR::BranchWithArg>(*this, parse_node,
                                                               arg_id);
 }
 
 auto Context::AddDominatedBlockAndBranchIf(Parse::Node parse_node,
-                                           SemIR::NodeId cond_id)
-    -> SemIR::NodeBlockId {
+                                           SemIR::InstId cond_id)
+    -> SemIR::InstBlockId {
   return AddDominatedBlockAndBranchImpl<SemIR::BranchIf>(*this, parse_node,
                                                          cond_id);
 }
@@ -230,73 +230,73 @@ auto Context::AddConvergenceBlockAndPush(Parse::Node parse_node, int num_blocks)
     -> void {
   CARBON_CHECK(num_blocks >= 2) << "no convergence";
 
-  SemIR::NodeBlockId new_block_id = SemIR::NodeBlockId::Unreachable;
+  SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable;
   for ([[maybe_unused]] auto _ : llvm::seq(num_blocks)) {
-    if (node_block_stack().is_current_block_reachable()) {
-      if (new_block_id == SemIR::NodeBlockId::Unreachable) {
-        new_block_id = node_blocks().AddDefaultValue();
+    if (inst_block_stack().is_current_block_reachable()) {
+      if (new_block_id == SemIR::InstBlockId::Unreachable) {
+        new_block_id = inst_blocks().AddDefaultValue();
       }
-      AddNode(SemIR::Branch{parse_node, new_block_id});
+      AddInst(SemIR::Branch{parse_node, new_block_id});
     }
-    node_block_stack().Pop();
+    inst_block_stack().Pop();
   }
-  node_block_stack().Push(new_block_id);
+  inst_block_stack().Push(new_block_id);
 }
 
 auto Context::AddConvergenceBlockWithArgAndPush(
-    Parse::Node parse_node, std::initializer_list<SemIR::NodeId> block_args)
-    -> SemIR::NodeId {
+    Parse::Node parse_node, std::initializer_list<SemIR::InstId> block_args)
+    -> SemIR::InstId {
   CARBON_CHECK(block_args.size() >= 2) << "no convergence";
 
-  SemIR::NodeBlockId new_block_id = SemIR::NodeBlockId::Unreachable;
+  SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable;
   for (auto arg_id : block_args) {
-    if (node_block_stack().is_current_block_reachable()) {
-      if (new_block_id == SemIR::NodeBlockId::Unreachable) {
-        new_block_id = node_blocks().AddDefaultValue();
+    if (inst_block_stack().is_current_block_reachable()) {
+      if (new_block_id == SemIR::InstBlockId::Unreachable) {
+        new_block_id = inst_blocks().AddDefaultValue();
       }
-      AddNode(SemIR::BranchWithArg{parse_node, new_block_id, arg_id});
+      AddInst(SemIR::BranchWithArg{parse_node, new_block_id, arg_id});
     }
-    node_block_stack().Pop();
+    inst_block_stack().Pop();
   }
-  node_block_stack().Push(new_block_id);
+  inst_block_stack().Push(new_block_id);
 
   // Acquire the result value.
-  SemIR::TypeId result_type_id = nodes().Get(*block_args.begin()).type_id();
-  return AddNode(SemIR::BlockArg{parse_node, result_type_id, new_block_id});
+  SemIR::TypeId result_type_id = insts().Get(*block_args.begin()).type_id();
+  return AddInst(SemIR::BlockArg{parse_node, result_type_id, new_block_id});
 }
 
 // Add the current code block to the enclosing function.
 auto Context::AddCurrentCodeBlockToFunction() -> void {
-  CARBON_CHECK(!node_block_stack().empty()) << "no current code block";
+  CARBON_CHECK(!inst_block_stack().empty()) << "no current code block";
   CARBON_CHECK(!return_scope_stack().empty()) << "no current function";
 
-  if (!node_block_stack().is_current_block_reachable()) {
+  if (!inst_block_stack().is_current_block_reachable()) {
     // Don't include unreachable blocks in the function.
     return;
   }
 
   auto function_id =
-      nodes()
+      insts()
           .GetAs<SemIR::FunctionDeclaration>(return_scope_stack().back())
           .function_id;
   functions()
       .Get(function_id)
-      .body_block_ids.push_back(node_block_stack().PeekOrAdd());
+      .body_block_ids.push_back(inst_block_stack().PeekOrAdd());
 }
 
 auto Context::is_current_position_reachable() -> bool {
-  if (!node_block_stack().is_current_block_reachable()) {
+  if (!inst_block_stack().is_current_block_reachable()) {
     return false;
   }
 
   // Our current position is at the end of a reachable block. That position is
   // reachable unless the previous instruction is a terminator instruction.
-  auto block_contents = node_block_stack().PeekCurrentBlockContents();
+  auto block_contents = inst_block_stack().PeekCurrentBlockContents();
   if (block_contents.empty()) {
     return true;
   }
-  const auto& last_node = nodes().Get(block_contents.back());
-  return last_node.kind().terminator_kind() !=
+  const auto& last_inst = insts().Get(block_contents.back());
+  return last_inst.kind().terminator_kind() !=
          SemIR::TerminatorKind::Terminator;
 }
 
@@ -312,11 +312,11 @@ auto Context::ParamOrArgEndNoPop(Parse::NodeKind start_kind) -> void {
   }
 }
 
-auto Context::ParamOrArgPop() -> SemIR::NodeBlockId {
+auto Context::ParamOrArgPop() -> SemIR::InstBlockId {
   return params_or_args_stack_.Pop();
 }
 
-auto Context::ParamOrArgEnd(Parse::NodeKind start_kind) -> SemIR::NodeBlockId {
+auto Context::ParamOrArgEnd(Parse::NodeKind start_kind) -> SemIR::InstBlockId {
   ParamOrArgEndNoPop(start_kind);
   return ParamOrArgPop();
 }
@@ -373,14 +373,14 @@ class TypeCompleter {
       return true;
     }
 
-    auto node_id = context_.sem_ir().GetTypeAllowBuiltinTypes(type_id);
-    auto node = context_.nodes().Get(node_id);
+    auto inst_id = context_.sem_ir().GetTypeAllowBuiltinTypes(type_id);
+    auto inst = context_.insts().Get(inst_id);
 
     auto old_work_list_size = work_list_.size();
 
     switch (phase) {
       case Phase::AddNestedIncompleteTypes:
-        if (!AddNestedIncompleteTypes(node)) {
+        if (!AddNestedIncompleteTypes(inst)) {
           return false;
         }
         CARBON_CHECK(work_list_.size() >= old_work_list_size)
@@ -390,7 +390,7 @@ class TypeCompleter {
         break;
 
       case Phase::BuildValueRepresentation: {
-        auto value_rep = BuildValueRepresentation(type_id, node);
+        auto value_rep = BuildValueRepresentation(type_id, inst);
         context_.sem_ir().CompleteType(type_id, value_rep);
         CARBON_CHECK(old_work_list_size == work_list_.size())
             << "BuildValueRepresentation should not change work items";
@@ -419,18 +419,18 @@ class TypeCompleter {
     return true;
   }
 
-  // Adds any types nested within `type_node` that need to be complete for
-  // `type_node` to be complete to our work list.
-  auto AddNestedIncompleteTypes(SemIR::Node type_node) -> bool {
-    switch (type_node.kind()) {
+  // Adds any types nested within `type_inst` that need to be complete for
+  // `type_inst` to be complete to our work list.
+  auto AddNestedIncompleteTypes(SemIR::Inst type_inst) -> bool {
+    switch (type_inst.kind()) {
       case SemIR::ArrayType::Kind:
-        Push(type_node.As<SemIR::ArrayType>().element_type_id);
+        Push(type_inst.As<SemIR::ArrayType>().element_type_id);
         break;
 
       case SemIR::StructType::Kind:
-        for (auto field_id : context_.node_blocks().Get(
-                 type_node.As<SemIR::StructType>().fields_id)) {
-          Push(context_.nodes()
+        for (auto field_id : context_.inst_blocks().Get(
+                 type_inst.As<SemIR::StructType>().fields_id)) {
+          Push(context_.insts()
                    .GetAs<SemIR::StructTypeField>(field_id)
                    .field_type_id);
         }
@@ -438,13 +438,13 @@ class TypeCompleter {
 
       case SemIR::TupleType::Kind:
         for (auto element_type_id : context_.type_blocks().Get(
-                 type_node.As<SemIR::TupleType>().elements_id)) {
+                 type_inst.As<SemIR::TupleType>().elements_id)) {
           Push(element_type_id);
         }
         break;
 
       case SemIR::ClassType::Kind: {
-        auto class_type = type_node.As<SemIR::ClassType>();
+        auto class_type = type_inst.As<SemIR::ClassType>();
         auto& class_info = context_.classes().Get(class_type.class_id);
         if (!class_info.is_defined()) {
           if (diagnoser_) {
@@ -459,7 +459,7 @@ class TypeCompleter {
       }
 
       case SemIR::ConstType::Kind:
-        Push(type_node.As<SemIR::ConstType>().inner_id);
+        Push(type_inst.As<SemIR::ConstType>().inner_id);
         break;
 
       default:
@@ -516,21 +516,21 @@ class TypeCompleter {
   auto BuildCrossReferenceValueRepresentation(SemIR::TypeId type_id,
                                               SemIR::CrossReference xref) const
       -> SemIR::ValueRepresentation {
-    auto xref_node = context_.sem_ir()
+    auto xref_inst = context_.sem_ir()
                          .GetCrossReferenceIR(xref.ir_id)
-                         .nodes()
-                         .Get(xref.node_id);
+                         .insts()
+                         .Get(xref.inst_id);
 
     // The canonical description of a type should only have cross-references
     // for entities owned by another File, such as builtins, which are owned
     // by the prelude, and named entities like classes and interfaces, which
     // we don't support yet.
-    CARBON_CHECK(xref_node.kind() == SemIR::Builtin::Kind)
-        << "TODO: Handle other kinds of node cross-references";
+    CARBON_CHECK(xref_inst.kind() == SemIR::Builtin::Kind)
+        << "TODO: Handle other kinds of inst cross-references";
 
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (xref_node.As<SemIR::Builtin>().builtin_kind) {
+    switch (xref_inst.As<SemIR::Builtin>().builtin_kind) {
       case SemIR::BuiltinKind::TypeType:
       case SemIR::BuiltinKind::Error:
       case SemIR::BuiltinKind::Invalid:
@@ -578,23 +578,23 @@ class TypeCompleter {
                                           SemIR::StructType struct_type) const
       -> SemIR::ValueRepresentation {
     // TODO: Share more code with tuples.
-    auto fields = context_.node_blocks().Get(struct_type.fields_id);
+    auto fields = context_.inst_blocks().Get(struct_type.fields_id);
     if (fields.empty()) {
       return MakeEmptyRepresentation(struct_type.parse_node);
     }
 
     // Find the value representation for each field, and construct a struct
     // of value representations.
-    llvm::SmallVector<SemIR::NodeId> value_rep_fields;
+    llvm::SmallVector<SemIR::InstId> value_rep_fields;
     value_rep_fields.reserve(fields.size());
     bool same_as_object_rep = true;
     for (auto field_id : fields) {
-      auto field = context_.nodes().GetAs<SemIR::StructTypeField>(field_id);
+      auto field = context_.insts().GetAs<SemIR::StructTypeField>(field_id);
       auto field_value_rep = GetNestedValueRepresentation(field.field_type_id);
       if (field_value_rep.type_id != field.field_type_id) {
         same_as_object_rep = false;
         field.field_type_id = field_value_rep.type_id;
-        field_id = context_.AddNode(field);
+        field_id = context_.AddInst(field);
       }
       value_rep_fields.push_back(field_id);
     }
@@ -603,7 +603,7 @@ class TypeCompleter {
                          ? type_id
                          : context_.CanonicalizeStructType(
                                struct_type.parse_node,
-                               context_.node_blocks().Add(value_rep_fields));
+                               context_.inst_blocks().Add(value_rep_fields));
     return BuildStructOrTupleValueRepresentation(
         struct_type.parse_node, fields.size(), value_rep, same_as_object_rep);
   }
@@ -640,16 +640,16 @@ class TypeCompleter {
 
   // Builds and returns the value representation for the given type. All nested
   // types, as found by AddNestedIncompleteTypes, are known to be complete.
-  auto BuildValueRepresentation(SemIR::TypeId type_id, SemIR::Node node) const
+  auto BuildValueRepresentation(SemIR::TypeId type_id, SemIR::Inst inst) const
       -> SemIR::ValueRepresentation {
-    // TODO: This can emit new SemIR nodes. Consider emitting them into a
-    // dedicated file-scope node block where possible, or somewhere else that
-    // better reflects the definition of the type, rather than wherever the
+    // TODO: This can emit new SemIR instructions. Consider emitting them into a
+    // dedicated file-scope instruction block where possible, or somewhere else
+    // that better reflects the definition of the type, rather than wherever the
     // type happens to first be required to be complete.
 
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (node.kind()) {
+    switch (inst.kind()) {
       case SemIR::AddressOf::Kind:
       case SemIR::ArrayIndex::Kind:
       case SemIR::ArrayInit::Kind:
@@ -697,28 +697,28 @@ class TypeCompleter {
       case SemIR::ValueAsReference::Kind:
       case SemIR::ValueOfInitializer::Kind:
       case SemIR::VarStorage::Kind:
-        CARBON_FATAL() << "Type refers to non-type node " << node;
+        CARBON_FATAL() << "Type refers to non-type inst " << inst;
 
       case SemIR::CrossReference::Kind:
         return BuildCrossReferenceValueRepresentation(
-            type_id, node.As<SemIR::CrossReference>());
+            type_id, inst.As<SemIR::CrossReference>());
 
       case SemIR::ArrayType::Kind: {
         // For arrays, it's convenient to always use a pointer representation,
         // even when the array has zero or one element, in order to support
         // indexing.
         return MakePointerRepresentation(
-            node.parse_node(), type_id,
+            inst.parse_node(), type_id,
             SemIR::ValueRepresentation::ObjectAggregate);
       }
 
       case SemIR::StructType::Kind:
         return BuildStructTypeValueRepresentation(type_id,
-                                                  node.As<SemIR::StructType>());
+                                                  inst.As<SemIR::StructType>());
 
       case SemIR::TupleType::Kind:
         return BuildTupleTypeValueRepresentation(type_id,
-                                                 node.As<SemIR::TupleType>());
+                                                 inst.As<SemIR::TupleType>());
 
       case SemIR::ClassType::Kind:
         // The value representation for a class is a pointer to the object
@@ -726,9 +726,9 @@ class TypeCompleter {
         // TODO: Support customized value representations for classes.
         // TODO: Pick a better value representation when possible.
         return MakePointerRepresentation(
-            node.parse_node(),
+            inst.parse_node(),
             context_.classes()
-                .Get(node.As<SemIR::ClassType>().class_id)
+                .Get(inst.As<SemIR::ClassType>().class_id)
                 .object_representation_id,
             SemIR::ValueRepresentation::ObjectAggregate);
 
@@ -743,7 +743,7 @@ class TypeCompleter {
         // The value representation of `const T` is the same as that of `T`.
         // Objects are not modifiable through their value representations.
         return GetNestedValueRepresentation(
-            node.As<SemIR::ConstType>().inner_id);
+            inst.As<SemIR::ConstType>().inner_id);
     }
   }
 
@@ -774,9 +774,9 @@ auto Context::TryToCompleteType(
 }
 
 auto Context::CanonicalizeTypeImpl(
-    SemIR::NodeKind kind,
+    SemIR::InstKind kind,
     llvm::function_ref<void(llvm::FoldingSetNodeID& canonical_id)> profile_type,
-    llvm::function_ref<SemIR::NodeId()> make_node) -> SemIR::TypeId {
+    llvm::function_ref<SemIR::InstId()> make_inst) -> SemIR::TypeId {
   llvm::FoldingSetNodeID canonical_id;
   kind.Profile(canonical_id);
   profile_type(canonical_id);
@@ -788,14 +788,14 @@ auto Context::CanonicalizeTypeImpl(
     return node->type_id();
   }
 
-  auto node_id = make_node();
-  auto type_id = types().Add({.node_id = node_id});
-  CARBON_CHECK(canonical_types_.insert({node_id, type_id}).second);
+  auto inst_id = make_inst();
+  auto type_id = types().Add({.inst_id = inst_id});
+  CARBON_CHECK(canonical_types_.insert({inst_id, type_id}).second);
   type_node_storage_.push_back(
       std::make_unique<TypeNode>(canonical_id, type_id));
 
   // In a debug build, check that our insertion position is still valid. It
-  // could have been invalidated by a misbehaving `make_node`.
+  // could have been invalidated by a misbehaving `make_inst`.
   CARBON_DCHECK([&] {
     void* check_insert_pos;
     auto* check_node = canonical_type_nodes_.FindNodeOrInsertPos(
@@ -816,45 +816,45 @@ static auto ProfileTupleType(llvm::ArrayRef<SemIR::TypeId> type_ids,
 }
 
 // Compute a fingerprint for a type, for use as a key in a folding set.
-static auto ProfileType(Context& semantics_context, SemIR::Node node,
+static auto ProfileType(Context& semantics_context, SemIR::Inst inst,
                         llvm::FoldingSetNodeID& canonical_id) -> void {
-  switch (node.kind()) {
+  switch (inst.kind()) {
     case SemIR::ArrayType::Kind: {
-      auto array_type = node.As<SemIR::ArrayType>();
+      auto array_type = inst.As<SemIR::ArrayType>();
       canonical_id.AddInteger(
           semantics_context.sem_ir().GetArrayBoundValue(array_type.bound_id));
       canonical_id.AddInteger(array_type.element_type_id.index);
       break;
     }
     case SemIR::Builtin::Kind:
-      canonical_id.AddInteger(node.As<SemIR::Builtin>().builtin_kind.AsInt());
+      canonical_id.AddInteger(inst.As<SemIR::Builtin>().builtin_kind.AsInt());
       break;
     case SemIR::ClassType::Kind:
-      canonical_id.AddInteger(node.As<SemIR::ClassType>().class_id.index);
+      canonical_id.AddInteger(inst.As<SemIR::ClassType>().class_id.index);
       break;
     case SemIR::CrossReference::Kind: {
       // TODO: Cross-references should be canonicalized by looking at their
       // target rather than treating them as new unique types.
-      auto xref = node.As<SemIR::CrossReference>();
+      auto xref = inst.As<SemIR::CrossReference>();
       canonical_id.AddInteger(xref.ir_id.index);
-      canonical_id.AddInteger(xref.node_id.index);
+      canonical_id.AddInteger(xref.inst_id.index);
       break;
     }
     case SemIR::ConstType::Kind:
       canonical_id.AddInteger(
           semantics_context
-              .GetUnqualifiedType(node.As<SemIR::ConstType>().inner_id)
+              .GetUnqualifiedType(inst.As<SemIR::ConstType>().inner_id)
               .index);
       break;
     case SemIR::PointerType::Kind:
-      canonical_id.AddInteger(node.As<SemIR::PointerType>().pointee_id.index);
+      canonical_id.AddInteger(inst.As<SemIR::PointerType>().pointee_id.index);
       break;
     case SemIR::StructType::Kind: {
-      auto fields = semantics_context.node_blocks().Get(
-          node.As<SemIR::StructType>().fields_id);
+      auto fields = semantics_context.inst_blocks().Get(
+          inst.As<SemIR::StructType>().fields_id);
       for (const auto& field_id : fields) {
         auto field =
-            semantics_context.nodes().GetAs<SemIR::StructTypeField>(field_id);
+            semantics_context.insts().GetAs<SemIR::StructTypeField>(field_id);
         canonical_id.AddInteger(field.name_id.index);
         canonical_id.AddInteger(field.field_type_id.index);
       }
@@ -862,49 +862,49 @@ static auto ProfileType(Context& semantics_context, SemIR::Node node,
     }
     case SemIR::TupleType::Kind:
       ProfileTupleType(semantics_context.type_blocks().Get(
-                           node.As<SemIR::TupleType>().elements_id),
+                           inst.As<SemIR::TupleType>().elements_id),
                        canonical_id);
       break;
     case SemIR::UnboundFieldType::Kind: {
-      auto unbound_field_type = node.As<SemIR::UnboundFieldType>();
+      auto unbound_field_type = inst.As<SemIR::UnboundFieldType>();
       canonical_id.AddInteger(unbound_field_type.class_type_id.index);
       canonical_id.AddInteger(unbound_field_type.field_type_id.index);
       break;
     }
     default:
-      CARBON_FATAL() << "Unexpected type node " << node;
+      CARBON_FATAL() << "Unexpected type inst " << inst;
   }
 }
 
-auto Context::CanonicalizeTypeAndAddNodeIfNew(SemIR::Node node)
+auto Context::CanonicalizeTypeAndAddInstIfNew(SemIR::Inst inst)
     -> SemIR::TypeId {
   auto profile_node = [&](llvm::FoldingSetNodeID& canonical_id) {
-    ProfileType(*this, node, canonical_id);
+    ProfileType(*this, inst, canonical_id);
   };
-  auto make_node = [&] { return AddNode(node); };
-  return CanonicalizeTypeImpl(node.kind(), profile_node, make_node);
+  auto make_inst = [&] { return AddInst(inst); };
+  return CanonicalizeTypeImpl(inst.kind(), profile_node, make_inst);
 }
 
-auto Context::CanonicalizeType(SemIR::NodeId node_id) -> SemIR::TypeId {
-  node_id = FollowNameReferences(node_id);
+auto Context::CanonicalizeType(SemIR::InstId inst_id) -> SemIR::TypeId {
+  inst_id = FollowNameReferences(inst_id);
 
-  auto it = canonical_types_.find(node_id);
+  auto it = canonical_types_.find(inst_id);
   if (it != canonical_types_.end()) {
     return it->second;
   }
 
-  auto node = nodes().Get(node_id);
+  auto inst = insts().Get(inst_id);
   auto profile_node = [&](llvm::FoldingSetNodeID& canonical_id) {
-    ProfileType(*this, node, canonical_id);
+    ProfileType(*this, inst, canonical_id);
   };
-  auto make_node = [&] { return node_id; };
-  return CanonicalizeTypeImpl(node.kind(), profile_node, make_node);
+  auto make_inst = [&] { return inst_id; };
+  return CanonicalizeTypeImpl(inst.kind(), profile_node, make_inst);
 }
 
 auto Context::CanonicalizeStructType(Parse::Node parse_node,
-                                     SemIR::NodeBlockId refs_id)
+                                     SemIR::InstBlockId refs_id)
     -> SemIR::TypeId {
-  return CanonicalizeTypeAndAddNodeIfNew(
+  return CanonicalizeTypeAndAddInstIfNew(
       SemIR::StructType{parse_node, SemIR::TypeId::TypeType, refs_id});
 }
 
@@ -915,17 +915,17 @@ auto Context::CanonicalizeTupleType(Parse::Node parse_node,
   auto profile_tuple = [&](llvm::FoldingSetNodeID& canonical_id) {
     ProfileTupleType(type_ids, canonical_id);
   };
-  auto make_tuple_node = [&] {
-    return AddNode(SemIR::TupleType{parse_node, SemIR::TypeId::TypeType,
+  auto make_tuple_inst = [&] {
+    return AddInst(SemIR::TupleType{parse_node, SemIR::TypeId::TypeType,
                                     type_blocks().Add(type_ids)});
   };
   return CanonicalizeTypeImpl(SemIR::TupleType::Kind, profile_tuple,
-                              make_tuple_node);
+                              make_tuple_inst);
 }
 
 auto Context::GetBuiltinType(SemIR::BuiltinKind kind) -> SemIR::TypeId {
   CARBON_CHECK(kind != SemIR::BuiltinKind::Invalid);
-  auto type_id = CanonicalizeType(SemIR::NodeId::ForBuiltin(kind));
+  auto type_id = CanonicalizeType(SemIR::InstId::ForBuiltin(kind));
   // To keep client code simpler, complete builtin types before returning them.
   bool complete = TryToCompleteType(type_id);
   CARBON_CHECK(complete) << "Failed to complete builtin type";
@@ -934,14 +934,14 @@ auto Context::GetBuiltinType(SemIR::BuiltinKind kind) -> SemIR::TypeId {
 
 auto Context::GetPointerType(Parse::Node parse_node,
                              SemIR::TypeId pointee_type_id) -> SemIR::TypeId {
-  return CanonicalizeTypeAndAddNodeIfNew(
+  return CanonicalizeTypeAndAddInstIfNew(
       SemIR::PointerType{parse_node, SemIR::TypeId::TypeType, pointee_type_id});
 }
 
 auto Context::GetUnqualifiedType(SemIR::TypeId type_id) -> SemIR::TypeId {
-  SemIR::Node type_node =
-      nodes().Get(sem_ir_->GetTypeAllowBuiltinTypes(type_id));
-  if (auto const_type = type_node.TryAs<SemIR::ConstType>()) {
+  SemIR::Inst type_inst =
+      insts().Get(sem_ir_->GetTypeAllowBuiltinTypes(type_id));
+  if (auto const_type = type_inst.TryAs<SemIR::ConstType>()) {
     return const_type->inner_id;
   }
   return type_id;
@@ -949,7 +949,7 @@ auto Context::GetUnqualifiedType(SemIR::TypeId type_id) -> SemIR::TypeId {
 
 auto Context::PrintForStackDump(llvm::raw_ostream& output) const -> void {
   node_stack_.PrintForStackDump(output);
-  node_block_stack_.PrintForStackDump(output);
+  inst_block_stack_.PrintForStackDump(output);
   params_or_args_stack_.PrintForStackDump(output);
   args_type_info_stack_.PrintForStackDump(output);
 }

+ 84 - 83
toolchain/check/context.h

@@ -14,7 +14,7 @@
 #include "toolchain/check/node_stack.h"
 #include "toolchain/parse/tree.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -26,8 +26,8 @@ class Context {
 
   // A scope in which `break` and `continue` can be used.
   struct BreakContinueScope {
-    SemIR::NodeBlockId break_target;
-    SemIR::NodeBlockId continue_target;
+    SemIR::InstBlockId break_target;
+    SemIR::InstBlockId continue_target;
   };
 
   // Stores references for work.
@@ -41,25 +41,25 @@ class Context {
   // Runs verification that the processing cleanly finished.
   auto VerifyOnFinish() -> void;
 
-  // Adds a node to the current block, returning the produced ID.
-  auto AddNode(SemIR::Node node) -> SemIR::NodeId;
+  // Adds an instruction to the current block, returning the produced ID.
+  auto AddInst(SemIR::Inst inst) -> SemIR::InstId;
 
-  // Pushes a parse tree node onto the stack, storing the SemIR::Node as the
+  // Pushes a parse tree node onto the stack, storing the SemIR::Inst as the
   // result.
-  auto AddNodeAndPush(Parse::Node parse_node, SemIR::Node node) -> void;
+  auto AddInstAndPush(Parse::Node parse_node, SemIR::Inst inst) -> void;
 
   // Adds a name to name lookup. Prints a diagnostic for name conflicts.
   auto AddNameToLookup(Parse::Node name_node, StringId name_id,
-                       SemIR::NodeId target_id) -> void;
+                       SemIR::InstId target_id) -> void;
 
-  // Performs name lookup in a specified scope, returning the referenced node.
-  // If scope_id is invalid, uses the current contextual scope.
+  // Performs name lookup in a specified scope, returning the referenced
+  // instruction. If scope_id is invalid, uses the current contextual scope.
   auto LookupName(Parse::Node parse_node, StringId name_id,
                   SemIR::NameScopeId scope_id, bool print_diagnostics)
-      -> SemIR::NodeId;
+      -> SemIR::InstId;
 
   // Prints a diagnostic for a duplicate name.
-  auto DiagnoseDuplicateName(Parse::Node parse_node, SemIR::NodeId prev_def_id)
+  auto DiagnoseDuplicateName(Parse::Node parse_node, SemIR::InstId prev_def_id)
       -> void;
 
   // Prints a diagnostic for a missing name.
@@ -70,7 +70,7 @@ class Context {
       -> void;
 
   // Pushes a new scope onto scope_stack_.
-  auto PushScope(SemIR::NodeId scope_node_id = SemIR::NodeId::Invalid,
+  auto PushScope(SemIR::InstId scope_inst_id = SemIR::InstId::Invalid,
                  SemIR::NameScopeId scope_id = SemIR::NameScopeId::Invalid)
       -> void;
 
@@ -84,55 +84,56 @@ class Context {
 
   // Returns the current scope, if it is of the specified kind. Otherwise,
   // returns nullopt.
-  template <typename NodeT>
-  auto GetCurrentScopeAs() -> std::optional<NodeT> {
-    auto current_scope_node_id = current_scope().scope_node_id;
-    if (!current_scope_node_id.is_valid()) {
+  template <typename InstT>
+  auto GetCurrentScopeAs() -> std::optional<InstT> {
+    auto current_scope_inst_id = current_scope().scope_inst_id;
+    if (!current_scope_inst_id.is_valid()) {
       return std::nullopt;
     }
-    return nodes().Get(current_scope_node_id).TryAs<NodeT>();
+    return insts().Get(current_scope_inst_id).TryAs<InstT>();
   }
 
-  // Follows NameReference nodes to find the value named by a given node.
-  auto FollowNameReferences(SemIR::NodeId node_id) -> SemIR::NodeId;
+  // Follows NameReference instructions to find the value named by a given
+  // instruction.
+  auto FollowNameReferences(SemIR::InstId inst_id) -> SemIR::InstId;
 
-  // Gets the constant value of the given node, if it has one.
-  auto GetConstantValue(SemIR::NodeId node_id) -> SemIR::NodeId;
+  // Gets the constant value of the given instruction, if it has one.
+  auto GetConstantValue(SemIR::InstId inst_id) -> SemIR::InstId;
 
-  // Adds a `Branch` node branching to a new node block, and returns the ID of
-  // the new block. All paths to the branch target must go through the current
-  // block, though not necessarily through this branch.
-  auto AddDominatedBlockAndBranch(Parse::Node parse_node) -> SemIR::NodeBlockId;
-
-  // Adds a `Branch` node branching to a new node block with a value, and
+  // Adds a `Branch` instruction branching to a new instruction block, and
   // returns the ID of the new block. All paths to the branch target must go
-  // through the current block.
+  // through the current block, though not necessarily through this branch.
+  auto AddDominatedBlockAndBranch(Parse::Node parse_node) -> SemIR::InstBlockId;
+
+  // Adds a `Branch` instruction branching to a new instruction block with a
+  // value, and returns the ID of the new block. All paths to the branch target
+  // must go through the current block.
   auto AddDominatedBlockAndBranchWithArg(Parse::Node parse_node,
-                                         SemIR::NodeId arg_id)
-      -> SemIR::NodeBlockId;
+                                         SemIR::InstId arg_id)
+      -> SemIR::InstBlockId;
 
-  // Adds a `BranchIf` node branching to a new node block, and returns the ID
-  // of the new block. All paths to the branch target must go through the
-  // current block.
+  // Adds a `BranchIf` instruction branching to a new instruction block, and
+  // returns the ID of the new block. All paths to the branch target must go
+  // through the current block.
   auto AddDominatedBlockAndBranchIf(Parse::Node parse_node,
-                                    SemIR::NodeId cond_id)
-      -> SemIR::NodeBlockId;
+                                    SemIR::InstId cond_id)
+      -> SemIR::InstBlockId;
 
   // Handles recovergence of control flow. Adds branches from the top
-  // `num_blocks` on the node block stack to a new block, pops the existing
-  // blocks, and pushes the new block onto the node block stack.
+  // `num_blocks` on the instruction block stack to a new block, pops the
+  // existing blocks, and pushes the new block onto the instruction block stack.
   auto AddConvergenceBlockAndPush(Parse::Node parse_node, int num_blocks)
       -> void;
 
   // Handles recovergence of control flow with a result value. Adds branches
-  // from the top few blocks on the node block stack to a new block, pops the
-  // existing blocks, and pushes the new block onto the node block stack. The
-  // number of blocks popped is the size of `block_args`, and the corresponding
-  // result values are the elements of `block_args`. Returns a node referring
-  // to the result value.
+  // from the top few blocks on the instruction block stack to a new block, pops
+  // the existing blocks, and pushes the new block onto the instruction block
+  // stack. The number of blocks popped is the size of `block_args`, and the
+  // corresponding result values are the elements of `block_args`. Returns an
+  // instruction referring to the result value.
   auto AddConvergenceBlockWithArgAndPush(
       Parse::Node parse_node,
-      std::initializer_list<SemIR::NodeId> blocks_and_args) -> SemIR::NodeId;
+      std::initializer_list<SemIR::InstId> blocks_and_args) -> SemIR::InstId;
 
   // Add the current code block to the enclosing function.
   auto AddCurrentCodeBlockToFunction() -> void;
@@ -140,8 +141,8 @@ class Context {
   // Returns whether the current position in the current block is reachable.
   auto is_current_position_reachable() -> bool;
 
-  // Canonicalizes a type which is tracked as a single node.
-  auto CanonicalizeType(SemIR::NodeId node_id) -> SemIR::TypeId;
+  // Canonicalizes a type which is tracked as a single instruction.
+  auto CanonicalizeType(SemIR::InstId inst_id) -> SemIR::TypeId;
 
   // Handles canonicalization of struct types. This may create a new struct type
   // when it has a new structure, or reference an existing struct type when it
@@ -151,7 +152,7 @@ class Context {
   // name conflicts or other diagnostics during creation, which can use the
   // parse node.
   auto CanonicalizeStructType(Parse::Node parse_node,
-                              SemIR::NodeBlockId refs_id) -> SemIR::TypeId;
+                              SemIR::InstBlockId refs_id) -> SemIR::TypeId;
 
   // Handles canonicalization of tuple types. This may create a new tuple type
   // if the `type_ids` doesn't match an existing tuple type.
@@ -197,16 +198,16 @@ class Context {
 
   // Pops the current parameter or argument list. Should only be called after
   // `ParamOrArgEndNoPop`.
-  auto ParamOrArgPop() -> SemIR::NodeBlockId;
+  auto ParamOrArgPop() -> SemIR::InstBlockId;
 
   // Detects whether there's an entry to push. Pops and returns the argument
   // list. This is the same as `ParamOrArgEndNoPop` followed by `ParamOrArgPop`.
-  auto ParamOrArgEnd(Parse::NodeKind start_kind) -> SemIR::NodeBlockId;
+  auto ParamOrArgEnd(Parse::NodeKind start_kind) -> SemIR::InstBlockId;
 
   // Saves a parameter from the top block in node_stack_ to the top block in
   // params_or_args_stack_.
-  auto ParamOrArgSave(SemIR::NodeId node_id) -> void {
-    params_or_args_stack_.AddNodeId(node_id);
+  auto ParamOrArgSave(SemIR::InstId inst_id) -> void {
+    params_or_args_stack_.AddInstId(inst_id);
   }
 
   // Prints information for a stack dump.
@@ -222,17 +223,17 @@ class Context {
 
   auto node_stack() -> NodeStack& { return node_stack_; }
 
-  auto node_block_stack() -> NodeBlockStack& { return node_block_stack_; }
+  auto inst_block_stack() -> InstBlockStack& { return inst_block_stack_; }
 
-  auto params_or_args_stack() -> NodeBlockStack& {
+  auto params_or_args_stack() -> InstBlockStack& {
     return params_or_args_stack_;
   }
 
-  auto args_type_info_stack() -> NodeBlockStack& {
+  auto args_type_info_stack() -> InstBlockStack& {
     return args_type_info_stack_;
   }
 
-  auto return_scope_stack() -> llvm::SmallVector<SemIR::NodeId>& {
+  auto return_scope_stack() -> llvm::SmallVector<SemIR::InstId>& {
     return return_scope_stack_;
   }
 
@@ -264,9 +265,9 @@ class Context {
       -> SemIR::BlockValueStore<SemIR::TypeBlockId, SemIR::TypeId>& {
     return sem_ir().type_blocks();
   }
-  auto nodes() -> SemIR::NodeStore& { return sem_ir().nodes(); }
-  auto node_blocks() -> SemIR::NodeBlockStore& {
-    return sem_ir().node_blocks();
+  auto insts() -> SemIR::InstStore& { return sem_ir().insts(); }
+  auto inst_blocks() -> SemIR::InstBlockStore& {
+    return sem_ir().inst_blocks();
   }
 
  private:
@@ -285,13 +286,13 @@ class Context {
 
   // An entry in scope_stack_.
   struct ScopeStackEntry {
-    // The node associated with this entry, if any. This can be one of:
+    // The instruction associated with this entry, if any. This can be one of:
     //
     // - A `ClassDeclaration`, for a class definition scope.
     // - A `FunctionDeclaration`, for the outermost scope in a function
     //   definition.
     // - Invalid, for any other scope.
-    SemIR::NodeId scope_node_id;
+    SemIR::InstId scope_inst_id;
 
     // The name scope associated with this entry, if any.
     SemIR::NameScopeId scope_id;
@@ -310,19 +311,19 @@ class Context {
   // type. The ID should be distinct for all distinct type values with the same
   // `kind`.
   //
-  // `make_node()` is called to obtain a `SemIR::NodeId` that describes the
+  // `make_inst()` is called to obtain a `SemIR::InstId` that describes the
   // type. It is only called if the type does not already exist, so can be used
-  // to lazily build the `SemIR::Node`. `make_node()` is not permitted to
+  // to lazily build the `SemIR::Inst`. `make_inst()` is not permitted to
   // directly or indirectly canonicalize any types.
   auto CanonicalizeTypeImpl(
-      SemIR::NodeKind kind,
+      SemIR::InstKind kind,
       llvm::function_ref<void(llvm::FoldingSetNodeID& canonical_id)>
           profile_type,
-      llvm::function_ref<SemIR::NodeId()> make_node) -> SemIR::TypeId;
+      llvm::function_ref<SemIR::InstId()> make_inst) -> SemIR::TypeId;
 
-  // Forms a canonical type ID for a type. If the type is new, adds the node to
-  // the current block.
-  auto CanonicalizeTypeAndAddNodeIfNew(SemIR::Node node) -> SemIR::TypeId;
+  // Forms a canonical type ID for a type. If the type is new, adds the
+  // instruction to the current block.
+  auto CanonicalizeTypeAndAddInstIfNew(SemIR::Inst inst) -> SemIR::TypeId;
 
   auto current_scope() -> ScopeStackEntry& { return scope_stack_.back(); }
   auto current_scope() const -> const ScopeStackEntry& {
@@ -347,24 +348,24 @@ class Context {
   // The stack during Build. Will contain file-level parse nodes on return.
   NodeStack node_stack_;
 
-  // The stack of node blocks being used for general IR generation.
-  NodeBlockStack node_block_stack_;
+  // The stack of instruction blocks being used for general IR generation.
+  InstBlockStack inst_block_stack_;
 
-  // The stack of node blocks being used for per-element tracking of nodes in
-  // parameter and argument node blocks. Versus node_block_stack_, an element
-  // will have 1 or more nodes in blocks in node_block_stack_, but only ever 1
-  // node in blocks here.
-  NodeBlockStack params_or_args_stack_;
+  // The stack of instruction blocks being used for per-element tracking of
+  // instructions in parameter and argument instruction blocks. Versus
+  // inst_block_stack_, an element will have 1 or more instructions in blocks in
+  // inst_block_stack_, but only ever 1 instruction in blocks here.
+  InstBlockStack params_or_args_stack_;
 
-  // The stack of node blocks being used for type information while processing
-  // arguments. This is used in parallel with params_or_args_stack_. It's
-  // currently only used for struct literals, where we need to track names
+  // The stack of instruction blocks being used for type information while
+  // processing arguments. This is used in parallel with params_or_args_stack_.
+  // It's currently only used for struct literals, where we need to track names
   // for a type separate from the literal arguments.
-  NodeBlockStack args_type_info_stack_;
+  InstBlockStack args_type_info_stack_;
 
   // A stack of return scopes; i.e., targets for `return`. Inside a function,
   // this will be a FunctionDeclaration.
-  llvm::SmallVector<SemIR::NodeId> return_scope_stack_;
+  llvm::SmallVector<SemIR::InstId> return_scope_stack_;
 
   // A stack of `break` and `continue` targets.
   llvm::SmallVector<BreakContinueScope> break_continue_stack_;
@@ -381,11 +382,11 @@ class Context {
   // reference.
   //
   // Names which no longer have lookup results are erased.
-  llvm::DenseMap<StringId, llvm::SmallVector<SemIR::NodeId>> name_lookup_;
+  llvm::DenseMap<StringId, llvm::SmallVector<SemIR::InstId>> name_lookup_;
 
-  // Cache of the mapping from nodes to types, to avoid recomputing the folding
-  // set ID.
-  llvm::DenseMap<SemIR::NodeId, SemIR::TypeId> canonical_types_;
+  // Cache of the mapping from instructions to types, to avoid recomputing the
+  // folding set ID.
+  llvm::DenseMap<SemIR::InstId, SemIR::TypeId> canonical_types_;
 
   // Tracks the canonical representation of types that have been defined.
   llvm::FoldingSet<TypeNode> canonical_type_nodes_;

+ 179 - 179
toolchain/check/convert.cpp

@@ -13,7 +13,7 @@
 #include "toolchain/diagnostics/diagnostic_kind.h"
 #include "toolchain/parse/node_kind.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Check {
@@ -22,12 +22,12 @@ namespace Carbon::Check {
 // there is no return slot, because the initialization is not performed in
 // place.
 static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
-                                         SemIR::NodeId init_id)
-    -> SemIR::NodeId {
-  SemIR::Node init = sem_ir.nodes().Get(init_id);
+                                         SemIR::InstId init_id)
+    -> SemIR::InstId {
+  SemIR::Inst init = sem_ir.insts().Get(init_id);
   switch (init.kind()) {
     default:
-      CARBON_FATAL() << "Initialization from unexpected node " << init;
+      CARBON_FATAL() << "Initialization from unexpected inst " << init;
 
     case SemIR::StructInit::Kind:
     case SemIR::TupleInit::Kind:
@@ -44,13 +44,13 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
       auto call = init.As<SemIR::Call>();
       if (!SemIR::GetInitializingRepresentation(sem_ir, call.type_id)
                .has_return_slot()) {
-        return SemIR::NodeId::Invalid;
+        return SemIR::InstId::Invalid;
       }
-      return sem_ir.node_blocks().Get(call.args_id).back();
+      return sem_ir.inst_blocks().Get(call.args_id).back();
     }
 
     case SemIR::ArrayInit::Kind: {
-      return sem_ir.node_blocks()
+      return sem_ir.inst_blocks()
           .Get(init.As<SemIR::ArrayInit>().inits_and_return_slot_id)
           .back();
     }
@@ -58,17 +58,17 @@ static auto FindReturnSlotForInitializer(SemIR::File& sem_ir,
 }
 
 // Marks the initializer `init_id` as initializing `target_id`.
-static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::NodeId init_id,
-                               SemIR::NodeId target_id,
+static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::InstId init_id,
+                               SemIR::InstId target_id,
                                PendingBlock& target_block) -> void {
   auto return_slot_id = FindReturnSlotForInitializer(sem_ir, init_id);
   if (return_slot_id.is_valid()) {
     // Replace the temporary in the return slot with a reference to our target.
-    CARBON_CHECK(sem_ir.nodes().Get(return_slot_id).kind() ==
+    CARBON_CHECK(sem_ir.insts().Get(return_slot_id).kind() ==
                  SemIR::TemporaryStorage::Kind)
         << "Return slot for initializer does not contain a temporary; "
         << "initialized multiple times? Have "
-        << sem_ir.nodes().Get(return_slot_id);
+        << sem_ir.insts().Get(return_slot_id);
     target_block.MergeReplacing(return_slot_id, target_id);
   }
 }
@@ -77,44 +77,44 @@ static auto MarkInitializerFor(SemIR::File& sem_ir, SemIR::NodeId init_id,
 // expression described by `init_id`, and returns the location of the
 // temporary. If `discarded` is `true`, the result is discarded, and no
 // temporary will be created if possible; if no temporary is created, the
-// return value will be `SemIR::NodeId::Invalid`.
-static auto FinalizeTemporary(Context& context, SemIR::NodeId init_id,
-                              bool discarded) -> SemIR::NodeId {
+// return value will be `SemIR::InstId::Invalid`.
+static auto FinalizeTemporary(Context& context, SemIR::InstId init_id,
+                              bool discarded) -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
   auto return_slot_id = FindReturnSlotForInitializer(sem_ir, init_id);
   if (return_slot_id.is_valid()) {
     // The return slot should already have a materialized temporary in it.
-    CARBON_CHECK(sem_ir.nodes().Get(return_slot_id).kind() ==
+    CARBON_CHECK(sem_ir.insts().Get(return_slot_id).kind() ==
                  SemIR::TemporaryStorage::Kind)
         << "Return slot for initializer does not contain a temporary; "
         << "initialized multiple times? Have "
-        << sem_ir.nodes().Get(return_slot_id);
-    auto init = sem_ir.nodes().Get(init_id);
-    return context.AddNode(SemIR::Temporary{init.parse_node(), init.type_id(),
+        << sem_ir.insts().Get(return_slot_id);
+    auto init = sem_ir.insts().Get(init_id);
+    return context.AddInst(SemIR::Temporary{init.parse_node(), init.type_id(),
                                             return_slot_id, init_id});
   }
 
   if (discarded) {
     // Don't invent a temporary that we're going to discard.
-    return SemIR::NodeId::Invalid;
+    return SemIR::InstId::Invalid;
   }
 
   // The initializer has no return slot, but we want to produce a temporary
   // object. Materialize one now.
   // TODO: Consider using an invalid ID to mean that we immediately
   // materialize and initialize a temporary, rather than two separate
-  // nodes.
-  auto init = sem_ir.nodes().Get(init_id);
-  auto temporary_id = context.AddNode(
+  // instructions.
+  auto init = sem_ir.insts().Get(init_id);
+  auto temporary_id = context.AddInst(
       SemIR::TemporaryStorage{init.parse_node(), init.type_id()});
-  return context.AddNode(SemIR::Temporary{init.parse_node(), init.type_id(),
+  return context.AddInst(SemIR::Temporary{init.parse_node(), init.type_id(),
                                           temporary_id, init_id});
 }
 
 // Materialize a temporary to hold the result of the given expression if it is
 // an initializing expression.
-static auto MaterializeIfInitializing(Context& context, SemIR::NodeId expr_id)
-    -> SemIR::NodeId {
+static auto MaterializeIfInitializing(Context& context, SemIR::InstId expr_id)
+    -> SemIR::InstId {
   if (GetExpressionCategory(context.sem_ir(), expr_id) ==
       SemIR::ExpressionCategory::Initializing) {
     return FinalizeTemporary(context, expr_id, /*discarded=*/false);
@@ -122,23 +122,23 @@ static auto MaterializeIfInitializing(Context& context, SemIR::NodeId expr_id)
   return expr_id;
 }
 
-// Creates and adds a node to perform element access into an aggregate.
-template <typename AccessNodeT, typename NodeBlockT>
-static auto MakeElemAccessNode(Context& context, Parse::Node parse_node,
-                               SemIR::NodeId aggregate_id,
-                               SemIR::TypeId elem_type_id, NodeBlockT& block,
+// Creates and adds an instruction to perform element access into an aggregate.
+template <typename AccessInstT, typename InstBlockT>
+static auto MakeElemAccessInst(Context& context, Parse::Node parse_node,
+                               SemIR::InstId aggregate_id,
+                               SemIR::TypeId elem_type_id, InstBlockT& block,
                                std::size_t i) {
-  if constexpr (std::is_same_v<AccessNodeT, SemIR::ArrayIndex>) {
-    // TODO: Add a new node kind for indexing an array at a constant index
-    // so that we don't need an integer literal node here, and remove this
-    // special case.
-    auto index_id = block.AddNode(SemIR::IntegerLiteral{
+  if constexpr (std::is_same_v<AccessInstT, SemIR::ArrayIndex>) {
+    // TODO: Add a new instruction kind for indexing an array at a constant
+    // index so that we don't need an integer literal instruction here, and
+    // remove this special case.
+    auto index_id = block.AddInst(SemIR::IntegerLiteral{
         parse_node, context.GetBuiltinType(SemIR::BuiltinKind::IntegerType),
         context.sem_ir().integers().Add(llvm::APInt(32, i))});
-    return block.AddNode(
-        AccessNodeT{parse_node, elem_type_id, aggregate_id, index_id});
+    return block.AddInst(
+        AccessInstT{parse_node, elem_type_id, aggregate_id, index_id});
   } else {
-    return block.AddNode(AccessNodeT{parse_node, elem_type_id, aggregate_id,
+    return block.AddInst(AccessInstT{parse_node, elem_type_id, aggregate_id,
                                      SemIR::MemberIndex(i)});
   }
 }
@@ -147,29 +147,29 @@ static auto MakeElemAccessNode(Context& context, Parse::Node parse_node,
 // another aggregate.
 //
 // For the source: `src_id` is the source aggregate, `src_elem_type` is the
-// element type, `i` is the index, and `SourceAccessNodeT` is the kind of node
-// used to access the source element.
+// element type, `i` is the index, and `SourceAccessInstT` is the kind of
+// instruction used to access the source element.
 //
 // For the target: `kind` is the kind of conversion or initialization,
 // `target_elem_type` is the element type. For initialization, `target_id` is
 // the destination, `target_block` is a pending block for target location
 // calculations that will be spliced as the return slot of the initializer if
-// necessary, `i` is the index, and `TargetAccessNodeT` is the kind of node
-// used to access the destination element.
-template <typename SourceAccessNodeT, typename TargetAccessNodeT>
+// necessary, `i` is the index, and `TargetAccessInstT` is the kind of
+// instruction used to access the destination element.
+template <typename SourceAccessInstT, typename TargetAccessInstT>
 static auto ConvertAggregateElement(
-    Context& context, Parse::Node parse_node, SemIR::NodeId src_id,
+    Context& context, Parse::Node parse_node, SemIR::InstId src_id,
     SemIR::TypeId src_elem_type,
-    llvm::ArrayRef<SemIR::NodeId> src_literal_elems,
-    ConversionTarget::Kind kind, SemIR::NodeId target_id,
+    llvm::ArrayRef<SemIR::InstId> src_literal_elems,
+    ConversionTarget::Kind kind, SemIR::InstId target_id,
     SemIR::TypeId target_elem_type, PendingBlock* target_block, std::size_t i) {
   // 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 node if it's unused.
+  // TODO: Ideally we would discard this instruction if it's unused.
   auto src_elem_id =
       !src_literal_elems.empty()
           ? src_literal_elems[i]
-          : MakeElemAccessNode<SourceAccessNodeT>(context, parse_node, src_id,
+          : MakeElemAccessInst<SourceAccessInstT>(context, parse_node, src_id,
                                                   src_elem_type, context, i);
 
   // If we're performing a conversion rather than an initialization, we won't
@@ -180,9 +180,9 @@ static auto ConvertAggregateElement(
   }
 
   // Compute the location of the target element and initialize it.
-  PendingBlock::DiscardUnusedNodesScope scope(target_block);
+  PendingBlock::DiscardUnusedInstsScope scope(target_block);
   target.init_block = target_block;
-  target.init_id = MakeElemAccessNode<TargetAccessNodeT>(
+  target.init_id = MakeElemAccessInst<TargetAccessInstT>(
       context, parse_node, target_id, target_elem_type, *target_block, i);
   return Convert(context, parse_node, src_elem_id, target);
 }
@@ -202,29 +202,29 @@ class CopyOnWriteBlock {
   // Constructs the block. If `source_id` is valid, it is used as the initial
   // value of the block. Otherwise, uninitialized storage for `size` elements
   // is allocated.
-  CopyOnWriteBlock(SemIR::File& file, SemIR::NodeBlockId source_id, size_t size)
+  CopyOnWriteBlock(SemIR::File& file, SemIR::InstBlockId source_id, size_t size)
       : file_(file), source_id_(source_id) {
     if (!source_id_.is_valid()) {
-      id_ = file_.node_blocks().AddUninitialized(size);
+      id_ = file_.inst_blocks().AddUninitialized(size);
     }
   }
 
-  auto id() -> SemIR::NodeBlockId const { return id_; }
+  auto id() -> SemIR::InstBlockId const { return id_; }
 
-  auto Set(int i, SemIR::NodeId value) -> void {
-    if (source_id_.is_valid() && file_.node_blocks().Get(id_)[i] == value) {
+  auto Set(int i, SemIR::InstId value) -> void {
+    if (source_id_.is_valid() && file_.inst_blocks().Get(id_)[i] == value) {
       return;
     }
     if (id_ == source_id_) {
-      id_ = file_.node_blocks().Add(file_.node_blocks().Get(source_id_));
+      id_ = file_.inst_blocks().Add(file_.inst_blocks().Get(source_id_));
     }
-    file_.node_blocks().Get(id_)[i] = value;
+    file_.inst_blocks().Get(id_)[i] = value;
   }
 
  private:
   SemIR::File& file_;
-  SemIR::NodeBlockId source_id_;
-  SemIR::NodeBlockId id_ = source_id_;
+  SemIR::InstBlockId source_id_;
+  SemIR::InstBlockId id_ = source_id_;
 };
 }  // namespace
 
@@ -232,19 +232,19 @@ class CopyOnWriteBlock {
 // final conversion to the requested expression category.
 static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
                                 SemIR::ArrayType array_type,
-                                SemIR::NodeId value_id, ConversionTarget target)
-    -> SemIR::NodeId {
+                                SemIR::InstId value_id, ConversionTarget target)
+    -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
   auto tuple_elem_types = sem_ir.type_blocks().Get(tuple_type.elements_id);
 
-  auto value = sem_ir.nodes().Get(value_id);
+  auto value = sem_ir.insts().Get(value_id);
 
   // If we're initializing from a tuple literal, we will use its elements
   // directly. Otherwise, materialize a temporary if needed and index into the
   // result.
-  llvm::ArrayRef<SemIR::NodeId> literal_elems;
+  llvm::ArrayRef<SemIR::InstId> literal_elems;
   if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {
-    literal_elems = sem_ir.node_blocks().Get(tuple_literal->elements_id);
+    literal_elems = sem_ir.inst_blocks().Get(tuple_literal->elements_id);
   } else {
     value_id = MaterializeIfInitializing(context, value_id);
   }
@@ -265,7 +265,7 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
                                ? ArrayInitFromExpressionArgCountMismatch
                                : ArrayInitFromLiteralArgCountMismatch,
                            array_bound, tuple_elem_types.size());
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   PendingBlock target_block_storage(context);
@@ -274,9 +274,9 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
 
   // Arrays are always initialized in-place. Allocate a temporary as the
   // destination for the array initialization if we weren't given one.
-  SemIR::NodeId return_slot_id = target.init_id;
+  SemIR::InstId return_slot_id = target.init_id;
   if (!target.init_id.is_valid()) {
-    return_slot_id = target_block->AddNode(
+    return_slot_id = target_block->AddInst(
         SemIR::TemporaryStorage{value.parse_node(), target.type_id});
   }
 
@@ -284,7 +284,7 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
   // tuple.
   // TODO: Annotate diagnostics coming from here with the array element index,
   // if initializing from a tuple literal.
-  llvm::SmallVector<SemIR::NodeId> inits;
+  llvm::SmallVector<SemIR::InstId> inits;
   inits.reserve(array_bound + 1);
   for (auto [i, src_type_id] : llvm::enumerate(tuple_elem_types)) {
     // TODO: This call recurses back into conversion. Switch to an iterative
@@ -294,8 +294,8 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
             context, value.parse_node(), value_id, src_type_id, literal_elems,
             ConversionTarget::FullInitializer, return_slot_id,
             array_type.element_type_id, target_block, i);
-    if (init_id == SemIR::NodeId::BuiltinError) {
-      return SemIR::NodeId::BuiltinError;
+    if (init_id == SemIR::InstId::BuiltinError) {
+      return SemIR::InstId::BuiltinError;
     }
     inits.push_back(init_id);
   }
@@ -305,31 +305,31 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
   target_block->InsertHere();
   inits.push_back(return_slot_id);
 
-  return context.AddNode(SemIR::ArrayInit{value.parse_node(), target.type_id,
+  return context.AddInst(SemIR::ArrayInit{value.parse_node(), target.type_id,
                                           value_id,
-                                          sem_ir.node_blocks().Add(inits)});
+                                          sem_ir.inst_blocks().Add(inits)});
 }
 
 // Performs a conversion from a tuple to a tuple type. Does not perform a
 // final conversion to the requested expression category.
 static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
                                 SemIR::TupleType dest_type,
-                                SemIR::NodeId value_id, ConversionTarget target)
-    -> SemIR::NodeId {
+                                SemIR::InstId value_id, ConversionTarget target)
+    -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
   auto src_elem_types = sem_ir.type_blocks().Get(src_type.elements_id);
   auto dest_elem_types = sem_ir.type_blocks().Get(dest_type.elements_id);
 
-  auto value = sem_ir.nodes().Get(value_id);
+  auto value = sem_ir.insts().Get(value_id);
 
   // If we're initializing from a tuple literal, we will use its elements
   // directly. Otherwise, materialize a temporary if needed and index into the
   // result.
-  llvm::ArrayRef<SemIR::NodeId> literal_elems;
-  auto literal_elems_id = SemIR::NodeBlockId::Invalid;
+  llvm::ArrayRef<SemIR::InstId> literal_elems;
+  auto literal_elems_id = SemIR::InstBlockId::Invalid;
   if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {
     literal_elems_id = tuple_literal->elements_id;
-    literal_elems = sem_ir.node_blocks().Get(literal_elems_id);
+    literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);
   } else {
     value_id = MaterializeIfInitializing(context, value_id);
   }
@@ -342,7 +342,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
                       size_t, size_t);
     context.emitter().Emit(value.parse_node(), TupleInitElementCountMismatch,
                            dest_elem_types.size(), src_elem_types.size());
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // If we're forming an initializer, then we want an initializer for each
@@ -369,16 +369,16 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
         ConvertAggregateElement<SemIR::TupleAccess, SemIR::TupleAccess>(
             context, value.parse_node(), value_id, src_type_id, literal_elems,
             inner_kind, target.init_id, dest_type_id, target.init_block, i);
-    if (init_id == SemIR::NodeId::BuiltinError) {
-      return SemIR::NodeId::BuiltinError;
+    if (init_id == SemIR::InstId::BuiltinError) {
+      return SemIR::InstId::BuiltinError;
     }
     new_block.Set(i, init_id);
   }
 
-  return is_init ? context.AddNode(SemIR::TupleInit{value.parse_node(),
+  return is_init ? context.AddInst(SemIR::TupleInit{value.parse_node(),
                                                     target.type_id, value_id,
                                                     new_block.id()})
-                 : context.AddNode(SemIR::TupleValue{value.parse_node(),
+                 : context.AddInst(SemIR::TupleValue{value.parse_node(),
                                                      target.type_id, value_id,
                                                      new_block.id()});
 }
@@ -387,22 +387,22 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
 // final conversion to the requested expression category.
 static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
                                   SemIR::StructType dest_type,
-                                  SemIR::NodeId value_id,
-                                  ConversionTarget target) -> SemIR::NodeId {
+                                  SemIR::InstId value_id,
+                                  ConversionTarget target) -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
-  auto src_elem_fields = sem_ir.node_blocks().Get(src_type.fields_id);
-  auto dest_elem_fields = sem_ir.node_blocks().Get(dest_type.fields_id);
+  auto src_elem_fields = sem_ir.inst_blocks().Get(src_type.fields_id);
+  auto dest_elem_fields = sem_ir.inst_blocks().Get(dest_type.fields_id);
 
-  auto value = sem_ir.nodes().Get(value_id);
+  auto value = sem_ir.insts().Get(value_id);
 
   // If we're initializing from a struct literal, we will use its elements
   // directly. Otherwise, materialize a temporary if needed and index into the
   // result.
-  llvm::ArrayRef<SemIR::NodeId> literal_elems;
-  auto literal_elems_id = SemIR::NodeBlockId::Invalid;
+  llvm::ArrayRef<SemIR::InstId> literal_elems;
+  auto literal_elems_id = SemIR::InstBlockId::Invalid;
   if (auto struct_literal = value.TryAs<SemIR::StructLiteral>()) {
     literal_elems_id = struct_literal->elements_id;
-    literal_elems = sem_ir.node_blocks().Get(literal_elems_id);
+    literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);
   } else {
     value_id = MaterializeIfInitializing(context, value_id);
   }
@@ -417,7 +417,7 @@ static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
                       size_t, size_t);
     context.emitter().Emit(value.parse_node(), StructInitElementCountMismatch,
                            dest_elem_fields.size(), src_elem_fields.size());
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // Prepare to look up fields in the source by index.
@@ -425,7 +425,7 @@ static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
   if (src_type.fields_id != dest_type.fields_id) {
     for (auto [i, field_id] : llvm::enumerate(src_elem_fields)) {
       auto [it, added] = src_field_indexes.insert(
-          {context.nodes().GetAs<SemIR::StructTypeField>(field_id).name_id, i});
+          {context.insts().GetAs<SemIR::StructTypeField>(field_id).name_id, i});
       CARBON_CHECK(added) << "Duplicate field in source structure";
     }
   }
@@ -448,7 +448,7 @@ static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
   CopyOnWriteBlock new_block(sem_ir, literal_elems_id, src_elem_fields.size());
   for (auto [i, dest_field_id] : llvm::enumerate(dest_elem_fields)) {
     auto dest_field =
-        sem_ir.nodes().GetAs<SemIR::StructTypeField>(dest_field_id);
+        sem_ir.insts().GetAs<SemIR::StructTypeField>(dest_field_id);
 
     // Find the matching source field.
     auto src_field_index = i;
@@ -474,11 +474,11 @@ static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
                                  sem_ir.StringifyType(target.type_id),
                                  sem_ir.strings().Get(dest_field.name_id));
         }
-        return SemIR::NodeId::BuiltinError;
+        return SemIR::InstId::BuiltinError;
       }
       src_field_index = src_field_it->second;
     }
-    auto src_field = sem_ir.nodes().GetAs<SemIR::StructTypeField>(
+    auto src_field = sem_ir.insts().GetAs<SemIR::StructTypeField>(
         src_elem_fields[src_field_index]);
 
     // TODO: This call recurses back into conversion. Switch to an iterative
@@ -488,16 +488,16 @@ static auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,
             context, value.parse_node(), value_id, src_field.field_type_id,
             literal_elems, inner_kind, target.init_id, dest_field.field_type_id,
             target.init_block, src_field_index);
-    if (init_id == SemIR::NodeId::BuiltinError) {
-      return SemIR::NodeId::BuiltinError;
+    if (init_id == SemIR::InstId::BuiltinError) {
+      return SemIR::InstId::BuiltinError;
     }
     new_block.Set(i, init_id);
   }
 
-  return is_init ? context.AddNode(SemIR::StructInit{value.parse_node(),
+  return is_init ? context.AddInst(SemIR::StructInit{value.parse_node(),
                                                      target.type_id, value_id,
                                                      new_block.id()})
-                 : context.AddNode(SemIR::StructValue{value.parse_node(),
+                 : context.AddInst(SemIR::StructValue{value.parse_node(),
                                                       target.type_id, value_id,
                                                       new_block.id()});
 }
@@ -525,13 +525,13 @@ static bool IsValidExpressionCategoryForConversionTarget(
 }
 
 static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
-                                     SemIR::NodeId value_id,
-                                     ConversionTarget target) -> SemIR::NodeId {
+                                     SemIR::InstId value_id,
+                                     ConversionTarget target) -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
-  auto value = sem_ir.nodes().Get(value_id);
+  auto value = sem_ir.insts().Get(value_id);
   auto value_type_id = value.type_id();
-  auto target_type_node =
-      sem_ir.nodes().Get(sem_ir.GetTypeAllowBuiltinTypes(target.type_id));
+  auto target_type_inst =
+      sem_ir.insts().Get(sem_ir.GetTypeAllowBuiltinTypes(target.type_id));
 
   // Various forms of implicit conversion are supported as builtin conversions,
   // either in addition to or instead of `impl`s of `ImplicitAs` in the Carbon
@@ -582,7 +582,7 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
         // The initializer produces an object representation by copy, and the
         // value representation is a copy of the object representation, so we
         // already have a value of the right form.
-        return context.AddNode(
+        return context.AddInst(
             SemIR::ValueOfInitializer{parse_node, value_type_id, value_id});
       }
     }
@@ -590,10 +590,10 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
 
   // A tuple (T1, T2, ..., Tn) converts to (U1, U2, ..., Un) if each Ti
   // converts to Ui.
-  if (auto target_tuple_type = target_type_node.TryAs<SemIR::TupleType>()) {
-    auto value_type_node =
-        sem_ir.nodes().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
-    if (auto src_tuple_type = value_type_node.TryAs<SemIR::TupleType>()) {
+  if (auto target_tuple_type = target_type_inst.TryAs<SemIR::TupleType>()) {
+    auto value_type_inst =
+        sem_ir.insts().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
+    if (auto src_tuple_type = value_type_inst.TryAs<SemIR::TupleType>()) {
       return ConvertTupleToTuple(context, *src_tuple_type, *target_tuple_type,
                                  value_id, target);
     }
@@ -603,20 +603,20 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
   // {.f_p(1): U_p(1), .f_p(2): U_p(2), ..., .f_p(n): U_p(n)} if
   // (p(1), ..., p(n)) is a permutation of (1, ..., n) and each Ti converts
   // to Ui.
-  if (auto target_struct_type = target_type_node.TryAs<SemIR::StructType>()) {
-    auto value_type_node =
-        sem_ir.nodes().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
-    if (auto src_struct_type = value_type_node.TryAs<SemIR::StructType>()) {
+  if (auto target_struct_type = target_type_inst.TryAs<SemIR::StructType>()) {
+    auto value_type_inst =
+        sem_ir.insts().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
+    if (auto src_struct_type = value_type_inst.TryAs<SemIR::StructType>()) {
       return ConvertStructToStruct(context, *src_struct_type,
                                    *target_struct_type, value_id, target);
     }
   }
 
   // A tuple (T1, T2, ..., Tn) converts to [T; n] if each Ti converts to T.
-  if (auto target_array_type = target_type_node.TryAs<SemIR::ArrayType>()) {
-    auto value_type_node =
-        sem_ir.nodes().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
-    if (auto src_tuple_type = value_type_node.TryAs<SemIR::TupleType>()) {
+  if (auto target_array_type = target_type_inst.TryAs<SemIR::ArrayType>()) {
+    auto value_type_inst =
+        sem_ir.insts().Get(sem_ir.GetTypeAllowBuiltinTypes(value_type_id));
+    if (auto src_tuple_type = value_type_inst.TryAs<SemIR::TupleType>()) {
       return ConvertTupleToArray(context, *src_tuple_type, *target_array_type,
                                  value_id, target);
     }
@@ -627,12 +627,12 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
     // TODO: This should apply even for non-literal tuples.
     if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {
       llvm::SmallVector<SemIR::TypeId> type_ids;
-      for (auto tuple_node_id :
-           sem_ir.node_blocks().Get(tuple_literal->elements_id)) {
+      for (auto tuple_inst_id :
+           sem_ir.inst_blocks().Get(tuple_literal->elements_id)) {
         // TODO: This call recurses back into conversion. Switch to an
         // iterative approach.
         type_ids.push_back(
-            ExpressionAsType(context, parse_node, tuple_node_id));
+            ExpressionAsType(context, parse_node, tuple_inst_id));
       }
       auto tuple_type_id =
           context.CanonicalizeTupleType(parse_node, std::move(type_ids));
@@ -644,7 +644,7 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
     // of type `{}`.
     if (auto struct_literal = value.TryAs<SemIR::StructLiteral>();
         struct_literal &&
-        struct_literal->elements_id == SemIR::NodeBlockId::Empty) {
+        struct_literal->elements_id == SemIR::InstBlockId::Empty) {
       value_id = sem_ir.GetTypeAllowBuiltinTypes(value_type_id);
     }
   }
@@ -655,12 +655,12 @@ static auto PerformBuiltinConversion(Context& context, Parse::Node parse_node,
 
 // Given a value expression, form a corresponding initializer that copies from
 // that value, if it is possible to do so.
-static auto PerformCopy(Context& context, SemIR::NodeId expr_id)
-    -> SemIR::NodeId {
-  auto expr = context.nodes().Get(expr_id);
+static auto PerformCopy(Context& context, SemIR::InstId expr_id)
+    -> SemIR::InstId {
+  auto expr = context.insts().Get(expr_id);
   auto type_id = expr.type_id();
   if (type_id == SemIR::TypeId::Error) {
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // TODO: Directly track on the value representation whether it's a copy of
@@ -680,19 +680,19 @@ static auto PerformCopy(Context& context, SemIR::NodeId expr_id)
                     "Cannot copy value of type `{0}`.", std::string);
   context.emitter().Emit(expr.parse_node(), CopyOfUncopyableType,
                          context.sem_ir().StringifyType(type_id));
-  return SemIR::NodeId::BuiltinError;
+  return SemIR::InstId::BuiltinError;
 }
 
-auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
-             ConversionTarget target) -> SemIR::NodeId {
+auto Convert(Context& context, Parse::Node parse_node, SemIR::InstId expr_id,
+             ConversionTarget target) -> SemIR::InstId {
   auto& sem_ir = context.sem_ir();
   auto orig_expr_id = expr_id;
 
   // Start by making sure both sides are valid. If any part is invalid, the
   // result is invalid and we shouldn't error.
-  if (sem_ir.nodes().Get(expr_id).type_id() == SemIR::TypeId::Error ||
+  if (sem_ir.insts().Get(expr_id).type_id() == SemIR::TypeId::Error ||
       target.type_id == SemIR::TypeId::Error) {
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   if (SemIR::GetExpressionCategory(sem_ir, expr_id) ==
@@ -702,9 +702,9 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
     // namespace names, and allow use of functions as values.
     CARBON_DIAGNOSTIC(UseOfNonExpressionAsValue, Error,
                       "Expression cannot be used as a value.");
-    context.emitter().Emit(sem_ir.nodes().Get(expr_id).parse_node(),
+    context.emitter().Emit(sem_ir.insts().Get(expr_id).parse_node(),
                            UseOfNonExpressionAsValue);
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // We can only perform initialization for complete types.
@@ -725,19 +725,19 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
                 : IncompleteTypeInConversion,
             context.sem_ir().StringifyType(target.type_id, true));
       })) {
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // Check whether any builtin conversion applies.
   expr_id = PerformBuiltinConversion(context, parse_node, expr_id, target);
-  if (expr_id == SemIR::NodeId::BuiltinError) {
+  if (expr_id == SemIR::InstId::BuiltinError) {
     return expr_id;
   }
 
   // If the types don't match at this point, we can't perform the conversion.
   // TODO: Look for an `ImplicitAs` impl, or an `As` impl in the case where
   // `target.kind == ConversionTarget::ExplicitAs`.
-  SemIR::Node expr = sem_ir.nodes().Get(expr_id);
+  SemIR::Inst expr = sem_ir.insts().Get(expr_id);
   if (expr.type_id() != target.type_id) {
     CARBON_DIAGNOSTIC(ImplicitAsConversionFailure, Error,
                       "Cannot implicitly convert from `{0}` to `{1}`.",
@@ -753,7 +753,7 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
                sem_ir.StringifyType(expr.type_id()),
                sem_ir.StringifyType(target.type_id))
         .Emit();
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   // For `as`, don't perform any value category conversions. In particular, an
@@ -770,7 +770,7 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
                      << " after builtin conversions";
 
     case SemIR::ExpressionCategory::Error:
-      return SemIR::NodeId::BuiltinError;
+      return SemIR::InstId::BuiltinError;
 
     case SemIR::ExpressionCategory::Initializing:
       if (target.is_initializer()) {
@@ -803,7 +803,7 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId 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.AddNode(
+      expr_id = context.AddInst(
           SemIR::BindValue{expr.parse_node(), expr.type_id(), expr_id});
       // We now have a value expression.
       [[fallthrough]];
@@ -822,7 +822,7 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
             SemIR::GetInitializingRepresentation(sem_ir, target.type_id);
         init_rep.kind == SemIR::InitializingRepresentation::ByCopy) {
       target.init_block->InsertHere();
-      expr_id = context.AddNode(SemIR::InitializeFrom{
+      expr_id = context.AddInst(SemIR::InitializeFrom{
           parse_node, target.type_id, expr_id, target.init_id});
     }
   }
@@ -831,49 +831,49 @@ auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId expr_id,
 }
 
 auto Initialize(Context& context, Parse::Node parse_node,
-                SemIR::NodeId target_id, SemIR::NodeId value_id)
-    -> SemIR::NodeId {
+                SemIR::InstId target_id, SemIR::InstId value_id)
+    -> SemIR::InstId {
   PendingBlock target_block(context);
   return Convert(context, parse_node, value_id,
                  {.kind = ConversionTarget::Initializer,
-                  .type_id = context.sem_ir().nodes().Get(target_id).type_id(),
+                  .type_id = context.sem_ir().insts().Get(target_id).type_id(),
                   .init_id = target_id,
                   .init_block = &target_block});
 }
 
-auto ConvertToValueExpression(Context& context, SemIR::NodeId expr_id)
-    -> SemIR::NodeId {
-  auto expr = context.sem_ir().nodes().Get(expr_id);
+auto ConvertToValueExpression(Context& context, SemIR::InstId expr_id)
+    -> SemIR::InstId {
+  auto expr = context.sem_ir().insts().Get(expr_id);
   return Convert(context, expr.parse_node(), expr_id,
                  {.kind = ConversionTarget::Value, .type_id = expr.type_id()});
 }
 
 auto ConvertToValueOrReferenceExpression(Context& context,
-                                         SemIR::NodeId expr_id)
-    -> SemIR::NodeId {
-  auto expr = context.sem_ir().nodes().Get(expr_id);
+                                         SemIR::InstId expr_id)
+    -> SemIR::InstId {
+  auto expr = context.sem_ir().insts().Get(expr_id);
   return Convert(
       context, expr.parse_node(), expr_id,
       {.kind = ConversionTarget::ValueOrReference, .type_id = expr.type_id()});
 }
 
 auto ConvertToValueOfType(Context& context, Parse::Node parse_node,
-                          SemIR::NodeId value_id, SemIR::TypeId type_id)
-    -> SemIR::NodeId {
+                          SemIR::InstId value_id, SemIR::TypeId type_id)
+    -> SemIR::InstId {
   return Convert(context, parse_node, value_id,
                  {.kind = ConversionTarget::Value, .type_id = type_id});
 }
 
 auto ConvertToBoolValue(Context& context, Parse::Node parse_node,
-                        SemIR::NodeId value_id) -> SemIR::NodeId {
+                        SemIR::InstId value_id) -> SemIR::InstId {
   return ConvertToValueOfType(
       context, parse_node, value_id,
       context.GetBuiltinType(SemIR::BuiltinKind::BoolType));
 }
 
 auto ConvertForExplicitAs(Context& context, Parse::Node as_node,
-                          SemIR::NodeId value_id, SemIR::TypeId type_id)
-    -> SemIR::NodeId {
+                          SemIR::InstId value_id, SemIR::TypeId type_id)
+    -> SemIR::InstId {
   return Convert(context, as_node, value_id,
                  {.kind = ConversionTarget::ExplicitAs, .type_id = type_id});
 }
@@ -883,8 +883,8 @@ CARBON_DIAGNOSTIC(InCallToFunction, Note, "Calling function declared here.");
 // Convert the object argument in a method call to match the `self` parameter.
 static auto ConvertSelf(Context& context, Parse::Node call_parse_node,
                         Parse::Node callee_parse_node,
-                        SemIR::SelfParameter self_param, SemIR::NodeId self_id)
-    -> SemIR::NodeId {
+                        SemIR::SelfParameter self_param, SemIR::InstId self_id)
+    -> SemIR::InstId {
   if (!self_id.is_valid()) {
     CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,
                       "Missing object argument in method call.");
@@ -892,7 +892,7 @@ static auto ConvertSelf(Context& context, Parse::Node call_parse_node,
         .Build(call_parse_node, MissingObjectInMethodCall)
         .Note(callee_parse_node, InCallToFunction)
         .Emit();
-    return SemIR::NodeId::BuiltinError;
+    return SemIR::InstId::BuiltinError;
   }
 
   DiagnosticAnnotationScope annotate_diagnostics(
@@ -912,7 +912,7 @@ static auto ConvertSelf(Context& context, Parse::Node call_parse_node,
   if (self_param.is_addr_self.index) {
     self_or_addr_id =
         ConvertToValueOrReferenceExpression(context, self_or_addr_id);
-    auto self = context.nodes().Get(self_or_addr_id);
+    auto self = context.insts().Get(self_or_addr_id);
     switch (SemIR::GetExpressionCategory(context.sem_ir(), self_id)) {
       case SemIR::ExpressionCategory::Error:
       case SemIR::ExpressionCategory::DurableReference:
@@ -922,9 +922,9 @@ static auto ConvertSelf(Context& context, Parse::Node call_parse_node,
         CARBON_DIAGNOSTIC(AddrSelfIsNonReference, Error,
                           "`addr self` method cannot be invoked on a value.");
         context.emitter().Emit(call_parse_node, AddrSelfIsNonReference);
-        return SemIR::NodeId::BuiltinError;
+        return SemIR::InstId::BuiltinError;
     }
-    self_or_addr_id = context.AddNode(SemIR::AddressOf{
+    self_or_addr_id = context.AddInst(SemIR::AddressOf{
         self.parse_node(),
         context.GetPointerType(self.parse_node(), self.type_id()),
         self_or_addr_id});
@@ -935,15 +935,15 @@ static auto ConvertSelf(Context& context, Parse::Node call_parse_node,
 }
 
 auto ConvertCallArgs(Context& context, Parse::Node call_parse_node,
-                     SemIR::NodeId self_id,
-                     llvm::ArrayRef<SemIR::NodeId> arg_refs,
-                     SemIR::NodeId return_storage_id,
+                     SemIR::InstId self_id,
+                     llvm::ArrayRef<SemIR::InstId> arg_refs,
+                     SemIR::InstId return_storage_id,
                      Parse::Node callee_parse_node,
-                     SemIR::NodeBlockId implicit_param_refs_id,
-                     SemIR::NodeBlockId param_refs_id) -> SemIR::NodeBlockId {
+                     SemIR::InstBlockId implicit_param_refs_id,
+                     SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId {
   auto implicit_param_refs =
-      context.sem_ir().node_blocks().Get(implicit_param_refs_id);
-  auto param_refs = context.sem_ir().node_blocks().Get(param_refs_id);
+      context.sem_ir().inst_blocks().Get(implicit_param_refs_id);
+  auto param_refs = context.sem_ir().inst_blocks().Get(param_refs_id);
 
   // If sizes mismatch, fail early.
   if (arg_refs.size() != param_refs.size()) {
@@ -956,28 +956,28 @@ auto ConvertCallArgs(Context& context, Parse::Node call_parse_node,
                param_refs.size())
         .Note(callee_parse_node, InCallToFunction)
         .Emit();
-    return SemIR::NodeBlockId::Invalid;
+    return SemIR::InstBlockId::Invalid;
   }
 
   // Start building a block to hold the converted arguments.
-  llvm::SmallVector<SemIR::NodeId> args;
+  llvm::SmallVector<SemIR::InstId> args;
   args.reserve(implicit_param_refs.size() + param_refs.size() +
                return_storage_id.is_valid());
 
   // Check implicit parameters.
   for (auto implicit_param_id : implicit_param_refs) {
-    auto param = context.nodes().Get(implicit_param_id);
+    auto param = context.insts().Get(implicit_param_id);
     if (auto self_param = param.TryAs<SemIR::SelfParameter>()) {
       auto converted_self_id = ConvertSelf(
           context, call_parse_node, callee_parse_node, *self_param, self_id);
-      if (converted_self_id == SemIR::NodeId::BuiltinError) {
-        return SemIR::NodeBlockId::Invalid;
+      if (converted_self_id == SemIR::InstId::BuiltinError) {
+        return SemIR::InstBlockId::Invalid;
       }
       args.push_back(converted_self_id);
     } else {
       // TODO: Form argument values for implicit parameters.
       context.TODO(call_parse_node, "Call with implicit parameters");
-      return SemIR::NodeBlockId::Invalid;
+      return SemIR::InstBlockId::Invalid;
     }
   }
 
@@ -995,13 +995,13 @@ auto ConvertCallArgs(Context& context, Parse::Node call_parse_node,
   for (auto [i, arg_id, param_id] : llvm::enumerate(arg_refs, param_refs)) {
     diag_param_index = i;
 
-    auto param_type_id = context.sem_ir().nodes().Get(param_id).type_id();
+    auto param_type_id = context.sem_ir().insts().Get(param_id).type_id();
     // TODO: Convert to the proper expression category. For now, we assume
     // parameters are all `let` bindings.
     auto converted_arg_id =
         ConvertToValueOfType(context, call_parse_node, arg_id, param_type_id);
-    if (converted_arg_id == SemIR::NodeId::BuiltinError) {
-      return SemIR::NodeBlockId::Invalid;
+    if (converted_arg_id == SemIR::InstId::BuiltinError) {
+      return SemIR::InstBlockId::Invalid;
     }
 
     args.push_back(converted_arg_id);
@@ -1012,11 +1012,11 @@ auto ConvertCallArgs(Context& context, Parse::Node call_parse_node,
     args.push_back(return_storage_id);
   }
 
-  return context.node_blocks().Add(args);
+  return context.inst_blocks().Add(args);
 }
 
 auto ExpressionAsType(Context& context, Parse::Node parse_node,
-                      SemIR::NodeId value_id) -> SemIR::TypeId {
+                      SemIR::InstId value_id) -> SemIR::TypeId {
   return context.CanonicalizeType(ConvertToValueOfType(
       context, parse_node, value_id, SemIR::TypeId::TypeType));
 }

+ 21 - 21
toolchain/check/convert.h

@@ -8,7 +8,7 @@
 #include "toolchain/check/context.h"
 #include "toolchain/check/pending_block.h"
 #include "toolchain/parse/tree.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -39,7 +39,7 @@ struct ConversionTarget {
   // The target type for the conversion.
   SemIR::TypeId type_id;
   // For an initializer, the object being initialized.
-  SemIR::NodeId init_id = SemIR::NodeId::Invalid;
+  SemIR::InstId init_id = SemIR::InstId::Invalid;
   // For an initializer, a block of pending instructions that are needed to
   // form the value of `target_id`, and that can be discarded if no
   // initialization is needed.
@@ -52,54 +52,54 @@ struct ConversionTarget {
 };
 
 // Convert a value to another type and expression category.
-auto Convert(Context& context, Parse::Node parse_node, SemIR::NodeId value_id,
-             ConversionTarget target) -> SemIR::NodeId;
+auto Convert(Context& context, Parse::Node parse_node, SemIR::InstId value_id,
+             ConversionTarget target) -> SemIR::InstId;
 
 // Performs initialization of `target_id` from `value_id`. Returns the
 // possibly-converted initializing expression, which should be assigned to the
 // target using a suitable node for the kind of initialization.
 auto Initialize(Context& context, Parse::Node parse_node,
-                SemIR::NodeId target_id, SemIR::NodeId value_id)
-    -> SemIR::NodeId;
+                SemIR::InstId target_id, SemIR::InstId value_id)
+    -> SemIR::InstId;
 
 // Convert the given expression to a value expression of the same type.
-auto ConvertToValueExpression(Context& context, SemIR::NodeId expr_id)
-    -> SemIR::NodeId;
+auto ConvertToValueExpression(Context& context, SemIR::InstId expr_id)
+    -> SemIR::InstId;
 
 // Convert the given expression to a value or reference expression of the same
 // type.
 auto ConvertToValueOrReferenceExpression(Context& context,
-                                         SemIR::NodeId expr_id)
-    -> SemIR::NodeId;
+                                         SemIR::InstId expr_id)
+    -> SemIR::InstId;
 
 // Converts `value_id` to a value expression of type `type_id`.
 auto ConvertToValueOfType(Context& context, Parse::Node parse_node,
-                          SemIR::NodeId value_id, SemIR::TypeId type_id)
-    -> SemIR::NodeId;
+                          SemIR::InstId value_id, SemIR::TypeId type_id)
+    -> SemIR::InstId;
 
 // Converts `value_id` to a value expression of type `bool`.
 auto ConvertToBoolValue(Context& context, Parse::Node parse_node,
-                        SemIR::NodeId value_id) -> SemIR::NodeId;
+                        SemIR::InstId value_id) -> SemIR::InstId;
 
 // Converts `value_id` to type `type_id` for an `as` expression.
 auto ConvertForExplicitAs(Context& context, Parse::Node as_node,
-                          SemIR::NodeId value_id, SemIR::TypeId type_id)
-    -> SemIR::NodeId;
+                          SemIR::InstId value_id, SemIR::TypeId type_id)
+    -> SemIR::InstId;
 
 // Implicitly converts a set of arguments to match the parameter types in a
 // function call. Returns a block containing the converted implicit and explicit
 // argument values.
 auto ConvertCallArgs(Context& context, Parse::Node call_parse_node,
-                     SemIR::NodeId self_id,
-                     llvm::ArrayRef<SemIR::NodeId> arg_refs,
-                     SemIR::NodeId return_storage_id,
+                     SemIR::InstId self_id,
+                     llvm::ArrayRef<SemIR::InstId> arg_refs,
+                     SemIR::InstId return_storage_id,
                      Parse::Node callee_parse_node,
-                     SemIR::NodeBlockId implicit_param_refs_id,
-                     SemIR::NodeBlockId param_refs_id) -> SemIR::NodeBlockId;
+                     SemIR::InstBlockId implicit_param_refs_id,
+                     SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId;
 
 // Converts an expression for use as a type.
 auto ExpressionAsType(Context& context, Parse::Node parse_node,
-                      SemIR::NodeId value_id) -> SemIR::TypeId;
+                      SemIR::InstId value_id) -> SemIR::TypeId;
 
 }  // namespace Carbon::Check
 

+ 23 - 22
toolchain/check/declaration_name_stack.cpp

@@ -43,12 +43,12 @@ auto DeclarationNameStack::Pop() -> NameContext {
 }
 
 auto DeclarationNameStack::LookupOrAddName(NameContext name_context,
-                                           SemIR::NodeId target_id)
-    -> SemIR::NodeId {
+                                           SemIR::InstId target_id)
+    -> SemIR::InstId {
   switch (name_context.state) {
     case NameContext::State::Error:
       // The name is invalid and a diagnostic has already been emitted.
-      return SemIR::NodeId::Invalid;
+      return SemIR::InstId::Invalid;
 
     case NameContext::State::Empty:
       CARBON_FATAL() << "Name is missing, not expected to call AddNameToLookup "
@@ -56,7 +56,7 @@ auto DeclarationNameStack::LookupOrAddName(NameContext name_context,
 
     case NameContext::State::Resolved:
     case NameContext::State::ResolvedNonScope:
-      return name_context.resolved_node_id;
+      return name_context.resolved_inst_id;
 
     case NameContext::State::Unresolved:
       if (name_context.target_scope_id == SemIR::NameScopeId::Invalid) {
@@ -73,15 +73,15 @@ auto DeclarationNameStack::LookupOrAddName(NameContext name_context,
             << name_context.unresolved_name_id << " in "
             << name_context.target_scope_id;
       }
-      return SemIR::NodeId::Invalid;
+      return SemIR::InstId::Invalid;
   }
 }
 
 auto DeclarationNameStack::AddNameToLookup(NameContext name_context,
-                                           SemIR::NodeId target_id) -> void {
-  auto existing_node_id = LookupOrAddName(name_context, target_id);
-  if (existing_node_id.is_valid()) {
-    context_->DiagnoseDuplicateName(name_context.parse_node, existing_node_id);
+                                           SemIR::InstId target_id) -> void {
+  auto existing_inst_id = LookupOrAddName(name_context, target_id);
+  if (existing_inst_id.is_valid()) {
+    context_->DiagnoseDuplicateName(name_context.parse_node, existing_inst_id);
   }
 }
 
@@ -95,22 +95,23 @@ auto DeclarationNameStack::ApplyNameQualifierTo(NameContext& name_context,
                                                 StringId name_id) -> void {
   if (CanResolveQualifier(name_context, parse_node)) {
     // For identifier nodes, we need to perform a lookup on the identifier.
-    // This means the input node_id is actually a string ID.
+    // This means the input instruction name_id is actually a string ID.
     //
     // TODO: This doesn't perform the right kind of lookup. We will find names
     // from enclosing lexical scopes here, in the case where `target_scope_id`
     // is invalid.
-    auto resolved_node_id = context_->LookupName(
+    auto resolved_inst_id = context_->LookupName(
         name_context.parse_node, name_id, name_context.target_scope_id,
         /*print_diagnostics=*/false);
-    if (resolved_node_id == SemIR::NodeId::BuiltinError) {
-      // Invalid indicates an unresolved node. Store it and return.
+    if (resolved_inst_id == SemIR::InstId::BuiltinError) {
+      // Invalid indicates an unresolved instruction. Store it and return.
       name_context.state = NameContext::State::Unresolved;
       name_context.unresolved_name_id = name_id;
       return;
     } else {
-      // Store the resolved node and continue for the target scope update.
-      name_context.resolved_node_id = resolved_node_id;
+      // Store the resolved instruction and continue for the target scope
+      // update.
+      name_context.resolved_inst_id = resolved_inst_id;
     }
 
     UpdateScopeIfNeeded(name_context);
@@ -119,13 +120,13 @@ auto DeclarationNameStack::ApplyNameQualifierTo(NameContext& name_context,
 
 auto DeclarationNameStack::UpdateScopeIfNeeded(NameContext& name_context)
     -> void {
-  // This will only be reached for resolved nodes. We update the target
+  // This will only be reached for resolved instructions. We update the target
   // scope based on the resolved type.
-  auto resolved_node = context_->nodes().Get(name_context.resolved_node_id);
-  switch (resolved_node.kind()) {
+  auto resolved_inst = context_->insts().Get(name_context.resolved_inst_id);
+  switch (resolved_inst.kind()) {
     case SemIR::ClassDeclaration::Kind: {
       const auto& class_info = context_->classes().Get(
-          resolved_node.As<SemIR::ClassDeclaration>().class_id);
+          resolved_inst.As<SemIR::ClassDeclaration>().class_id);
       if (class_info.is_defined()) {
         name_context.state = NameContext::State::Resolved;
         name_context.target_scope_id = class_info.scope_id;
@@ -137,7 +138,7 @@ auto DeclarationNameStack::UpdateScopeIfNeeded(NameContext& name_context)
     case SemIR::Namespace::Kind:
       name_context.state = NameContext::State::Resolved;
       name_context.target_scope_id =
-          resolved_node.As<SemIR::Namespace>().name_scope_id;
+          resolved_inst.As<SemIR::Namespace>().name_scope_id;
       break;
     default:
       name_context.state = NameContext::State::ResolvedNonScope;
@@ -163,8 +164,8 @@ auto DeclarationNameStack::CanResolveQualifier(NameContext& name_context,
     case NameContext::State::ResolvedNonScope: {
       // Because more qualifiers were found, we diagnose that the earlier
       // qualifier didn't resolve to a scoped entity.
-      if (auto class_decl = context_->nodes()
-                                .Get(name_context.resolved_node_id)
+      if (auto class_decl = context_->insts()
+                                .Get(name_context.resolved_inst_id)
                                 .TryAs<SemIR::ClassDeclaration>()) {
         CARBON_DIAGNOSTIC(QualifiedDeclarationInIncompleteClassScope, Error,
                           "Cannot declare a member of incomplete class `{0}`.",

+ 12 - 12
toolchain/check/declaration_name_stack.h

@@ -7,7 +7,7 @@
 
 #include "llvm/ADT/SmallVector.h"
 #include "toolchain/parse/tree.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -55,11 +55,11 @@ class DeclarationNameStack {
       // A context that has not processed any parts of the qualifier.
       Empty,
 
-      // A node ID has been resolved, whether through an identifier or
+      // An instruction ID has been resolved, whether through an identifier or
       // expression. This provided a new scope, such as a type.
       Resolved,
 
-      // A node ID has been resolved, whether through an identifier or
+      // An instruction ID has been resolved, whether through an identifier or
       // expression. It did not provide a new scope, so must be the final part,
       // such as an out-of-line function definition.
       ResolvedNonScope,
@@ -85,7 +85,7 @@ class DeclarationNameStack {
     union {
       // The ID of a resolved qualifier, including both identifiers and
       // expressions. Invalid indicates resolution failed.
-      SemIR::NodeId resolved_node_id = SemIR::NodeId::Invalid;
+      SemIR::InstId resolved_inst_id = SemIR::InstId::Invalid;
 
       // The ID of an unresolved identifier.
       StringId unresolved_name_id;
@@ -100,7 +100,7 @@ class DeclarationNameStack {
 
   // Pops the current declaration name processing, returning the final context
   // for adding the name to lookup. This also pops the final name node from the
-  // node stack, which will be applied to the declaration name if appropriate.
+  // name stack, which will be applied to the declaration name if appropriate.
   auto Pop() -> NameContext;
 
   // Creates and returns a name context corresponding to declaring an
@@ -110,24 +110,24 @@ class DeclarationNameStack {
   auto MakeUnqualifiedName(Parse::Node parse_node, StringId name_id)
       -> NameContext;
 
-  // Applies a Name from the node stack to the top of the declaration name
+  // Applies a Name from the name stack to the top of the declaration name
   // stack.
   auto ApplyNameQualifier(Parse::Node parse_node, StringId name_id) -> void;
 
   // Adds a name to name lookup. Prints a diagnostic for name conflicts.
-  auto AddNameToLookup(NameContext name_context, SemIR::NodeId target_id)
+  auto AddNameToLookup(NameContext name_context, SemIR::InstId target_id)
       -> void;
 
-  // Adds a name to name lookup, or returns the existing node if this name has
-  // already been declared in this scope.
-  auto LookupOrAddName(NameContext name_context, SemIR::NodeId target_id)
-      -> SemIR::NodeId;
+  // Adds a name to name lookup, or returns the existing instruction if this
+  // name has already been declared in this scope.
+  auto LookupOrAddName(NameContext name_context, SemIR::InstId target_id)
+      -> SemIR::InstId;
 
  private:
   // Returns a name context corresponding to an empty name.
   auto MakeEmptyNameContext() -> NameContext;
 
-  // Applies a Name from the node stack to given name context.
+  // Applies a Name from the name stack to given name context.
   auto ApplyNameQualifierTo(NameContext& name_context, Parse::Node parse_node,
                             StringId name_id) -> void;
 

+ 9 - 9
toolchain/check/handle_array.cpp

@@ -5,7 +5,7 @@
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
 #include "toolchain/parse/node_kind.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Check {
@@ -30,26 +30,26 @@ auto HandleArrayExpression(Context& context, Parse::Node parse_node) -> bool {
     return context.TODO(parse_node, "HandleArrayExpressionWithoutBounds");
   }
 
-  auto bound_node_id = context.node_stack().PopExpression();
+  auto bound_inst_id = context.node_stack().PopExpression();
   context.node_stack()
       .PopAndDiscardSoloParseNode<Parse::NodeKind::ArrayExpressionSemi>();
-  auto element_type_node_id = context.node_stack().PopExpression();
-  auto bound_node = context.nodes().Get(bound_node_id);
-  if (auto literal = bound_node.TryAs<SemIR::IntegerLiteral>()) {
+  auto element_type_inst_id = context.node_stack().PopExpression();
+  auto bound_inst = context.insts().Get(bound_inst_id);
+  if (auto literal = bound_inst.TryAs<SemIR::IntegerLiteral>()) {
     const auto& bound_value = context.integers().Get(literal->integer_id);
     // TODO: Produce an error if the array type is too large.
     if (bound_value.getActiveBits() <= 64) {
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::ArrayType{
-              parse_node, SemIR::TypeId::TypeType, bound_node_id,
-              ExpressionAsType(context, parse_node, element_type_node_id)});
+              parse_node, SemIR::TypeId::TypeType, bound_inst_id,
+              ExpressionAsType(context, parse_node, element_type_inst_id)});
       return true;
     }
   }
   CARBON_DIAGNOSTIC(InvalidArrayExpression, Error, "Invalid array expression.");
   context.emitter().Emit(parse_node, InvalidArrayExpression);
-  context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
+  context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
   return true;
 }
 

+ 10 - 10
toolchain/check/handle_call_expression.cpp

@@ -5,7 +5,7 @@
 #include "llvm/ADT/ScopeExit.h"
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -22,7 +22,7 @@ auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
 
   auto diagnose_not_callable = [&, call_expr_parse_node = call_expr_parse_node,
                                 callee_id = callee_id] {
-    auto callee_type_id = context.nodes().Get(callee_id).type_id();
+    auto callee_type_id = context.insts().Get(callee_id).type_id();
     if (callee_type_id != SemIR::TypeId::Error) {
       CARBON_DIAGNOSTIC(CallToNonCallable, Error,
                         "Value of type `{0}` is not callable.", std::string);
@@ -30,15 +30,15 @@ auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
           call_expr_parse_node, CallToNonCallable,
           context.sem_ir().StringifyType(callee_type_id, true));
     }
-    context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
+    context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
     return true;
   };
 
   // For a method call, pick out the `self` value.
   auto function_callee_id = callee_id;
-  SemIR::NodeId self_id = SemIR::NodeId::Invalid;
+  SemIR::InstId self_id = SemIR::InstId::Invalid;
   if (auto bound_method =
-          context.nodes().Get(callee_id).TryAs<SemIR::BoundMethod>()) {
+          context.insts().Get(callee_id).TryAs<SemIR::BoundMethod>()) {
     self_id = bound_method->object_id;
     function_callee_id = bound_method->function_id;
   }
@@ -49,7 +49,7 @@ auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
     return diagnose_not_callable();
   }
   auto function_decl =
-      context.nodes().Get(function_decl_id).TryAs<SemIR::FunctionDeclaration>();
+      context.insts().Get(function_decl_id).TryAs<SemIR::FunctionDeclaration>();
   if (!function_decl) {
     return diagnose_not_callable();
   }
@@ -64,11 +64,11 @@ auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
   }
 
   // If there is a return slot, build storage for the result.
-  SemIR::NodeId return_storage_id = SemIR::NodeId::Invalid;
+  SemIR::InstId return_storage_id = SemIR::InstId::Invalid;
   if (callable.return_slot_id.is_valid()) {
     // Tentatively put storage for a temporary in the function's return slot.
     // This will be replaced if necessary when we perform initialization.
-    return_storage_id = context.AddNode(
+    return_storage_id = context.AddInst(
         SemIR::TemporaryStorage{call_expr_parse_node, callable.return_type_id});
   }
 
@@ -78,10 +78,10 @@ auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
                       context.params_or_args_stack().PeekCurrentBlockContents(),
                       return_storage_id, function_decl->parse_node,
                       callable.implicit_param_refs_id, callable.param_refs_id);
-  auto call_node_id = context.AddNode(
+  auto call_inst_id = context.AddInst(
       SemIR::Call{call_expr_parse_node, type_id, callee_id, converted_args_id});
 
-  context.node_stack().Push(parse_node, call_node_id);
+  context.node_stack().Push(parse_node, call_inst_id);
   return true;
 }
 

+ 15 - 14
toolchain/check/handle_class.cpp

@@ -8,9 +8,9 @@
 namespace Carbon::Check {
 
 auto HandleClassIntroducer(Context& context, Parse::Node parse_node) -> bool {
-  // Create a node block to hold the nodes created as part of the class
-  // signature, such as generic parameters.
-  context.node_block_stack().Push();
+  // Create an instruction block to hold the instructions created as part of the
+  // class signature, such as generic parameters.
+  context.inst_block_stack().Push();
   // Push the bracketing node.
   context.node_stack().Push(parse_node);
   // A name should always follow.
@@ -19,24 +19,24 @@ auto HandleClassIntroducer(Context& context, Parse::Node parse_node) -> bool {
 }
 
 static auto BuildClassDeclaration(Context& context)
-    -> std::tuple<SemIR::ClassId, SemIR::NodeId> {
+    -> std::tuple<SemIR::ClassId, SemIR::InstId> {
   auto name_context = context.declaration_name_stack().Pop();
   auto class_keyword =
       context.node_stack()
           .PopForSoloParseNode<Parse::NodeKind::ClassIntroducer>();
-  auto decl_block_id = context.node_block_stack().Pop();
+  auto decl_block_id = context.inst_block_stack().Pop();
 
   // Add the class declaration.
   auto class_decl = SemIR::ClassDeclaration{
       class_keyword, SemIR::ClassId::Invalid, decl_block_id};
-  auto class_decl_id = context.AddNode(class_decl);
+  auto class_decl_id = context.AddInst(class_decl);
 
   // Check whether this is a redeclaration.
   auto existing_id = context.declaration_name_stack().LookupOrAddName(
       name_context, class_decl_id);
   if (existing_id.is_valid()) {
     if (auto existing_class_decl =
-            context.nodes().Get(existing_id).TryAs<SemIR::ClassDeclaration>()) {
+            context.insts().Get(existing_id).TryAs<SemIR::ClassDeclaration>()) {
       // This is a redeclaration of an existing class.
       class_decl.class_id = existing_class_decl->class_id;
     } else {
@@ -62,13 +62,13 @@ static auto BuildClassDeclaration(Context& context)
     // Build the `Self` type.
     auto& class_info = context.classes().Get(class_decl.class_id);
     class_info.self_type_id =
-        context.CanonicalizeType(context.AddNode(SemIR::ClassType{
+        context.CanonicalizeType(context.AddInst(SemIR::ClassType{
             class_keyword, context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
             class_decl.class_id}));
   }
 
   // Write the class ID into the ClassDeclaration.
-  context.nodes().Set(class_decl_id, class_decl);
+  context.insts().Set(class_decl_id, class_decl);
 
   return {class_decl.class_id, class_decl_id};
 }
@@ -93,7 +93,7 @@ auto HandleClassDefinitionStart(Context& context, Parse::Node parse_node)
     context.emitter()
         .Build(parse_node, ClassRedefinition,
                context.strings().Get(class_info.name_id))
-        .Note(context.nodes().Get(class_info.definition_id).parse_node(),
+        .Note(context.insts().Get(class_info.definition_id).parse_node(),
               ClassPreviousDefinition)
         .Emit();
   } else {
@@ -114,7 +114,7 @@ auto HandleClassDefinitionStart(Context& context, Parse::Node parse_node)
           Lex::TokenKind::SelfTypeIdentifier.fixed_spelling()),
       context.sem_ir().GetTypeAllowBuiltinTypes(class_info.self_type_id));
 
-  context.node_block_stack().Push();
+  context.inst_block_stack().Push();
   context.node_stack().Push(parse_node, class_id);
   context.args_type_info_stack().Push();
 
@@ -125,8 +125,9 @@ auto HandleClassDefinitionStart(Context& context, Parse::Node parse_node)
   //     var v: if true then i32 else f64;
   //   }
   //
-  // We may need to track a list of node blocks here, as we do for a function.
-  class_info.body_block_id = context.node_block_stack().PeekOrAdd();
+  // We may need to track a list of instruction blocks here, as we do for a
+  // function.
+  class_info.body_block_id = context.inst_block_stack().PeekOrAdd();
   return true;
 }
 
@@ -134,7 +135,7 @@ auto HandleClassDefinition(Context& context, Parse::Node parse_node) -> bool {
   auto fields_id = context.args_type_info_stack().Pop();
   auto class_id =
       context.node_stack().Pop<Parse::NodeKind::ClassDefinitionStart>();
-  context.node_block_stack().Pop();
+  context.inst_block_stack().Pop();
   context.PopScope();
 
   // The class type is now fully defined.

+ 27 - 27
toolchain/check/handle_function.cpp

@@ -12,7 +12,7 @@ namespace Carbon::Check {
 // handles the common logic shared by function declaration syntax and function
 // definition syntax.
 static auto BuildFunctionDeclaration(Context& context, bool is_definition)
-    -> std::pair<SemIR::FunctionId, SemIR::NodeId> {
+    -> std::pair<SemIR::FunctionId, SemIR::InstId> {
   // TODO: This contains the IR block for the parameters and return type. At
   // present, it's just loose, but it's not strictly required for parameter
   // refs; we should either stop constructing it completely or, if it turns out
@@ -20,16 +20,16 @@ static auto BuildFunctionDeclaration(Context& context, bool is_definition)
   // nowhere clear to emit, so changing storage would require addressing that
   // problem. For comparison with function calls, the IR needs to be emitted
   // prior to the call.
-  context.node_block_stack().Pop();
+  context.inst_block_stack().Pop();
 
   auto return_type_id = SemIR::TypeId::Invalid;
-  auto return_slot_id = SemIR::NodeId::Invalid;
+  auto return_slot_id = SemIR::InstId::Invalid;
   if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
       Parse::NodeKind::ReturnType) {
     auto [return_node, return_storage_id] =
         context.node_stack().PopWithParseNode<Parse::NodeKind::ReturnType>();
     auto return_node_copy = return_node;
-    return_type_id = context.nodes().Get(return_storage_id).type_id();
+    return_type_id = context.insts().Get(return_storage_id).type_id();
 
     if (!context.TryToCompleteType(return_type_id, [&] {
           CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Error,
@@ -49,12 +49,12 @@ static auto BuildFunctionDeclaration(Context& context, bool is_definition)
     }
   }
 
-  SemIR::NodeBlockId param_refs_id =
+  SemIR::InstBlockId param_refs_id =
       context.node_stack().Pop<Parse::NodeKind::ParameterList>();
-  SemIR::NodeBlockId implicit_param_refs_id =
+  SemIR::InstBlockId implicit_param_refs_id =
       context.node_stack()
           .PopIf<Parse::NodeKind::ImplicitParameterList>()
-          .value_or(SemIR::NodeBlockId::Empty);
+          .value_or(SemIR::InstBlockId::Empty);
   auto name_context = context.declaration_name_stack().Pop();
   auto fn_node =
       context.node_stack()
@@ -64,14 +64,14 @@ static auto BuildFunctionDeclaration(Context& context, bool is_definition)
   auto function_decl = SemIR::FunctionDeclaration{
       fn_node, context.GetBuiltinType(SemIR::BuiltinKind::FunctionType),
       SemIR::FunctionId::Invalid};
-  auto function_decl_id = context.AddNode(function_decl);
+  auto function_decl_id = context.AddInst(function_decl);
 
   // Check whether this is a redeclaration.
   auto existing_id = context.declaration_name_stack().LookupOrAddName(
       name_context, function_decl_id);
   if (existing_id.is_valid()) {
     if (auto existing_function_decl =
-            context.nodes()
+            context.insts()
                 .Get(existing_id)
                 .TryAs<SemIR::FunctionDeclaration>()) {
       // This is a redeclaration of an existing function.
@@ -109,12 +109,12 @@ static auto BuildFunctionDeclaration(Context& context, bool is_definition)
   }
 
   // Write the function ID into the FunctionDeclaration.
-  context.nodes().Set(function_decl_id, function_decl);
+  context.insts().Set(function_decl_id, function_decl);
 
   if (SemIR::IsEntryPoint(context.sem_ir(), function_decl.function_id)) {
     // TODO: Update this once valid signatures for the entry point are decided.
-    if (!context.node_blocks().Get(implicit_param_refs_id).empty() ||
-        !context.node_blocks().Get(param_refs_id).empty() ||
+    if (!context.inst_blocks().Get(implicit_param_refs_id).empty() ||
+        !context.inst_blocks().Get(param_refs_id).empty() ||
         (return_slot_id.is_valid() &&
          return_type_id !=
              context.GetBuiltinType(SemIR::BuiltinKind::BoolType) &&
@@ -149,12 +149,12 @@ auto HandleFunctionDefinition(Context& context, Parse::Node parse_node)
           "Missing `return` at end of function with declared return type.");
       context.emitter().Emit(parse_node, MissingReturnStatement);
     } else {
-      context.AddNode(SemIR::Return{parse_node});
+      context.AddInst(SemIR::Return{parse_node});
     }
   }
 
   context.PopScope();
-  context.node_block_stack().Pop();
+  context.inst_block_stack().Pop();
   context.return_scope_stack().pop_back();
   return true;
 }
@@ -175,7 +175,7 @@ auto HandleFunctionDefinitionStart(Context& context, Parse::Node parse_node)
     context.emitter()
         .Build(parse_node, FunctionRedefinition,
                context.strings().Get(function.name_id))
-        .Note(context.nodes().Get(function.definition_id).parse_node(),
+        .Note(context.insts().Get(function.definition_id).parse_node(),
               FunctionPreviousDefinition)
         .Emit();
   } else {
@@ -184,15 +184,15 @@ auto HandleFunctionDefinitionStart(Context& context, Parse::Node parse_node)
 
   // Create the function scope and the entry block.
   context.return_scope_stack().push_back(decl_id);
-  context.node_block_stack().Push();
+  context.inst_block_stack().Push();
   context.PushScope(decl_id);
   context.AddCurrentCodeBlockToFunction();
 
   // Bring the implicit and explicit parameters into scope.
-  for (auto param_id : llvm::concat<SemIR::NodeId>(
-           context.node_blocks().Get(function.implicit_param_refs_id),
-           context.node_blocks().Get(function.param_refs_id))) {
-    auto param = context.nodes().Get(param_id);
+  for (auto param_id : llvm::concat<SemIR::InstId>(
+           context.inst_blocks().Get(function.implicit_param_refs_id),
+           context.inst_blocks().Get(function.param_refs_id))) {
+    auto param = context.insts().Get(param_id);
 
     // The parameter types need to be complete.
     context.TryToCompleteType(param.type_id(), [&] {
@@ -227,9 +227,9 @@ auto HandleFunctionDefinitionStart(Context& context, Parse::Node parse_node)
 
 auto HandleFunctionIntroducer(Context& context, Parse::Node parse_node)
     -> bool {
-  // Create a node block to hold the nodes created as part of the function
-  // signature, such as parameter and return types.
-  context.node_block_stack().Push();
+  // Create an instruction block to hold the instructions created as part of the
+  // function signature, such as parameter and return types.
+  context.inst_block_stack().Push();
   // Push the bracketing node.
   context.node_stack().Push(parse_node);
   // A name should always follow.
@@ -239,11 +239,11 @@ auto HandleFunctionIntroducer(Context& context, Parse::Node parse_node)
 
 auto HandleReturnType(Context& context, Parse::Node parse_node) -> bool {
   // Propagate the type expression.
-  auto [type_parse_node, type_node_id] =
+  auto [type_parse_node, type_inst_id] =
       context.node_stack().PopExpressionWithParseNode();
-  auto type_id = ExpressionAsType(context, type_parse_node, type_node_id);
-  // TODO: Use a dedicated node rather than VarStorage here.
-  context.AddNodeAndPush(
+  auto type_id = ExpressionAsType(context, type_parse_node, type_inst_id);
+  // TODO: Use a dedicated instruction rather than VarStorage here.
+  context.AddInstAndPush(
       parse_node,
       SemIR::VarStorage{parse_node, type_id, context.strings().Add("return")});
   return true;

+ 4 - 4
toolchain/check/handle_if_expression.cpp

@@ -20,8 +20,8 @@ auto HandleIfExpressionIf(Context& context, Parse::Node parse_node) -> bool {
   auto else_block_id = context.AddDominatedBlockAndBranch(if_node);
 
   // Start emitting the `then` block.
-  context.node_block_stack().Pop();
-  context.node_block_stack().Push(then_block_id);
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().Push(then_block_id);
   context.AddCurrentCodeBlockToFunction();
 
   context.node_stack().Push(if_node, else_block_id);
@@ -37,7 +37,7 @@ auto HandleIfExpressionThen(Context& context, Parse::Node parse_node) -> bool {
   then_value_id = ConvertToValueExpression(context, then_value_id);
 
   // Start emitting the `else` block.
-  context.node_block_stack().Push(else_block_id);
+  context.inst_block_stack().Push(else_block_id);
   context.AddCurrentCodeBlockToFunction();
 
   context.node_stack().Push(parse_node, then_value_id);
@@ -57,7 +57,7 @@ auto HandleIfExpressionElse(Context& context, Parse::Node parse_node) -> bool {
   // Convert the `else` value to the `then` value's type, and finish the `else`
   // block.
   // TODO: Find a common type, and convert both operands to it instead.
-  auto result_type_id = context.nodes().Get(then_value_id).type_id();
+  auto result_type_id = context.insts().Get(then_value_id).type_id();
   else_value_id =
       ConvertToValueOfType(context, else_node, else_value_id, result_type_id);
 

+ 7 - 7
toolchain/check/handle_if_statement.cpp

@@ -4,7 +4,7 @@
 
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -26,8 +26,8 @@ auto HandleIfCondition(Context& context, Parse::Node parse_node) -> bool {
   auto else_block_id = context.AddDominatedBlockAndBranch(parse_node);
 
   // Start emitting the `then` block.
-  context.node_block_stack().Pop();
-  context.node_block_stack().Push(then_block_id);
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().Push(then_block_id);
   context.AddCurrentCodeBlockToFunction();
 
   context.node_stack().Push(parse_node, else_block_id);
@@ -38,7 +38,7 @@ auto HandleIfStatementElse(Context& context, Parse::Node parse_node) -> bool {
   auto else_block_id = context.node_stack().Pop<Parse::NodeKind::IfCondition>();
 
   // Switch to emitting the `else` block.
-  context.node_block_stack().Push(else_block_id);
+  context.inst_block_stack().Push(else_block_id);
   context.AddCurrentCodeBlockToFunction();
 
   context.node_stack().Push(parse_node);
@@ -53,9 +53,9 @@ auto HandleIfStatement(Context& context, Parse::Node parse_node) -> bool {
       // block.
       auto else_block_id =
           context.node_stack().Pop<Parse::NodeKind::IfCondition>();
-      context.AddNode(SemIR::Branch{parse_node, else_block_id});
-      context.node_block_stack().Pop();
-      context.node_block_stack().Push(else_block_id);
+      context.AddInst(SemIR::Branch{parse_node, else_block_id});
+      context.inst_block_stack().Pop();
+      context.inst_block_stack().Push(else_block_id);
       break;
     }
 

+ 33 - 33
toolchain/check/handle_index.cpp

@@ -5,7 +5,7 @@
 #include "llvm/ADT/APSInt.h"
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Check {
@@ -20,10 +20,10 @@ auto HandleIndexExpressionStart(Context& /*context*/,
 // the array or tuple size. Returns the index on success, or nullptr on failure.
 static auto ValidateIntegerLiteralBound(Context& context,
                                         Parse::Node parse_node,
-                                        SemIR::Node operand_node,
-                                        SemIR::IntegerLiteral index_node,
+                                        SemIR::Inst operand_inst,
+                                        SemIR::IntegerLiteral index_inst,
                                         int size) -> const llvm::APInt* {
-  const auto& index_val = context.integers().Get(index_node.integer_id);
+  const auto& index_val = context.integers().Get(index_inst.integer_id);
   if (index_val.uge(size)) {
     CARBON_DIAGNOSTIC(IndexOutOfBounds, Error,
                       "Index `{0}` is past the end of `{1}`.", llvm::APSInt,
@@ -31,49 +31,49 @@ static auto ValidateIntegerLiteralBound(Context& context,
     context.emitter().Emit(
         parse_node, IndexOutOfBounds,
         llvm::APSInt(index_val, /*isUnsigned=*/true),
-        context.sem_ir().StringifyType(operand_node.type_id()));
+        context.sem_ir().StringifyType(operand_inst.type_id()));
     return nullptr;
   }
   return &index_val;
 }
 
 auto HandleIndexExpression(Context& context, Parse::Node parse_node) -> bool {
-  auto index_node_id = context.node_stack().PopExpression();
-  auto index_node = context.nodes().Get(index_node_id);
-  auto operand_node_id = context.node_stack().PopExpression();
-  operand_node_id =
-      ConvertToValueOrReferenceExpression(context, operand_node_id);
-  auto operand_node = context.nodes().Get(operand_node_id);
-  auto operand_type_id = operand_node.type_id();
-  auto operand_type_node = context.nodes().Get(
+  auto index_inst_id = context.node_stack().PopExpression();
+  auto index_inst = context.insts().Get(index_inst_id);
+  auto operand_inst_id = context.node_stack().PopExpression();
+  operand_inst_id =
+      ConvertToValueOrReferenceExpression(context, operand_inst_id);
+  auto operand_inst = context.insts().Get(operand_inst_id);
+  auto operand_type_id = operand_inst.type_id();
+  auto operand_type_inst = context.insts().Get(
       context.sem_ir().GetTypeAllowBuiltinTypes(operand_type_id));
 
-  switch (operand_type_node.kind()) {
+  switch (operand_type_inst.kind()) {
     case SemIR::ArrayType::Kind: {
-      auto array_type = operand_type_node.As<SemIR::ArrayType>();
+      auto array_type = operand_type_inst.As<SemIR::ArrayType>();
       // We can check whether integers are in-bounds, although it doesn't affect
       // the IR for an array.
-      if (auto index_literal = index_node.TryAs<SemIR::IntegerLiteral>();
+      if (auto index_literal = index_inst.TryAs<SemIR::IntegerLiteral>();
           index_literal &&
           !ValidateIntegerLiteralBound(
-              context, parse_node, operand_node, *index_literal,
+              context, parse_node, operand_inst, *index_literal,
               context.sem_ir().GetArrayBoundValue(array_type.bound_id))) {
-        index_node_id = SemIR::NodeId::BuiltinError;
+        index_inst_id = SemIR::InstId::BuiltinError;
       }
       auto cast_index_id = ConvertToValueOfType(
-          context, index_node.parse_node(), index_node_id,
+          context, index_inst.parse_node(), index_inst_id,
           context.GetBuiltinType(SemIR::BuiltinKind::IntegerType));
       auto array_cat =
-          SemIR::GetExpressionCategory(context.sem_ir(), operand_node_id);
+          SemIR::GetExpressionCategory(context.sem_ir(), operand_inst_id);
       if (array_cat == SemIR::ExpressionCategory::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_node_id = context.AddNode(SemIR::ValueAsReference{
-            parse_node, operand_type_id, operand_node_id});
+        operand_inst_id = context.AddInst(SemIR::ValueAsReference{
+            parse_node, operand_type_id, operand_inst_id});
       }
-      auto elem_id = context.AddNode(
+      auto elem_id = context.AddInst(
           SemIR::ArrayIndex{parse_node, array_type.element_type_id,
-                            operand_node_id, cast_index_id});
+                            operand_inst_id, cast_index_id});
       if (array_cat != SemIR::ExpressionCategory::DurableReference) {
         // Indexing a durable reference gives a durable reference expression.
         // Indexing anything else gives a value expression.
@@ -86,25 +86,25 @@ auto HandleIndexExpression(Context& context, Parse::Node parse_node) -> bool {
     }
     case SemIR::TupleType::Kind: {
       SemIR::TypeId element_type_id = SemIR::TypeId::Error;
-      if (auto index_literal = index_node.TryAs<SemIR::IntegerLiteral>()) {
+      if (auto index_literal = index_inst.TryAs<SemIR::IntegerLiteral>()) {
         auto type_block = context.type_blocks().Get(
-            operand_type_node.As<SemIR::TupleType>().elements_id);
+            operand_type_inst.As<SemIR::TupleType>().elements_id);
         if (const auto* index_val = ValidateIntegerLiteralBound(
-                context, parse_node, operand_node, *index_literal,
+                context, parse_node, operand_inst, *index_literal,
                 type_block.size())) {
           element_type_id = type_block[index_val->getZExtValue()];
         } else {
-          index_node_id = SemIR::NodeId::BuiltinError;
+          index_inst_id = SemIR::InstId::BuiltinError;
         }
-      } else if (index_node.type_id() != SemIR::TypeId::Error) {
+      } else if (index_inst.type_id() != SemIR::TypeId::Error) {
         CARBON_DIAGNOSTIC(TupleIndexIntegerLiteral, Error,
                           "Tuples indices must be integer literals.");
         context.emitter().Emit(parse_node, TupleIndexIntegerLiteral);
-        index_node_id = SemIR::NodeId::BuiltinError;
+        index_inst_id = SemIR::InstId::BuiltinError;
       }
-      context.AddNodeAndPush(parse_node,
+      context.AddInstAndPush(parse_node,
                              SemIR::TupleIndex{parse_node, element_type_id,
-                                               operand_node_id, index_node_id});
+                                               operand_inst_id, index_inst_id});
       return true;
     }
     default: {
@@ -114,7 +114,7 @@ auto HandleIndexExpression(Context& context, Parse::Node parse_node) -> bool {
         context.emitter().Emit(parse_node, TypeNotIndexable,
                                context.sem_ir().StringifyType(operand_type_id));
       }
-      context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
+      context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
       return true;
     }
   }

+ 5 - 5
toolchain/check/handle_let.cpp

@@ -4,19 +4,19 @@
 
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
 auto HandleLetDeclaration(Context& context, Parse::Node parse_node) -> bool {
   auto value_id = context.node_stack().PopExpression();
-  SemIR::NodeId pattern_id =
+  SemIR::InstId pattern_id =
       context.node_stack().Pop<Parse::NodeKind::PatternBinding>();
   context.node_stack()
       .PopAndDiscardSoloParseNode<Parse::NodeKind::LetIntroducer>();
 
   // Convert the value to match the type of the pattern.
-  auto pattern = context.nodes().Get(pattern_id);
+  auto pattern = context.insts().Get(pattern_id);
   value_id =
       ConvertToValueOfType(context, parse_node, value_id, pattern.type_id());
 
@@ -27,8 +27,8 @@ auto HandleLetDeclaration(Context& context, Parse::Node parse_node) -> bool {
   CARBON_CHECK(!bind_name.value_id.is_valid())
       << "Binding should not already have a value!";
   bind_name.value_id = value_id;
-  context.nodes().Set(pattern_id, bind_name);
-  context.node_block_stack().AddNodeId(pattern_id);
+  context.insts().Set(pattern_id, bind_name);
+  context.inst_block_stack().AddInstId(pattern_id);
 
   // Add the name of the binding to the current scope.
   context.AddNameToLookup(pattern.parse_node(), bind_name.name_id, pattern_id);

+ 9 - 9
toolchain/check/handle_literal.cpp

@@ -11,7 +11,7 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
   switch (auto token_kind = context.tokens().GetKind(token)) {
     case Lex::TokenKind::False:
     case Lex::TokenKind::True: {
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::BoolLiteral{
               parse_node, context.GetBuiltinType(SemIR::BuiltinKind::BoolType),
@@ -20,7 +20,7 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
       break;
     }
     case Lex::TokenKind::IntegerLiteral: {
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::IntegerLiteral{
               parse_node,
@@ -29,7 +29,7 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
       break;
     }
     case Lex::TokenKind::RealLiteral: {
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::RealLiteral{
               parse_node,
@@ -39,7 +39,7 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
     }
     case Lex::TokenKind::StringLiteral: {
       auto id = context.tokens().GetStringLiteral(token);
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::StringLiteral{
               parse_node,
@@ -47,11 +47,11 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
       break;
     }
     case Lex::TokenKind::Type: {
-      context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinTypeType);
+      context.node_stack().Push(parse_node, SemIR::InstId::BuiltinTypeType);
       break;
     }
     case Lex::TokenKind::Bool: {
-      context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinBoolType);
+      context.node_stack().Push(parse_node, SemIR::InstId::BuiltinBoolType);
       break;
     }
     case Lex::TokenKind::IntegerTypeLiteral: {
@@ -59,7 +59,7 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
       if (text != "i32") {
         return context.TODO(parse_node, "Currently only i32 is allowed");
       }
-      context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinIntegerType);
+      context.node_stack().Push(parse_node, SemIR::InstId::BuiltinIntegerType);
       break;
     }
     case Lex::TokenKind::FloatingPointTypeLiteral: {
@@ -68,11 +68,11 @@ auto HandleLiteral(Context& context, Parse::Node parse_node) -> bool {
         return context.TODO(parse_node, "Currently only f64 is allowed");
       }
       context.node_stack().Push(parse_node,
-                                SemIR::NodeId::BuiltinFloatingPointType);
+                                SemIR::InstId::BuiltinFloatingPointType);
       break;
     }
     case Lex::TokenKind::StringTypeLiteral: {
-      context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinStringType);
+      context.node_stack().Push(parse_node, SemIR::InstId::BuiltinStringType);
       break;
     }
     default: {

+ 13 - 13
toolchain/check/handle_loop_statement.cpp

@@ -20,11 +20,11 @@ auto HandleBreakStatementStart(Context& context, Parse::Node parse_node)
                       "`break` can only be used in a loop.");
     context.emitter().Emit(parse_node, BreakOutsideLoop);
   } else {
-    context.AddNode(SemIR::Branch{parse_node, stack.back().break_target});
+    context.AddInst(SemIR::Branch{parse_node, stack.back().break_target});
   }
 
-  context.node_block_stack().Pop();
-  context.node_block_stack().PushUnreachable();
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().PushUnreachable();
   return true;
 }
 
@@ -41,11 +41,11 @@ auto HandleContinueStatementStart(Context& context, Parse::Node parse_node)
                       "`continue` can only be used in a loop.");
     context.emitter().Emit(parse_node, ContinueOutsideLoop);
   } else {
-    context.AddNode(SemIR::Branch{parse_node, stack.back().continue_target});
+    context.AddInst(SemIR::Branch{parse_node, stack.back().continue_target});
   }
 
-  context.node_block_stack().Pop();
-  context.node_block_stack().PushUnreachable();
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().PushUnreachable();
   return true;
 }
 
@@ -71,10 +71,10 @@ auto HandleWhileConditionStart(Context& context, Parse::Node parse_node)
   // if the current block is empty; this ensures that the loop always has a
   // preheader block.
   auto loop_header_id = context.AddDominatedBlockAndBranch(parse_node);
-  context.node_block_stack().Pop();
+  context.inst_block_stack().Pop();
 
   // Start emitting the loop header block.
-  context.node_block_stack().Push(loop_header_id);
+  context.inst_block_stack().Push(loop_header_id);
   context.AddCurrentCodeBlockToFunction();
 
   context.node_stack().Push(parse_node, loop_header_id);
@@ -91,10 +91,10 @@ auto HandleWhileCondition(Context& context, Parse::Node parse_node) -> bool {
   auto loop_body_id =
       context.AddDominatedBlockAndBranchIf(parse_node, cond_value_id);
   auto loop_exit_id = context.AddDominatedBlockAndBranch(parse_node);
-  context.node_block_stack().Pop();
+  context.inst_block_stack().Pop();
 
   // Start emitting the loop body.
-  context.node_block_stack().Push(loop_body_id);
+  context.inst_block_stack().Push(loop_body_id);
   context.AddCurrentCodeBlockToFunction();
   context.break_continue_stack().push_back(
       {.break_target = loop_exit_id, .continue_target = loop_header_id});
@@ -111,11 +111,11 @@ auto HandleWhileStatement(Context& context, Parse::Node parse_node) -> bool {
   context.break_continue_stack().pop_back();
 
   // Add the loop backedge.
-  context.AddNode(SemIR::Branch{parse_node, loop_header_id});
-  context.node_block_stack().Pop();
+  context.AddInst(SemIR::Branch{parse_node, loop_header_id});
+  context.inst_block_stack().Pop();
 
   // Start emitting the loop exit block.
-  context.node_block_stack().Push(loop_exit_id);
+  context.inst_block_stack().Push(loop_exit_id);
   context.AddCurrentCodeBlockToFunction();
   return true;
 }

+ 47 - 46
toolchain/check/handle_name.cpp

@@ -6,15 +6,15 @@
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
 #include "toolchain/lex/token_kind.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
 // Returns the name scope corresponding to base_id, or nullopt if not a scope.
 // On invalid scopes, prints a diagnostic and still returns the scope.
-static auto GetAsNameScope(Context& context, SemIR::NodeId base_id)
+static auto GetAsNameScope(Context& context, SemIR::InstId base_id)
     -> std::optional<SemIR::NameScopeId> {
-  auto base = context.nodes().Get(context.FollowNameReferences(base_id));
+  auto base = context.insts().Get(context.FollowNameReferences(base_id));
   if (auto base_as_namespace = base.TryAs<SemIR::Namespace>()) {
     return base_as_namespace->name_scope_id;
   }
@@ -25,7 +25,7 @@ static auto GetAsNameScope(Context& context, SemIR::NodeId base_id)
                         "Member access into incomplete class `{0}`.",
                         std::string);
       auto builder = context.emitter().Build(
-          context.nodes().Get(base_id).parse_node(),
+          context.insts().Get(base_id).parse_node(),
           QualifiedExpressionInIncompleteClassScope,
           context.sem_ir().StringifyTypeExpression(base_id, true));
       context.NoteIncompleteClass(base_as_class->class_id, builder);
@@ -36,20 +36,20 @@ static auto GetAsNameScope(Context& context, SemIR::NodeId base_id)
   return std::nullopt;
 }
 
-// Given a node produced by a name lookup, get the value to use for that result
-// in an expression.
+// Given an instruction produced by a name lookup, get the value to use for that
+// result in an expression.
 static auto GetExpressionValueForLookupResult(Context& context,
-                                              SemIR::NodeId lookup_result_id)
-    -> SemIR::NodeId {
+                                              SemIR::InstId lookup_result_id)
+    -> SemIR::InstId {
   // If lookup finds a class declaration, the value is its `Self` type.
-  auto lookup_result = context.nodes().Get(lookup_result_id);
+  auto lookup_result = context.insts().Get(lookup_result_id);
   if (auto class_decl = lookup_result.TryAs<SemIR::ClassDeclaration>()) {
     return context.sem_ir().GetTypeAllowBuiltinTypes(
         context.classes().Get(class_decl->class_id).self_type_id);
   }
 
   // Anything else should be a typed value already.
-  CARBON_CHECK(lookup_result.kind().value_kind() == SemIR::NodeValueKind::Typed)
+  CARBON_CHECK(lookup_result.kind().value_kind() == SemIR::InstValueKind::Typed)
       << "Unexpected kind for lookup result";
   return lookup_result_id;
 }
@@ -62,39 +62,39 @@ auto HandleMemberAccessExpression(Context& context, Parse::Node parse_node)
   // If the base is a name scope, such as a class or namespace, perform lookup
   // into that scope.
   if (auto name_scope_id = GetAsNameScope(context, base_id)) {
-    auto node_id = name_scope_id->is_valid()
+    auto inst_id = name_scope_id->is_valid()
                        ? context.LookupName(parse_node, name_id, *name_scope_id,
                                             /*print_diagnostics=*/true)
-                       : SemIR::NodeId::BuiltinError;
-    node_id = GetExpressionValueForLookupResult(context, node_id);
-    auto node = context.nodes().Get(node_id);
-    // TODO: Track that this node was named within `base_id`.
-    context.AddNodeAndPush(
+                       : SemIR::InstId::BuiltinError;
+    inst_id = GetExpressionValueForLookupResult(context, inst_id);
+    auto inst = context.insts().Get(inst_id);
+    // TODO: Track that this instruction was named within `base_id`.
+    context.AddInstAndPush(
         parse_node,
-        SemIR::NameReference{parse_node, node.type_id(), name_id, node_id});
+        SemIR::NameReference{parse_node, inst.type_id(), name_id, inst_id});
     return true;
   }
 
   // If the base isn't a scope, it must have a complete type.
-  auto base_type_id = context.nodes().Get(base_id).type_id();
+  auto base_type_id = context.insts().Get(base_id).type_id();
   if (!context.TryToCompleteType(base_type_id, [&] {
         CARBON_DIAGNOSTIC(IncompleteTypeInMemberAccess, Error,
                           "Member access into object of incomplete type `{0}`.",
                           std::string);
         return context.emitter().Build(
-            context.nodes().Get(base_id).parse_node(),
+            context.insts().Get(base_id).parse_node(),
             IncompleteTypeInMemberAccess,
             context.sem_ir().StringifyType(base_type_id, true));
       })) {
-    context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
+    context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
     return true;
   }
 
   // Materialize a temporary for the base expression if necessary.
   base_id = ConvertToValueOrReferenceExpression(context, base_id);
-  base_type_id = context.nodes().Get(base_id).type_id();
+  base_type_id = context.insts().Get(base_id).type_id();
 
-  auto base_type = context.nodes().Get(
+  auto base_type = context.insts().Get(
       context.sem_ir().GetTypeAllowBuiltinTypes(base_type_id));
 
   switch (base_type.kind()) {
@@ -108,24 +108,24 @@ auto HandleMemberAccessExpression(Context& context, Parse::Node parse_node)
       member_id = GetExpressionValueForLookupResult(context, member_id);
 
       // Perform instance binding if we found an instance member.
-      auto member_type_id = context.nodes().Get(member_id).type_id();
-      auto member_type_node = context.nodes().Get(
+      auto member_type_id = context.insts().Get(member_id).type_id();
+      auto member_type_inst = context.insts().Get(
           context.sem_ir().GetTypeAllowBuiltinTypes(member_type_id));
       if (auto unbound_field_type =
-              member_type_node.TryAs<SemIR::UnboundFieldType>()) {
+              member_type_inst.TryAs<SemIR::UnboundFieldType>()) {
         // TODO: Check that the unbound field type describes a member of this
         // class. Perform a conversion of the base if necessary.
 
         // Find the named field and build a field access expression.
         auto field_id = context.GetConstantValue(member_id);
         CARBON_CHECK(field_id.is_valid())
-            << "Non-constant value " << context.nodes().Get(member_id)
+            << "Non-constant value " << context.insts().Get(member_id)
             << " of unbound field type";
-        auto field = context.nodes().Get(field_id).TryAs<SemIR::Field>();
+        auto field = context.insts().Get(field_id).TryAs<SemIR::Field>();
         CARBON_CHECK(field)
-            << "Unexpected value " << context.nodes().Get(field_id)
+            << "Unexpected value " << context.insts().Get(field_id)
             << " for field name expression";
-        auto access_id = context.AddNode(SemIR::ClassFieldAccess{
+        auto access_id = context.AddInst(SemIR::ClassFieldAccess{
             parse_node, unbound_field_type->field_type_id, base_id,
             field->index});
         if (SemIR::GetExpressionCategory(context.sem_ir(), base_id) ==
@@ -147,19 +147,19 @@ auto HandleMemberAccessExpression(Context& context, Parse::Node parse_node)
         // Find the named function and check whether it's an instance method.
         auto function_name_id = context.GetConstantValue(member_id);
         CARBON_CHECK(function_name_id.is_valid())
-            << "Non-constant value " << context.nodes().Get(member_id)
+            << "Non-constant value " << context.insts().Get(member_id)
             << " of function type";
-        auto function_decl = context.nodes()
+        auto function_decl = context.insts()
                                  .Get(function_name_id)
                                  .TryAs<SemIR::FunctionDeclaration>();
         CARBON_CHECK(function_decl)
-            << "Unexpected value " << context.nodes().Get(function_name_id)
+            << "Unexpected value " << context.insts().Get(function_name_id)
             << " of function type";
         auto& function = context.functions().Get(function_decl->function_id);
         for (auto param_id :
-             context.node_blocks().Get(function.implicit_param_refs_id)) {
-          if (context.nodes().Get(param_id).Is<SemIR::SelfParameter>()) {
-            context.AddNodeAndPush(
+             context.inst_blocks().Get(function.implicit_param_refs_id)) {
+          if (context.insts().Get(param_id).Is<SemIR::SelfParameter>()) {
+            context.AddInstAndPush(
                 parse_node,
                 SemIR::BoundMethod{
                     parse_node,
@@ -172,19 +172,19 @@ auto HandleMemberAccessExpression(Context& context, Parse::Node parse_node)
 
       // For a non-instance member, the result is that member.
       // TODO: Track that this was named within `base_id`.
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::NameReference{parse_node, member_type_id, name_id, member_id});
       return true;
     }
     case SemIR::StructType::Kind: {
-      auto refs = context.node_blocks().Get(
+      auto refs = context.inst_blocks().Get(
           base_type.As<SemIR::StructType>().fields_id);
       // TODO: Do we need to optimize this with a lookup table for O(1)?
       for (auto [i, ref_id] : llvm::enumerate(refs)) {
-        auto field = context.nodes().GetAs<SemIR::StructTypeField>(ref_id);
+        auto field = context.insts().GetAs<SemIR::StructTypeField>(ref_id);
         if (name_id == field.name_id) {
-          context.AddNodeAndPush(
+          context.AddInstAndPush(
               parse_node, SemIR::StructAccess{parse_node, field.field_type_id,
                                               base_id, SemIR::MemberIndex(i)});
           return true;
@@ -214,7 +214,7 @@ auto HandleMemberAccessExpression(Context& context, Parse::Node parse_node)
   }
 
   // Should only be reached on error.
-  context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
+  context.node_stack().Push(parse_node, SemIR::InstId::BuiltinError);
   return true;
 }
 
@@ -237,9 +237,10 @@ auto HandleNameExpression(Context& context, Parse::Node parse_node) -> bool {
   auto value_id =
       context.LookupName(parse_node, name_id, SemIR::NameScopeId::Invalid,
                          /*print_diagnostics=*/true);
+
   value_id = GetExpressionValueForLookupResult(context, value_id);
-  auto value = context.nodes().Get(value_id);
-  context.AddNodeAndPush(
+  auto value = context.insts().Get(value_id);
+  context.AddInstAndPush(
       parse_node,
       SemIR::NameReference{parse_node, value.type_id(), name_id, value_id});
   return true;
@@ -287,8 +288,8 @@ auto HandleSelfTypeNameExpression(Context& context, Parse::Node parse_node)
   auto value_id =
       context.LookupName(parse_node, name_id, SemIR::NameScopeId::Invalid,
                          /*print_diagnostics=*/true);
-  auto value = context.nodes().Get(value_id);
-  context.AddNodeAndPush(
+  auto value = context.insts().Get(value_id);
+  context.AddInstAndPush(
       parse_node,
       SemIR::NameReference{parse_node, value.type_id(), name_id, value_id});
   return true;
@@ -308,8 +309,8 @@ auto HandleSelfValueNameExpression(Context& context, Parse::Node parse_node)
   auto value_id =
       context.LookupName(parse_node, name_id, SemIR::NameScopeId::Invalid,
                          /*print_diagnostics=*/true);
-  auto value = context.nodes().Get(value_id);
-  context.AddNodeAndPush(
+  auto value = context.insts().Get(value_id);
+  context.AddInstAndPush(
       parse_node,
       SemIR::NameReference{parse_node, value.type_id(), name_id, value_id});
   return true;

+ 2 - 2
toolchain/check/handle_namespace.cpp

@@ -3,7 +3,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 #include "toolchain/check/context.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -15,7 +15,7 @@ auto HandleNamespaceStart(Context& context, Parse::Node /*parse_node*/)
 
 auto HandleNamespace(Context& context, Parse::Node parse_node) -> bool {
   auto name_context = context.declaration_name_stack().Pop();
-  auto namespace_id = context.AddNode(SemIR::Namespace{
+  auto namespace_id = context.AddInst(SemIR::Namespace{
       parse_node, context.GetBuiltinType(SemIR::BuiltinKind::NamespaceType),
       context.name_scopes().Add()});
   context.declaration_name_stack().AddNameToLookup(name_context, namespace_id);

+ 29 - 29
toolchain/check/handle_operator.cpp

@@ -18,12 +18,12 @@ auto HandleInfixOperator(Context& context, Parse::Node parse_node) -> bool {
       // TODO: This should search for a compatible interface. For now, it's a
       // very trivial check of validity on the operation.
       lhs_id = ConvertToValueOfType(context, parse_node, lhs_id,
-                                    context.nodes().Get(rhs_id).type_id());
+                                    context.insts().Get(rhs_id).type_id());
       rhs_id = ConvertToValueExpression(context, rhs_id);
 
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node, SemIR::BinaryOperatorAdd{
-                          parse_node, context.nodes().Get(lhs_id).type_id(),
+                          parse_node, context.insts().Get(lhs_id).type_id(),
                           lhs_id, rhs_id});
       return true;
 
@@ -36,16 +36,16 @@ auto HandleInfixOperator(Context& context, Parse::Node parse_node) -> bool {
 
       // When the second operand is evaluated, the result of `and` and `or` is
       // its value.
-      auto resume_block_id = context.node_block_stack().PeekOrAdd(/*depth=*/1);
-      context.AddNode(
+      auto resume_block_id = context.inst_block_stack().PeekOrAdd(/*depth=*/1);
+      context.AddInst(
           SemIR::BranchWithArg{parse_node, resume_block_id, rhs_id});
-      context.node_block_stack().Pop();
+      context.inst_block_stack().Pop();
       context.AddCurrentCodeBlockToFunction();
 
       // Collect the result from either the first or second operand.
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
-          SemIR::BlockArg{parse_node, context.nodes().Get(rhs_id).type_id(),
+          SemIR::BlockArg{parse_node, context.insts().Get(rhs_id).type_id(),
                           resume_block_id});
       return true;
     }
@@ -68,7 +68,7 @@ auto HandleInfixOperator(Context& context, Parse::Node parse_node) -> bool {
       // TODO: Destroy the old value before reinitializing. This will require
       // building the destruction code before we build the RHS subexpression.
       rhs_id = Initialize(context, parse_node, lhs_id, rhs_id);
-      context.AddNode(SemIR::Assign{parse_node, lhs_id, rhs_id});
+      context.AddInst(SemIR::Assign{parse_node, lhs_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
@@ -89,7 +89,7 @@ auto HandlePostfixOperator(Context& context, Parse::Node parse_node) -> bool {
   switch (auto token_kind = context.tokens().GetKind(token)) {
     case Lex::TokenKind::Star: {
       auto inner_type_id = ExpressionAsType(context, parse_node, value_id);
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node, SemIR::PointerType{parse_node, SemIR::TypeId::TypeType,
                                          inner_type_id});
       return true;
@@ -124,12 +124,12 @@ auto HandlePrefixOperator(Context& context, Parse::Node parse_node) -> bool {
           context.emitter().Emit(parse_node, AddressOfNonReference);
           break;
       }
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::AddressOf{
               parse_node,
               context.GetPointerType(parse_node,
-                                     context.nodes().Get(value_id).type_id()),
+                                     context.insts().Get(value_id).type_id()),
               value_id});
       return true;
     }
@@ -138,14 +138,14 @@ auto HandlePrefixOperator(Context& context, Parse::Node parse_node) -> bool {
       // `const (const T)` is probably not what the developer intended.
       // TODO: Detect `const (const T)*` and suggest moving the `*` inside the
       // parentheses.
-      if (context.nodes().Get(value_id).kind() == SemIR::ConstType::Kind) {
+      if (context.insts().Get(value_id).kind() == SemIR::ConstType::Kind) {
         CARBON_DIAGNOSTIC(RepeatedConst, Warning,
                           "`const` applied repeatedly to the same type has no "
                           "additional effect.");
         context.emitter().Emit(parse_node, RepeatedConst);
       }
       auto inner_type_id = ExpressionAsType(context, parse_node, value_id);
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::ConstType{parse_node, SemIR::TypeId::TypeType, inner_type_id});
       return true;
@@ -153,20 +153,20 @@ auto HandlePrefixOperator(Context& context, Parse::Node parse_node) -> bool {
 
     case Lex::TokenKind::Not:
       value_id = ConvertToBoolValue(context, parse_node, value_id);
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::UnaryOperatorNot{
-              parse_node, context.nodes().Get(value_id).type_id(), value_id});
+              parse_node, context.insts().Get(value_id).type_id(), value_id});
       return true;
 
     case Lex::TokenKind::Star: {
       value_id = ConvertToValueExpression(context, value_id);
       auto type_id =
-          context.GetUnqualifiedType(context.nodes().Get(value_id).type_id());
-      auto type_node = context.nodes().Get(
+          context.GetUnqualifiedType(context.insts().Get(value_id).type_id());
+      auto type_inst = context.insts().Get(
           context.sem_ir().GetTypeAllowBuiltinTypes(type_id));
       auto result_type_id = SemIR::TypeId::Error;
-      if (auto pointer_type = type_node.TryAs<SemIR::PointerType>()) {
+      if (auto pointer_type = type_inst.TryAs<SemIR::PointerType>()) {
         result_type_id = pointer_type->pointee_id;
       } else if (type_id != SemIR::TypeId::Error) {
         CARBON_DIAGNOSTIC(
@@ -185,7 +185,7 @@ auto HandlePrefixOperator(Context& context, Parse::Node parse_node) -> bool {
         }
         builder.Emit();
       }
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node, SemIR::Dereference{parse_node, result_type_id, value_id});
       return true;
     }
@@ -200,23 +200,23 @@ auto HandleShortCircuitOperand(Context& context, Parse::Node parse_node)
   // Convert the condition to `bool`.
   auto cond_value_id = context.node_stack().PopExpression();
   cond_value_id = ConvertToBoolValue(context, parse_node, cond_value_id);
-  auto bool_type_id = context.nodes().Get(cond_value_id).type_id();
+  auto bool_type_id = context.insts().Get(cond_value_id).type_id();
 
   // Compute the branch value: the condition for `and`, inverted for `or`.
   auto token = context.parse_tree().node_token(parse_node);
-  SemIR::NodeId branch_value_id = SemIR::NodeId::Invalid;
-  auto short_circuit_result_id = SemIR::NodeId::Invalid;
+  SemIR::InstId branch_value_id = SemIR::InstId::Invalid;
+  auto short_circuit_result_id = SemIR::InstId::Invalid;
   switch (auto token_kind = context.tokens().GetKind(token)) {
     case Lex::TokenKind::And:
       branch_value_id = cond_value_id;
-      short_circuit_result_id = context.AddNode(SemIR::BoolLiteral{
+      short_circuit_result_id = context.AddInst(SemIR::BoolLiteral{
           parse_node, bool_type_id, SemIR::BoolValue::False});
       break;
 
     case Lex::TokenKind::Or:
-      branch_value_id = context.AddNode(
+      branch_value_id = context.AddInst(
           SemIR::UnaryOperatorNot{parse_node, bool_type_id, cond_value_id});
-      short_circuit_result_id = context.AddNode(
+      short_circuit_result_id = context.AddInst(
           SemIR::BoolLiteral{parse_node, bool_type_id, SemIR::BoolValue::True});
       break;
 
@@ -232,9 +232,9 @@ auto HandleShortCircuitOperand(Context& context, Parse::Node parse_node)
 
   // Push the resumption and the right-hand side blocks, and start emitting the
   // right-hand operand.
-  context.node_block_stack().Pop();
-  context.node_block_stack().Push(end_block_id);
-  context.node_block_stack().Push(rhs_block_id);
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().Push(end_block_id);
+  context.inst_block_stack().Push(rhs_block_id);
   context.AddCurrentCodeBlockToFunction();
 
   // Put the condition back on the stack for HandleInfixOperator.

+ 5 - 5
toolchain/check/handle_paren.cpp

@@ -40,16 +40,16 @@ auto HandleTupleLiteral(Context& context, Parse::Node parse_node) -> bool {
   context.node_stack()
       .PopAndDiscardSoloParseNode<
           Parse::NodeKind::ParenExpressionOrTupleLiteralStart>();
-  const auto& node_block = context.node_blocks().Get(refs_id);
+  const auto& inst_block = context.inst_blocks().Get(refs_id);
   llvm::SmallVector<SemIR::TypeId> type_ids;
-  type_ids.reserve(node_block.size());
-  for (auto node : node_block) {
-    type_ids.push_back(context.nodes().Get(node).type_id());
+  type_ids.reserve(inst_block.size());
+  for (auto inst : inst_block) {
+    type_ids.push_back(context.insts().Get(inst).type_id());
   }
   auto type_id = context.CanonicalizeTupleType(parse_node, std::move(type_ids));
 
   auto value_id =
-      context.AddNode(SemIR::TupleLiteral{parse_node, type_id, refs_id});
+      context.AddInst(SemIR::TupleLiteral{parse_node, type_id, refs_id});
   context.node_stack().Push(parse_node, value_id);
   return true;
 }

+ 19 - 19
toolchain/check/handle_pattern_binding.cpp

@@ -4,7 +4,7 @@
 
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -12,9 +12,9 @@ auto HandleAddress(Context& context, Parse::Node parse_node) -> bool {
   auto self_param_id =
       context.node_stack().Peek<Parse::NodeKind::PatternBinding>();
   if (auto self_param =
-          context.nodes().Get(self_param_id).TryAs<SemIR::SelfParameter>()) {
+          context.insts().Get(self_param_id).TryAs<SemIR::SelfParameter>()) {
     self_param->is_addr_self = SemIR::BoolValue::True;
-    context.nodes().Set(self_param_id, *self_param);
+    context.insts().Set(self_param_id, *self_param);
   } else {
     CARBON_DIAGNOSTIC(AddrOnNonSelfParameter, Error,
                       "`addr` can only be applied to a `self` parameter");
@@ -45,7 +45,7 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
           "`self` can only be declared in an implicit parameter list");
       context.emitter().Emit(parse_node, SelfOutsideImplicitParameterList);
     }
-    context.AddNodeAndPush(
+    context.AddInstAndPush(
         parse_node,
         SemIR::SelfParameter{*self_node, cast_type_id,
                              /*is_addr_self=*/SemIR::BoolValue::False});
@@ -58,8 +58,8 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
   auto [name_node, name_id] =
       context.node_stack().PopWithParseNode<Parse::NodeKind::Name>();
 
-  // Allocate a node of the appropriate kind, linked to the name for error
-  // locations.
+  // Allocate an instruction of the appropriate kind, linked to the name for
+  // error locations.
   switch (auto context_parse_node_kind = context.parse_tree().node_kind(
               context.node_stack().PeekParseNode())) {
     case Parse::NodeKind::VariableIntroducer: {
@@ -77,29 +77,29 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
           })) {
         cast_type_id = SemIR::TypeId::Error;
       }
-      SemIR::NodeId value_id = SemIR::NodeId::Invalid;
+      SemIR::InstId value_id = SemIR::InstId::Invalid;
       SemIR::TypeId value_type_id = cast_type_id;
       if (enclosing_class_decl) {
         auto& class_info =
             context.classes().Get(enclosing_class_decl->class_id);
-        auto field_type_node_id = context.AddNode(SemIR::UnboundFieldType{
+        auto field_type_inst_id = context.AddInst(SemIR::UnboundFieldType{
             parse_node, context.GetBuiltinType(SemIR::BuiltinKind::TypeType),
             class_info.self_type_id, cast_type_id});
-        value_type_id = context.CanonicalizeType(field_type_node_id);
-        value_id = context.AddNode(
+        value_type_id = context.CanonicalizeType(field_type_inst_id);
+        value_id = context.AddInst(
             SemIR::Field{parse_node, value_type_id, name_id,
                          SemIR::MemberIndex(context.args_type_info_stack()
                                                 .PeekCurrentBlockContents()
                                                 .size())});
 
         // Add a corresponding field to the object representation of the class.
-        context.args_type_info_stack().AddNode(
+        context.args_type_info_stack().AddInst(
             SemIR::StructTypeField{parse_node, name_id, cast_type_id});
       } else {
-        value_id = context.AddNode(
+        value_id = context.AddInst(
             SemIR::VarStorage{name_node, value_type_id, name_id});
       }
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node,
           SemIR::BindName{name_node, value_type_id, name_id, value_id});
       break;
@@ -109,9 +109,9 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
     case Parse::NodeKind::ParameterListStart:
       // Parameters can have incomplete types in a function declaration, but not
       // in a function definition. We don't know which kind we have here.
-      context.AddNodeAndPush(
+      context.AddInstAndPush(
           parse_node, SemIR::Parameter{name_node, cast_type_id, name_id});
-      // TODO: Create a `BindName` node.
+      // TODO: Create a `BindName` instruction.
       break;
 
     case Parse::NodeKind::LetIntroducer:
@@ -125,14 +125,14 @@ auto HandlePatternBinding(Context& context, Parse::Node parse_node) -> bool {
           })) {
         cast_type_id = SemIR::TypeId::Error;
       }
-      // Create the node, but don't add it to a block until after we've formed
-      // its initializer.
+      // Create the instruction, but don't add it to a block until after we've
+      // formed its initializer.
       // TODO: For general pattern parsing, we'll need to create a block to hold
       // the `let` pattern before we see the initializer.
       context.node_stack().Push(
           parse_node,
-          context.nodes().AddInNoBlock(SemIR::BindName{
-              name_node, cast_type_id, name_id, SemIR::NodeId::Invalid}));
+          context.insts().AddInNoBlock(SemIR::BindName{
+              name_node, cast_type_id, name_id, SemIR::InstId::Invalid}));
       break;
 
     default:

+ 11 - 11
toolchain/check/handle_statement.cpp

@@ -4,17 +4,17 @@
 
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
 // TODO: Find a better home for this. We'll likely need it for more than just
 // expression statements.
-static auto HandleDiscardedExpression(Context& context, SemIR::NodeId expr_id)
+static auto HandleDiscardedExpression(Context& context, SemIR::InstId expr_id)
     -> void {
   // If we discard an initializing expression, convert it to a value or
   // reference so that it has something to initialize.
-  auto expr = context.nodes().Get(expr_id);
+  auto expr = context.insts().Get(expr_id);
   Convert(context, expr.parse_node(), expr_id,
           {.kind = ConversionTarget::Discarded, .type_id = expr.type_id()});
 
@@ -29,9 +29,9 @@ auto HandleExpressionStatement(Context& context, Parse::Node /*parse_node*/)
 
 auto HandleReturnStatement(Context& context, Parse::Node parse_node) -> bool {
   CARBON_CHECK(!context.return_scope_stack().empty());
-  auto fn_node = context.nodes().GetAs<SemIR::FunctionDeclaration>(
+  auto fn_inst = context.insts().GetAs<SemIR::FunctionDeclaration>(
       context.return_scope_stack().back());
-  const auto& callable = context.functions().Get(fn_node.function_id);
+  const auto& callable = context.functions().Get(fn_inst.function_id);
 
   if (context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
       Parse::NodeKind::ReturnStatementStart) {
@@ -48,7 +48,7 @@ auto HandleReturnStatement(Context& context, Parse::Node parse_node) -> bool {
           .Emit();
     }
 
-    context.AddNode(SemIR::Return{parse_node});
+    context.AddInst(SemIR::Return{parse_node});
   } else {
     auto arg = context.node_stack().PopExpression();
     context.node_stack()
@@ -62,7 +62,7 @@ auto HandleReturnStatement(Context& context, Parse::Node parse_node) -> bool {
                         "There was no return type provided.");
       context.emitter()
           .Build(parse_node, ReturnStatementDisallowExpression)
-          .Note(fn_node.parse_node, ReturnStatementImplicitNote)
+          .Note(fn_inst.parse_node, ReturnStatementImplicitNote)
           .Emit();
     } else if (callable.return_slot_id.is_valid()) {
       arg = Initialize(context, parse_node, callable.return_slot_id, arg);
@@ -71,14 +71,14 @@ auto HandleReturnStatement(Context& context, Parse::Node parse_node) -> bool {
                                  callable.return_type_id);
     }
 
-    context.AddNode(SemIR::ReturnExpression{parse_node, arg});
+    context.AddInst(SemIR::ReturnExpression{parse_node, arg});
   }
 
-  // Switch to a new, unreachable, empty node block. This typically won't
+  // Switch to a new, unreachable, empty instruction block. This typically won't
   // contain any semantics IR, but it can do if there are statements following
   // the `return` statement.
-  context.node_block_stack().Pop();
-  context.node_block_stack().PushUnreachable();
+  context.inst_block_stack().Pop();
+  context.inst_block_stack().PushUnreachable();
   return true;
 }
 

+ 8 - 8
toolchain/check/handle_struct.cpp

@@ -28,7 +28,7 @@ auto HandleStructFieldType(Context& context, Parse::Node parse_node) -> bool {
   auto [name_node, name_id] =
       context.node_stack().PopWithParseNode<Parse::NodeKind::Name>();
 
-  context.AddNodeAndPush(
+  context.AddInstAndPush(
       parse_node, SemIR::StructTypeField{name_node, name_id, cast_type_id});
   return true;
 }
@@ -39,16 +39,16 @@ auto HandleStructFieldUnknown(Context& context, Parse::Node parse_node)
 }
 
 auto HandleStructFieldValue(Context& context, Parse::Node parse_node) -> bool {
-  auto [value_parse_node, value_node_id] =
+  auto [value_parse_node, value_inst_id] =
       context.node_stack().PopExpressionWithParseNode();
   StringId name_id = context.node_stack().Pop<Parse::NodeKind::Name>();
 
   // Store the name for the type.
-  context.args_type_info_stack().AddNode(SemIR::StructTypeField{
-      parse_node, name_id, context.nodes().Get(value_node_id).type_id()});
+  context.args_type_info_stack().AddInst(SemIR::StructTypeField{
+      parse_node, name_id, context.insts().Get(value_inst_id).type_id()});
 
   // Push the value back on the stack as an argument.
-  context.node_stack().Push(parse_node, value_node_id);
+  context.node_stack().Push(parse_node, value_inst_id);
   return true;
 }
 
@@ -65,7 +65,7 @@ auto HandleStructLiteral(Context& context, Parse::Node parse_node) -> bool {
   auto type_id = context.CanonicalizeStructType(parse_node, type_block_id);
 
   auto value_id =
-      context.AddNode(SemIR::StructLiteral{parse_node, type_id, refs_id});
+      context.AddInst(SemIR::StructLiteral{parse_node, type_id, refs_id});
   context.node_stack().Push(parse_node, value_id);
   return true;
 }
@@ -94,10 +94,10 @@ auto HandleStructTypeLiteral(Context& context, Parse::Node parse_node) -> bool {
   // This is only used for value literals.
   context.args_type_info_stack().Pop();
 
-  CARBON_CHECK(refs_id != SemIR::NodeBlockId::Empty)
+  CARBON_CHECK(refs_id != SemIR::InstBlockId::Empty)
       << "{} is handled by StructLiteral.";
 
-  context.AddNodeAndPush(
+  context.AddInstAndPush(
       parse_node,
       SemIR::StructType{parse_node, SemIR::TypeId::TypeType, refs_id});
   return true;

+ 6 - 6
toolchain/check/handle_variable.cpp

@@ -4,14 +4,14 @@
 
 #include "toolchain/check/context.h"
 #include "toolchain/check/convert.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
 auto HandleVariableDeclaration(Context& context, Parse::Node parse_node)
     -> bool {
   // Handle the optional initializer.
-  auto init_id = SemIR::NodeId::Invalid;
+  auto init_id = SemIR::InstId::Invalid;
   bool has_init =
       context.parse_tree().node_kind(context.node_stack().PeekParseNode()) !=
       Parse::NodeKind::PatternBinding;
@@ -23,7 +23,7 @@ auto HandleVariableDeclaration(Context& context, Parse::Node parse_node)
 
   // Extract the name binding.
   auto value_id = context.node_stack().Pop<Parse::NodeKind::PatternBinding>();
-  if (auto bind_name = context.nodes().Get(value_id).TryAs<SemIR::BindName>()) {
+  if (auto bind_name = context.insts().Get(value_id).TryAs<SemIR::BindName>()) {
     // Form a corresponding name in the current context, and bind the name to
     // the variable.
     context.declaration_name_stack().AddNameToLookup(
@@ -35,11 +35,11 @@ auto HandleVariableDeclaration(Context& context, Parse::Node parse_node)
 
   // If there was an initializer, assign it to the storage.
   if (has_init) {
-    if (context.nodes().Get(value_id).Is<SemIR::VarStorage>()) {
+    if (context.insts().Get(value_id).Is<SemIR::VarStorage>()) {
       init_id = Initialize(context, parse_node, value_id, init_id);
-      // TODO: Consider using different node kinds for assignment versus
+      // TODO: Consider using different instruction kinds for assignment versus
       // initialization.
-      context.AddNode(SemIR::Assign{parse_node, value_id, init_id});
+      context.AddInst(SemIR::Assign{parse_node, value_id, init_id});
     } else {
       // TODO: In a class scope, we should instead save the initializer
       // somewhere so that we can use it as a default.

+ 12 - 13
toolchain/check/node_block_stack.cpp → toolchain/check/inst_block_stack.cpp

@@ -2,16 +2,15 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include "toolchain/check/node_block_stack.h"
-
 #include "common/vlog.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/check/node_block_stack.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
-auto NodeBlockStack::Push(SemIR::NodeBlockId id) -> void {
+auto InstBlockStack::Push(SemIR::InstBlockId id) -> void {
   CARBON_VLOG() << name_ << " Push " << size_ << "\n";
   CARBON_CHECK(size_ < (1 << 20))
       << "Excessive stack size: likely infinite loop";
@@ -22,44 +21,44 @@ auto NodeBlockStack::Push(SemIR::NodeBlockId id) -> void {
   ++size_;
 }
 
-auto NodeBlockStack::PeekOrAdd(int depth) -> SemIR::NodeBlockId {
+auto InstBlockStack::PeekOrAdd(int depth) -> SemIR::InstBlockId {
   CARBON_CHECK(size() > depth) << "no such block";
   int index = size() - depth - 1;
   auto& slot = stack_[index];
   if (!slot.id.is_valid()) {
-    slot.id = sem_ir_->node_blocks().AddDefaultValue();
+    slot.id = sem_ir_->inst_blocks().AddDefaultValue();
   }
   return slot.id;
 }
 
-auto NodeBlockStack::Pop() -> SemIR::NodeBlockId {
+auto InstBlockStack::Pop() -> SemIR::InstBlockId {
   CARBON_CHECK(!empty()) << "no current block";
   --size_;
   auto& back = stack_[size_];
 
   // Finalize the block.
-  if (!back.content.empty() && back.id != SemIR::NodeBlockId::Unreachable) {
+  if (!back.content.empty() && back.id != SemIR::InstBlockId::Unreachable) {
     if (back.id.is_valid()) {
-      sem_ir_->node_blocks().Set(back.id, back.content);
+      sem_ir_->inst_blocks().Set(back.id, back.content);
     } else {
-      back.id = sem_ir_->node_blocks().Add(back.content);
+      back.id = sem_ir_->inst_blocks().Add(back.content);
     }
   }
 
   CARBON_VLOG() << name_ << " Pop " << size_ << ": " << back.id << "\n";
   if (!back.id.is_valid()) {
-    return SemIR::NodeBlockId::Empty;
+    return SemIR::InstBlockId::Empty;
   }
   return back.id;
 }
 
-auto NodeBlockStack::PopAndDiscard() -> void {
+auto InstBlockStack::PopAndDiscard() -> void {
   CARBON_CHECK(!empty()) << "no current block";
   --size_;
   CARBON_VLOG() << name_ << " PopAndDiscard " << size_ << "\n";
 }
 
-auto NodeBlockStack::PrintForStackDump(llvm::raw_ostream& output) const
+auto InstBlockStack::PrintForStackDump(llvm::raw_ostream& output) const
     -> void {
   output << name_ << ":\n";
   for (const auto& [i, entry] : llvm::enumerate(stack_)) {

+ 38 - 36
toolchain/check/node_block_stack.h

@@ -7,66 +7,68 @@
 
 #include "llvm/ADT/SmallVector.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
-// A stack of node blocks that are currently being constructed in a Context. The
-// contents of the node blocks are stored here until the node block is popped
-// from the stack, at which point they are transferred into the SemIR::File for
-// long-term storage.
+// A stack of instruction blocks that are currently being constructed in a
+// Context. The contents of the instruction blocks are stored here until the
+// instruction block is popped from the stack, at which point they are
+// transferred into the SemIR::File for long-term storage.
 //
 // All pushes and pops will be vlogged.
-class NodeBlockStack {
+class InstBlockStack {
  public:
-  explicit NodeBlockStack(llvm::StringLiteral name, SemIR::File& sem_ir,
+  explicit InstBlockStack(llvm::StringLiteral name, SemIR::File& sem_ir,
                           llvm::raw_ostream* vlog_stream)
       : name_(name), sem_ir_(&sem_ir), vlog_stream_(vlog_stream) {}
 
-  // Pushes an existing node block.
-  auto Push(SemIR::NodeBlockId id) -> void;
+  // Pushes an existing instruction block.
+  auto Push(SemIR::InstBlockId id) -> void;
 
-  // Pushes a new node block. It will be invalid unless PeekOrAdd is called in
-  // order to support lazy allocation.
-  auto Push() -> void { Push(SemIR::NodeBlockId::Invalid); }
+  // Pushes a new instruction block. It will be invalid unless PeekOrAdd is
+  // called in order to support lazy allocation.
+  auto Push() -> void { Push(SemIR::InstBlockId::Invalid); }
 
   // Pushes a new unreachable code block.
-  auto PushUnreachable() -> void { Push(SemIR::NodeBlockId::Unreachable); }
+  auto PushUnreachable() -> void { Push(SemIR::InstBlockId::Unreachable); }
 
-  // Returns the ID of the top node block, allocating one if necessary. If
-  // `depth` is specified, returns the node at `depth` levels from the top of
-  // the stack instead of the top block, where the top block is at depth 0.
-  auto PeekOrAdd(int depth = 0) -> SemIR::NodeBlockId;
+  // Returns the ID of the top instruction block, allocating one if necessary.
+  // If `depth` is specified, returns the instruction at `depth` levels from the
+  // top of the stack instead of the top block, where the top block is at depth
+  // 0.
+  auto PeekOrAdd(int depth = 0) -> SemIR::InstBlockId;
 
-  // Pops the top node block. This will always return a valid node block;
-  // SemIR::NodeBlockId::Empty is returned if one wasn't allocated.
-  auto Pop() -> SemIR::NodeBlockId;
+  // Pops the top instruction block. This will always return a valid instruction
+  // block; SemIR::InstBlockId::Empty is returned if one wasn't allocated.
+  auto Pop() -> SemIR::InstBlockId;
 
-  // Pops the top node block, and discards it if it hasn't had an ID allocated.
+  // Pops the top instruction block, and discards it if it hasn't had an ID
+  // allocated.
   auto PopAndDiscard() -> void;
 
-  // Adds the given node to the block at the top of the stack and returns its
-  // ID.
-  auto AddNode(SemIR::Node node) -> SemIR::NodeId {
-    auto node_id = sem_ir_->nodes().AddInNoBlock(node);
-    AddNodeId(node_id);
-    return node_id;
+  // Adds the given instruction to the block at the top of the stack and returns
+  // its ID.
+  auto AddInst(SemIR::Inst inst) -> SemIR::InstId {
+    auto inst_id = sem_ir_->insts().AddInNoBlock(inst);
+    AddInstId(inst_id);
+    return inst_id;
   }
 
-  // Adds the given node ID to the block at the top of the stack.
-  auto AddNodeId(SemIR::NodeId node_id) -> void {
+  // Adds the given instruction ID to the block at the top of the stack.
+  auto AddInstId(SemIR::InstId inst_id) -> void {
     CARBON_CHECK(!empty()) << "no current block";
-    stack_[size_ - 1].content.push_back(node_id);
+    stack_[size_ - 1].content.push_back(inst_id);
   }
 
   // Returns whether the current block is statically reachable.
   auto is_current_block_reachable() -> bool {
     return size_ != 0 &&
-           stack_[size_ - 1].id != SemIR::NodeBlockId::Unreachable;
+           stack_[size_ - 1].id != SemIR::InstBlockId::Unreachable;
   }
 
-  // Returns a view of the contents of the top node block on the stack.
-  auto PeekCurrentBlockContents() -> llvm::ArrayRef<SemIR::NodeId> {
+  // Returns a view of the contents of the top instruction block on the stack.
+  auto PeekCurrentBlockContents() -> llvm::ArrayRef<SemIR::InstId> {
     CARBON_CHECK(!empty()) << "no current block";
     return stack_[size_ - 1].content;
   }
@@ -84,18 +86,18 @@ class NodeBlockStack {
     // reallocation.
     StackEntry() { content.reserve(32); }
 
-    auto Reset(SemIR::NodeBlockId new_id) {
+    auto Reset(SemIR::InstBlockId new_id) {
       id = new_id;
       content.clear();
     }
 
     // The block ID, if one has been allocated, Invalid if no block has been
     // allocated, or Unreachable if this block is known to be unreachable.
-    SemIR::NodeBlockId id = SemIR::NodeBlockId::Invalid;
+    SemIR::InstBlockId id = SemIR::InstBlockId::Invalid;
 
     // The content of the block. Stored as a vector rather than as a SmallVector
     // to reduce the cost of resizing `stack_` and performing swaps.
-    std::vector<SemIR::NodeId> content;
+    std::vector<SemIR::InstId> content;
   };
 
   // A name for debugging.

+ 3 - 3
toolchain/check/node_stack.cpp

@@ -5,7 +5,7 @@
 #include "toolchain/check/node_stack.h"
 
 #include "llvm/ADT/STLExtras.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
@@ -17,8 +17,8 @@ auto NodeStack::PrintForStackDump(llvm::raw_ostream& output) const -> void {
     if (parse_node_kind == Parse::NodeKind::PatternBinding) {
       output << " -> " << entry.name_id;
     } else {
-      if (entry.node_id.is_valid()) {
-        output << " -> " << entry.node_id;
+      if (entry.inst_id.is_valid()) {
+        output << " -> " << entry.inst_id;
       }
     }
     output << "\n";

+ 40 - 38
toolchain/check/node_stack.h

@@ -11,11 +11,13 @@
 #include "llvm/ADT/SmallVector.h"
 #include "toolchain/parse/node_kind.h"
 #include "toolchain/parse/tree.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Check {
 
-// Wraps the stack of nodes for Context.
+// Wraps the stack of parse nodes for Context. Each parse node can have an
+// associated id of some kind (instruction, instruction block, function, class,
+// ...).
 //
 // All pushes and pops will be vlogged.
 //
@@ -23,7 +25,7 @@ namespace Carbon::Check {
 //
 // - If receiving a pop_parse_kind, verify that the parse_node being popped is
 //   of pop_parse_kind.
-// - Validates presence of node_id based on whether it's a solo
+// - Validates presence of inst_id based on whether it's a solo
 //   parse_node.
 //
 // These should be assumed API constraints unless otherwise mentioned on a
@@ -44,7 +46,7 @@ class NodeStack {
                   << parse_tree_->node_kind(parse_node) << " -> <none>\n";
     CARBON_CHECK(stack_.size() < (1 << 20))
         << "Excessive stack size: likely infinite loop";
-    stack_.push_back(Entry(parse_node, SemIR::NodeId::Invalid));
+    stack_.push_back(Entry(parse_node, SemIR::InstId::Invalid));
   }
 
   // Pushes a parse tree node onto the stack with an ID.
@@ -70,12 +72,12 @@ class NodeStack {
   }
 
   // Pops the top of the stack without any verification.
-  auto PopAndIgnore() -> void { PopEntry<SemIR::NodeId>(); }
+  auto PopAndIgnore() -> void { PopEntry<SemIR::InstId>(); }
 
   // Pops the top of the stack and returns the parse_node.
   template <Parse::NodeKind::RawEnumType RequiredParseKind>
   auto PopForSoloParseNode() -> Parse::Node {
-    Entry back = PopEntry<SemIR::NodeId>();
+    Entry back = PopEntry<SemIR::InstId>();
     RequireIdKind(Parse::NodeKind::Create(RequiredParseKind),
                   IdKind::SoloParseNode);
     RequireParseKind<RequiredParseKind>(back.parse_node);
@@ -100,8 +102,8 @@ class NodeStack {
 
   // Pops an expression from the top of the stack and returns the parse_node and
   // the ID.
-  auto PopExpressionWithParseNode() -> std::pair<Parse::Node, SemIR::NodeId> {
-    return PopWithParseNode<SemIR::NodeId>();
+  auto PopExpressionWithParseNode() -> std::pair<Parse::Node, SemIR::InstId> {
+    return PopWithParseNode<SemIR::InstId>();
   }
 
   // Pops the top of the stack and returns the parse_node and the ID.
@@ -109,13 +111,13 @@ class NodeStack {
   auto PopWithParseNode() -> auto {
     constexpr IdKind RequiredIdKind =
         ParseNodeKindToIdKind(Parse::NodeKind::Create(RequiredParseKind));
-    if constexpr (RequiredIdKind == IdKind::NodeId) {
-      auto back = PopWithParseNode<SemIR::NodeId>();
+    if constexpr (RequiredIdKind == IdKind::InstId) {
+      auto back = PopWithParseNode<SemIR::InstId>();
       RequireParseKind<RequiredParseKind>(back.first);
       return back;
     }
-    if constexpr (RequiredIdKind == IdKind::NodeBlockId) {
-      auto back = PopWithParseNode<SemIR::NodeBlockId>();
+    if constexpr (RequiredIdKind == IdKind::InstBlockId) {
+      auto back = PopWithParseNode<SemIR::InstBlockId>();
       RequireParseKind<RequiredParseKind>(back.first);
       return back;
     }
@@ -145,8 +147,8 @@ class NodeStack {
   }
 
   // Pops an expression from the top of the stack and returns the ID.
-  // Expressions map multiple Parse::NodeKinds to SemIR::NodeId always.
-  auto PopExpression() -> SemIR::NodeId {
+  // Expressions map multiple Parse::NodeKinds to SemIR::InstId always.
+  auto PopExpression() -> SemIR::InstId {
     return PopExpressionWithParseNode().second;
   }
 
@@ -166,7 +168,7 @@ class NodeStack {
     return std::nullopt;
   }
 
-  // Peeks at the parse_node of the given depth in the stack, or by default the
+  // Peeks at the parse node of the given depth in the stack, or by default the
   // top node.
   auto PeekParseNode() const -> Parse::Node { return stack_.back().parse_node; }
 
@@ -178,11 +180,11 @@ class NodeStack {
     RequireParseKind<RequiredParseKind>(back.parse_node);
     constexpr IdKind RequiredIdKind =
         ParseNodeKindToIdKind(Parse::NodeKind::Create(RequiredParseKind));
-    if constexpr (RequiredIdKind == IdKind::NodeId) {
-      return back.id<SemIR::NodeId>();
+    if constexpr (RequiredIdKind == IdKind::InstId) {
+      return back.id<SemIR::InstId>();
     }
-    if constexpr (RequiredIdKind == IdKind::NodeBlockId) {
-      return back.id<SemIR::NodeBlockId>();
+    if constexpr (RequiredIdKind == IdKind::InstBlockId) {
+      return back.id<SemIR::InstBlockId>();
     }
     if constexpr (RequiredIdKind == IdKind::FunctionId) {
       return back.id<SemIR::FunctionId>();
@@ -210,8 +212,8 @@ class NodeStack {
  private:
   // Possible associated ID types.
   enum class IdKind : int8_t {
-    NodeId,
-    NodeBlockId,
+    InstId,
+    InstBlockId,
     FunctionId,
     ClassId,
     StringId,
@@ -224,10 +226,10 @@ class NodeStack {
 
   // An entry in stack_.
   struct Entry {
-    explicit Entry(Parse::Node parse_node, SemIR::NodeId node_id)
-        : parse_node(parse_node), node_id(node_id) {}
-    explicit Entry(Parse::Node parse_node, SemIR::NodeBlockId node_block_id)
-        : parse_node(parse_node), node_block_id(node_block_id) {}
+    explicit Entry(Parse::Node parse_node, SemIR::InstId inst_id)
+        : parse_node(parse_node), inst_id(inst_id) {}
+    explicit Entry(Parse::Node parse_node, SemIR::InstBlockId inst_block_id)
+        : parse_node(parse_node), inst_block_id(inst_block_id) {}
     explicit Entry(Parse::Node parse_node, SemIR::FunctionId function_id)
         : parse_node(parse_node), function_id(function_id) {}
     explicit Entry(Parse::Node parse_node, SemIR::ClassId class_id)
@@ -240,11 +242,11 @@ class NodeStack {
     // Returns the appropriate ID basaed on type.
     template <typename T>
     auto id() -> T& {
-      if constexpr (std::is_same<T, SemIR::NodeId>()) {
-        return node_id;
+      if constexpr (std::is_same<T, SemIR::InstId>()) {
+        return inst_id;
       }
-      if constexpr (std::is_same<T, SemIR::NodeBlockId>()) {
-        return node_block_id;
+      if constexpr (std::is_same<T, SemIR::InstBlockId>()) {
+        return inst_block_id;
       }
       if constexpr (std::is_same<T, SemIR::FunctionId>()) {
         return function_id;
@@ -260,7 +262,7 @@ class NodeStack {
       }
     }
 
-    // The node associated with the stack entry.
+    // The parse node associated with the stack entry.
     Parse::Node parse_node;
 
     // The entries will evaluate as invalid if and only if they're a solo
@@ -269,8 +271,8 @@ class NodeStack {
     // A discriminator isn't needed because the caller can determine which field
     // is used based on the Parse::NodeKind.
     union {
-      SemIR::NodeId node_id;
-      SemIR::NodeBlockId node_block_id;
+      SemIR::InstId inst_id;
+      SemIR::InstBlockId inst_block_id;
       SemIR::FunctionId function_id;
       SemIR::ClassId class_id;
       StringId name_id;
@@ -305,14 +307,14 @@ class NodeStack {
       case Parse::NodeKind::StructFieldType:
       case Parse::NodeKind::StructTypeLiteral:
       case Parse::NodeKind::TupleLiteral:
-        return IdKind::NodeId;
+        return IdKind::InstId;
       case Parse::NodeKind::IfCondition:
       case Parse::NodeKind::IfExpressionIf:
       case Parse::NodeKind::ImplicitParameterList:
       case Parse::NodeKind::ParameterList:
       case Parse::NodeKind::WhileCondition:
       case Parse::NodeKind::WhileConditionStart:
-        return IdKind::NodeBlockId;
+        return IdKind::InstBlockId;
       case Parse::NodeKind::FunctionDefinitionStart:
         return IdKind::FunctionId;
       case Parse::NodeKind::ClassDefinitionStart:
@@ -344,11 +346,11 @@ class NodeStack {
   // ParseNodeKindToIdKind.
   template <typename IdT>
   static constexpr auto IdTypeToIdKind() -> IdKind {
-    if constexpr (std::is_same_v<IdT, SemIR::NodeId>) {
-      return IdKind::NodeId;
+    if constexpr (std::is_same_v<IdT, SemIR::InstId>) {
+      return IdKind::InstId;
     }
-    if constexpr (std::is_same_v<IdT, SemIR::NodeBlockId>) {
-      return IdKind::NodeBlockId;
+    if constexpr (std::is_same_v<IdT, SemIR::InstBlockId>) {
+      return IdKind::InstBlockId;
     }
     if constexpr (std::is_same_v<IdT, SemIR::FunctionId>) {
       return IdKind::FunctionId;

+ 31 - 31
toolchain/check/pending_block.h

@@ -19,18 +19,18 @@ class PendingBlock {
   PendingBlock(const PendingBlock&) = delete;
   PendingBlock& operator=(const PendingBlock&) = delete;
 
-  // A scope in which we will tentatively add nodes to a pending block. If we
-  // leave the scope without inserting or merging the block, nodes added after
-  // this point will be removed again.
-  class DiscardUnusedNodesScope {
+  // A scope in which we will tentatively add instructions to a pending block.
+  // If we leave the scope without inserting or merging the block, instructions
+  // added after this point will be removed again.
+  class DiscardUnusedInstsScope {
    public:
     // If `block` is not null, enters the scope. If `block` is null, this object
     // has no effect.
-    DiscardUnusedNodesScope(PendingBlock* block)
-        : block_(block), size_(block ? block->nodes_.size() : 0) {}
-    ~DiscardUnusedNodesScope() {
-      if (block_ && block_->nodes_.size() > size_) {
-        block_->nodes_.truncate(size_);
+    DiscardUnusedInstsScope(PendingBlock* block)
+        : block_(block), size_(block ? block->insts_.size() : 0) {}
+    ~DiscardUnusedInstsScope() {
+      if (block_ && block_->insts_.size() > size_) {
+        block_->insts_.truncate(size_);
       }
     }
 
@@ -39,52 +39,52 @@ class PendingBlock {
     size_t size_;
   };
 
-  auto AddNode(SemIR::Node node) -> SemIR::NodeId {
-    auto node_id = context_.nodes().AddInNoBlock(node);
-    nodes_.push_back(node_id);
-    return node_id;
+  auto AddInst(SemIR::Inst inst) -> SemIR::InstId {
+    auto inst_id = context_.insts().AddInNoBlock(inst);
+    insts_.push_back(inst_id);
+    return inst_id;
   }
 
   // Insert the pending block of code at the current position.
   auto InsertHere() -> void {
-    for (auto id : nodes_) {
-      context_.node_block_stack().AddNodeId(id);
+    for (auto id : insts_) {
+      context_.inst_block_stack().AddInstId(id);
     }
-    nodes_.clear();
+    insts_.clear();
   }
 
-  // Replace the node at target_id with the nodes in this block. The new value
-  // for target_id should be value_id.
-  auto MergeReplacing(SemIR::NodeId target_id, SemIR::NodeId value_id) -> void {
-    auto value = context_.nodes().Get(value_id);
+  // 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().Get(value_id);
 
     // There are three cases here:
 
-    if (nodes_.empty()) {
+    if (insts_.empty()) {
       // 1) The block is empty. Replace `target_id` with an empty splice
       // pointing at `value_id`.
-      context_.nodes().Set(
+      context_.insts().Set(
           target_id, SemIR::SpliceBlock{value.parse_node(), value.type_id(),
-                                        SemIR::NodeBlockId::Empty, value_id});
-    } else if (nodes_.size() == 1 && nodes_[0] == value_id) {
-      // 2) The block is {value_id}. Replace `target_id` with the node referred
-      // to by `value_id`. This is intended to be the common case.
-      context_.nodes().Set(target_id, value);
+                                        SemIR::InstBlockId::Empty, value_id});
+    } 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_.insts().Set(target_id, value);
     } else {
       // 3) Anything else: splice it into the IR, replacing `target_id`.
-      context_.nodes().Set(
+      context_.insts().Set(
           target_id,
           SemIR::SpliceBlock{value.parse_node(), value.type_id(),
-                             context_.node_blocks().Add(nodes_), value_id});
+                             context_.inst_blocks().Add(insts_), value_id});
     }
 
     // Prepare to stash more pending instructions.
-    nodes_.clear();
+    insts_.clear();
   }
 
  private:
   Context& context_;
-  llvm::SmallVector<SemIR::NodeId> nodes_;
+  llvm::SmallVector<SemIR::InstId> insts_;
 };
 
 }  // namespace Carbon::Check

+ 11 - 11
toolchain/check/testdata/basics/builtin_nodes.carbon

@@ -14,16 +14,16 @@
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:           {}
 // CHECK:STDOUT:   type_blocks:     {}
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     nodeTypeType:    {kind: CrossReference, arg0: ir0, arg1: nodeTypeType, type: typeTypeType}
-// CHECK:STDOUT:     nodeError:       {kind: CrossReference, arg0: ir0, arg1: nodeError, type: typeError}
-// CHECK:STDOUT:     nodeBoolType:    {kind: CrossReference, arg0: ir0, arg1: nodeBoolType, type: typeTypeType}
-// CHECK:STDOUT:     nodeIntegerType: {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType}
-// CHECK:STDOUT:     nodeFloatingPointType: {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType}
-// CHECK:STDOUT:     nodeStringType:  {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType}
-// CHECK:STDOUT:     nodeFunctionType: {kind: CrossReference, arg0: ir0, arg1: nodeFunctionType, type: typeTypeType}
-// CHECK:STDOUT:     nodeBoundMethodType: {kind: CrossReference, arg0: ir0, arg1: nodeBoundMethodType, type: typeTypeType}
-// CHECK:STDOUT:     nodeNamespaceType: {kind: CrossReference, arg0: ir0, arg1: nodeNamespaceType, type: typeTypeType}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     instTypeType:    {kind: CrossReference, arg0: ir0, arg1: instTypeType, type: typeTypeType}
+// CHECK:STDOUT:     instError:       {kind: CrossReference, arg0: ir0, arg1: instError, type: typeError}
+// CHECK:STDOUT:     instBoolType:    {kind: CrossReference, arg0: ir0, arg1: instBoolType, type: typeTypeType}
+// CHECK:STDOUT:     instIntegerType: {kind: CrossReference, arg0: ir0, arg1: instIntegerType, type: typeTypeType}
+// CHECK:STDOUT:     instFloatingPointType: {kind: CrossReference, arg0: ir0, arg1: instFloatingPointType, type: typeTypeType}
+// CHECK:STDOUT:     instStringType:  {kind: CrossReference, arg0: ir0, arg1: instStringType, type: typeTypeType}
+// CHECK:STDOUT:     instFunctionType: {kind: CrossReference, arg0: ir0, arg1: instFunctionType, type: typeTypeType}
+// CHECK:STDOUT:     instBoundMethodType: {kind: CrossReference, arg0: ir0, arg1: instBoundMethodType, type: typeTypeType}
+// CHECK:STDOUT:     instNamespaceType: {kind: CrossReference, arg0: ir0, arg1: instNamespaceType, type: typeTypeType}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT: ...

+ 14 - 14
toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon

@@ -22,17 +22,17 @@ fn B() {}
 // CHECK:STDOUT:     function0:       {name: str0, param_refs: block0, body: [block1]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeFunctionType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type0:           {inst: instFunctionType, value_rep: {kind: copy, type: type0}}
 // CHECK:STDOUT:   type_blocks:     {}
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: Return}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: Return}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+1
+// CHECK:STDOUT:       0:               inst+1
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT: ...
 // CHECK:STDOUT:
 // CHECK:STDOUT: file "a.carbon" {
@@ -51,17 +51,17 @@ fn B() {}
 // CHECK:STDOUT:     function0:       {name: str0, param_refs: block0, body: [block1]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeFunctionType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type0:           {inst: instFunctionType, value_rep: {kind: copy, type: type0}}
 // CHECK:STDOUT:   type_blocks:     {}
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: Return}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: Return}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+1
+// CHECK:STDOUT:       0:               inst+1
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT: ...
 // CHECK:STDOUT:
 // CHECK:STDOUT: file "b.carbon" {

+ 14 - 14
toolchain/check/testdata/basics/multifile_raw_ir.carbon

@@ -22,17 +22,17 @@ fn B() {}
 // CHECK:STDOUT:     function0:       {name: str0, param_refs: block0, body: [block1]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeFunctionType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type0:           {inst: instFunctionType, value_rep: {kind: copy, type: type0}}
 // CHECK:STDOUT:   type_blocks:     {}
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: Return}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: Return}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+1
+// CHECK:STDOUT:       0:               inst+1
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT: ...
 // CHECK:STDOUT: ---
 // CHECK:STDOUT: filename:        b.carbon
@@ -42,15 +42,15 @@ fn B() {}
 // CHECK:STDOUT:     function0:       {name: str0, param_refs: block0, body: [block1]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeFunctionType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type0:           {inst: instFunctionType, value_rep: {kind: copy, type: type0}}
 // CHECK:STDOUT:   type_blocks:     {}
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: Return}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: FunctionDeclaration, arg0: function0, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: Return}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+1
+// CHECK:STDOUT:       0:               inst+1
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT: ...

+ 52 - 52
toolchain/check/testdata/basics/raw_and_textual_ir.carbon

@@ -17,15 +17,15 @@ fn Foo(n: i32) -> (i32, f64) {
 // CHECK:STDOUT: sem_ir:
 // CHECK:STDOUT:   cross_reference_irs_size: 1
 // CHECK:STDOUT:   functions:
-// CHECK:STDOUT:     function0:       {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]}
+// CHECK:STDOUT:     function0:       {name: str0, param_refs: block1, return_type: type3, return_slot: inst+4, body: [block4]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeIntegerType, value_rep: {kind: copy, type: type0}}
-// CHECK:STDOUT:     type1:           {node: node+1, value_rep: {kind: unknown, type: type<invalid>}}
-// CHECK:STDOUT:     type2:           {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}}
-// CHECK:STDOUT:     type3:           {node: node+3, value_rep: {kind: pointer, type: type4}}
-// CHECK:STDOUT:     type4:           {node: node+5, value_rep: {kind: copy, type: type4}}
-// CHECK:STDOUT:     type5:           {node: nodeFunctionType, value_rep: {kind: copy, type: type5}}
+// CHECK:STDOUT:     type0:           {inst: instIntegerType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type1:           {inst: inst+1, value_rep: {kind: unknown, type: type<invalid>}}
+// CHECK:STDOUT:     type2:           {inst: instFloatingPointType, value_rep: {kind: copy, type: type2}}
+// CHECK:STDOUT:     type3:           {inst: inst+3, value_rep: {kind: pointer, type: type4}}
+// CHECK:STDOUT:     type4:           {inst: inst+5, value_rep: {kind: copy, type: type4}}
+// CHECK:STDOUT:     type5:           {inst: instFunctionType, value_rep: {kind: copy, type: type5}}
 // CHECK:STDOUT:   type_blocks:
 // CHECK:STDOUT:     typeBlock0:
 // CHECK:STDOUT:       0:               typeTypeType
@@ -33,59 +33,59 @@ fn Foo(n: i32) -> (i32, f64) {
 // CHECK:STDOUT:     typeBlock1:
 // CHECK:STDOUT:       0:               type0
 // CHECK:STDOUT:       1:               type2
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: Parameter, arg0: str1, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: TupleType, arg0: typeBlock0, type: typeTypeType}
-// CHECK:STDOUT:     node+2:          {kind: TupleLiteral, arg0: block2, type: type1}
-// CHECK:STDOUT:     node+3:          {kind: TupleType, arg0: typeBlock1, type: typeTypeType}
-// CHECK:STDOUT:     node+4:          {kind: VarStorage, arg0: str2, type: type3}
-// CHECK:STDOUT:     node+5:          {kind: PointerType, arg0: type3, type: typeTypeType}
-// CHECK:STDOUT:     node+6:          {kind: FunctionDeclaration, arg0: function0, type: type5}
-// CHECK:STDOUT:     node+7:          {kind: NameReference, arg0: str1, arg1: node+0, type: type0}
-// CHECK:STDOUT:     node+8:          {kind: IntegerLiteral, arg0: int3, type: type0}
-// CHECK:STDOUT:     node+9:          {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0}
-// CHECK:STDOUT:     node+10:         {kind: RealLiteral, arg0: real0, type: type2}
-// CHECK:STDOUT:     node+11:         {kind: TupleLiteral, arg0: block5, type: type3}
-// CHECK:STDOUT:     node+12:         {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0}
-// CHECK:STDOUT:     node+13:         {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0}
-// CHECK:STDOUT:     node+14:         {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2}
-// CHECK:STDOUT:     node+15:         {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2}
-// CHECK:STDOUT:     node+16:         {kind: TupleInit, arg0: node+11, arg1: block6, type: type3}
-// CHECK:STDOUT:     node+17:         {kind: ReturnExpression, arg0: node+16}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: Parameter, arg0: str1, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: TupleType, arg0: typeBlock0, type: typeTypeType}
+// CHECK:STDOUT:     inst+2:          {kind: TupleLiteral, arg0: block2, type: type1}
+// CHECK:STDOUT:     inst+3:          {kind: TupleType, arg0: typeBlock1, type: typeTypeType}
+// CHECK:STDOUT:     inst+4:          {kind: VarStorage, arg0: str2, type: type3}
+// CHECK:STDOUT:     inst+5:          {kind: PointerType, arg0: type3, type: typeTypeType}
+// CHECK:STDOUT:     inst+6:          {kind: FunctionDeclaration, arg0: function0, type: type5}
+// CHECK:STDOUT:     inst+7:          {kind: NameReference, arg0: str1, arg1: inst+0, type: type0}
+// CHECK:STDOUT:     inst+8:          {kind: IntegerLiteral, arg0: int3, type: type0}
+// CHECK:STDOUT:     inst+9:          {kind: BinaryOperatorAdd, arg0: inst+7, arg1: inst+8, type: type0}
+// CHECK:STDOUT:     inst+10:         {kind: RealLiteral, arg0: real0, type: type2}
+// CHECK:STDOUT:     inst+11:         {kind: TupleLiteral, arg0: block5, type: type3}
+// CHECK:STDOUT:     inst+12:         {kind: TupleAccess, arg0: inst+4, arg1: member0, type: type0}
+// CHECK:STDOUT:     inst+13:         {kind: InitializeFrom, arg0: inst+9, arg1: inst+12, type: type0}
+// CHECK:STDOUT:     inst+14:         {kind: TupleAccess, arg0: inst+4, arg1: member1, type: type2}
+// CHECK:STDOUT:     inst+15:         {kind: InitializeFrom, arg0: inst+10, arg1: inst+14, type: type2}
+// CHECK:STDOUT:     inst+16:         {kind: TupleInit, arg0: inst+11, arg1: block6, type: type3}
+// CHECK:STDOUT:     inst+17:         {kind: ReturnExpression, arg0: inst+16}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               nodeIntegerType
-// CHECK:STDOUT:       1:               nodeFloatingPointType
+// CHECK:STDOUT:       0:               instIntegerType
+// CHECK:STDOUT:       1:               instFloatingPointType
 // CHECK:STDOUT:     block3:
-// CHECK:STDOUT:       0:               node+0
-// CHECK:STDOUT:       1:               node+1
-// CHECK:STDOUT:       2:               node+2
-// CHECK:STDOUT:       3:               node+3
-// CHECK:STDOUT:       4:               node+4
+// CHECK:STDOUT:       0:               inst+0
+// CHECK:STDOUT:       1:               inst+1
+// CHECK:STDOUT:       2:               inst+2
+// CHECK:STDOUT:       3:               inst+3
+// CHECK:STDOUT:       4:               inst+4
 // CHECK:STDOUT:     block4:
-// CHECK:STDOUT:       0:               node+7
-// CHECK:STDOUT:       1:               node+8
-// CHECK:STDOUT:       2:               node+9
-// CHECK:STDOUT:       3:               node+10
-// CHECK:STDOUT:       4:               node+11
-// CHECK:STDOUT:       5:               node+12
-// CHECK:STDOUT:       6:               node+13
-// CHECK:STDOUT:       7:               node+14
-// CHECK:STDOUT:       8:               node+15
-// CHECK:STDOUT:       9:               node+16
-// CHECK:STDOUT:       10:              node+17
+// CHECK:STDOUT:       0:               inst+7
+// CHECK:STDOUT:       1:               inst+8
+// CHECK:STDOUT:       2:               inst+9
+// CHECK:STDOUT:       3:               inst+10
+// CHECK:STDOUT:       4:               inst+11
+// CHECK:STDOUT:       5:               inst+12
+// CHECK:STDOUT:       6:               inst+13
+// CHECK:STDOUT:       7:               inst+14
+// CHECK:STDOUT:       8:               inst+15
+// CHECK:STDOUT:       9:               inst+16
+// CHECK:STDOUT:       10:              inst+17
 // CHECK:STDOUT:     block5:
-// CHECK:STDOUT:       0:               node+9
-// CHECK:STDOUT:       1:               node+10
+// CHECK:STDOUT:       0:               inst+9
+// CHECK:STDOUT:       1:               inst+10
 // CHECK:STDOUT:     block6:
-// CHECK:STDOUT:       0:               node+13
-// CHECK:STDOUT:       1:               node+15
+// CHECK:STDOUT:       0:               inst+13
+// CHECK:STDOUT:       1:               inst+15
 // CHECK:STDOUT:     block7:
-// CHECK:STDOUT:       0:               node+5
-// CHECK:STDOUT:       1:               node+6
+// CHECK:STDOUT:       0:               inst+5
+// CHECK:STDOUT:       1:               inst+6
 // CHECK:STDOUT: ...
 // CHECK:STDOUT:
 // CHECK:STDOUT: file "raw_and_textual_ir.carbon" {

+ 52 - 52
toolchain/check/testdata/basics/raw_ir.carbon

@@ -17,15 +17,15 @@ fn Foo(n: i32) -> (i32, f64) {
 // CHECK:STDOUT: sem_ir:
 // CHECK:STDOUT:   cross_reference_irs_size: 1
 // CHECK:STDOUT:   functions:
-// CHECK:STDOUT:     function0:       {name: str0, param_refs: block1, return_type: type3, return_slot: node+4, body: [block4]}
+// CHECK:STDOUT:     function0:       {name: str0, param_refs: block1, return_type: type3, return_slot: inst+4, body: [block4]}
 // CHECK:STDOUT:   classes:         {}
 // CHECK:STDOUT:   types:
-// CHECK:STDOUT:     type0:           {node: nodeIntegerType, value_rep: {kind: copy, type: type0}}
-// CHECK:STDOUT:     type1:           {node: node+1, value_rep: {kind: unknown, type: type<invalid>}}
-// CHECK:STDOUT:     type2:           {node: nodeFloatingPointType, value_rep: {kind: copy, type: type2}}
-// CHECK:STDOUT:     type3:           {node: node+3, value_rep: {kind: pointer, type: type4}}
-// CHECK:STDOUT:     type4:           {node: node+5, value_rep: {kind: copy, type: type4}}
-// CHECK:STDOUT:     type5:           {node: nodeFunctionType, value_rep: {kind: copy, type: type5}}
+// CHECK:STDOUT:     type0:           {inst: instIntegerType, value_rep: {kind: copy, type: type0}}
+// CHECK:STDOUT:     type1:           {inst: inst+1, value_rep: {kind: unknown, type: type<invalid>}}
+// CHECK:STDOUT:     type2:           {inst: instFloatingPointType, value_rep: {kind: copy, type: type2}}
+// CHECK:STDOUT:     type3:           {inst: inst+3, value_rep: {kind: pointer, type: type4}}
+// CHECK:STDOUT:     type4:           {inst: inst+5, value_rep: {kind: copy, type: type4}}
+// CHECK:STDOUT:     type5:           {inst: instFunctionType, value_rep: {kind: copy, type: type5}}
 // CHECK:STDOUT:   type_blocks:
 // CHECK:STDOUT:     typeBlock0:
 // CHECK:STDOUT:       0:               typeTypeType
@@ -33,57 +33,57 @@ fn Foo(n: i32) -> (i32, f64) {
 // CHECK:STDOUT:     typeBlock1:
 // CHECK:STDOUT:       0:               type0
 // CHECK:STDOUT:       1:               type2
-// CHECK:STDOUT:   nodes:
-// CHECK:STDOUT:     node+0:          {kind: Parameter, arg0: str1, type: type0}
-// CHECK:STDOUT:     node+1:          {kind: TupleType, arg0: typeBlock0, type: typeTypeType}
-// CHECK:STDOUT:     node+2:          {kind: TupleLiteral, arg0: block2, type: type1}
-// CHECK:STDOUT:     node+3:          {kind: TupleType, arg0: typeBlock1, type: typeTypeType}
-// CHECK:STDOUT:     node+4:          {kind: VarStorage, arg0: str2, type: type3}
-// CHECK:STDOUT:     node+5:          {kind: PointerType, arg0: type3, type: typeTypeType}
-// CHECK:STDOUT:     node+6:          {kind: FunctionDeclaration, arg0: function0, type: type5}
-// CHECK:STDOUT:     node+7:          {kind: NameReference, arg0: str1, arg1: node+0, type: type0}
-// CHECK:STDOUT:     node+8:          {kind: IntegerLiteral, arg0: int3, type: type0}
-// CHECK:STDOUT:     node+9:          {kind: BinaryOperatorAdd, arg0: node+7, arg1: node+8, type: type0}
-// CHECK:STDOUT:     node+10:         {kind: RealLiteral, arg0: real0, type: type2}
-// CHECK:STDOUT:     node+11:         {kind: TupleLiteral, arg0: block5, type: type3}
-// CHECK:STDOUT:     node+12:         {kind: TupleAccess, arg0: node+4, arg1: member0, type: type0}
-// CHECK:STDOUT:     node+13:         {kind: InitializeFrom, arg0: node+9, arg1: node+12, type: type0}
-// CHECK:STDOUT:     node+14:         {kind: TupleAccess, arg0: node+4, arg1: member1, type: type2}
-// CHECK:STDOUT:     node+15:         {kind: InitializeFrom, arg0: node+10, arg1: node+14, type: type2}
-// CHECK:STDOUT:     node+16:         {kind: TupleInit, arg0: node+11, arg1: block6, type: type3}
-// CHECK:STDOUT:     node+17:         {kind: ReturnExpression, arg0: node+16}
-// CHECK:STDOUT:   node_blocks:
+// CHECK:STDOUT:   insts:
+// CHECK:STDOUT:     inst+0:          {kind: Parameter, arg0: str1, type: type0}
+// CHECK:STDOUT:     inst+1:          {kind: TupleType, arg0: typeBlock0, type: typeTypeType}
+// CHECK:STDOUT:     inst+2:          {kind: TupleLiteral, arg0: block2, type: type1}
+// CHECK:STDOUT:     inst+3:          {kind: TupleType, arg0: typeBlock1, type: typeTypeType}
+// CHECK:STDOUT:     inst+4:          {kind: VarStorage, arg0: str2, type: type3}
+// CHECK:STDOUT:     inst+5:          {kind: PointerType, arg0: type3, type: typeTypeType}
+// CHECK:STDOUT:     inst+6:          {kind: FunctionDeclaration, arg0: function0, type: type5}
+// CHECK:STDOUT:     inst+7:          {kind: NameReference, arg0: str1, arg1: inst+0, type: type0}
+// CHECK:STDOUT:     inst+8:          {kind: IntegerLiteral, arg0: int3, type: type0}
+// CHECK:STDOUT:     inst+9:          {kind: BinaryOperatorAdd, arg0: inst+7, arg1: inst+8, type: type0}
+// CHECK:STDOUT:     inst+10:         {kind: RealLiteral, arg0: real0, type: type2}
+// CHECK:STDOUT:     inst+11:         {kind: TupleLiteral, arg0: block5, type: type3}
+// CHECK:STDOUT:     inst+12:         {kind: TupleAccess, arg0: inst+4, arg1: member0, type: type0}
+// CHECK:STDOUT:     inst+13:         {kind: InitializeFrom, arg0: inst+9, arg1: inst+12, type: type0}
+// CHECK:STDOUT:     inst+14:         {kind: TupleAccess, arg0: inst+4, arg1: member1, type: type2}
+// CHECK:STDOUT:     inst+15:         {kind: InitializeFrom, arg0: inst+10, arg1: inst+14, type: type2}
+// CHECK:STDOUT:     inst+16:         {kind: TupleInit, arg0: inst+11, arg1: block6, type: type3}
+// CHECK:STDOUT:     inst+17:         {kind: ReturnExpression, arg0: inst+16}
+// CHECK:STDOUT:   inst_blocks:
 // CHECK:STDOUT:     block0:          {}
 // CHECK:STDOUT:     block1:
-// CHECK:STDOUT:       0:               node+0
+// CHECK:STDOUT:       0:               inst+0
 // CHECK:STDOUT:     block2:
-// CHECK:STDOUT:       0:               nodeIntegerType
-// CHECK:STDOUT:       1:               nodeFloatingPointType
+// CHECK:STDOUT:       0:               instIntegerType
+// CHECK:STDOUT:       1:               instFloatingPointType
 // CHECK:STDOUT:     block3:
-// CHECK:STDOUT:       0:               node+0
-// CHECK:STDOUT:       1:               node+1
-// CHECK:STDOUT:       2:               node+2
-// CHECK:STDOUT:       3:               node+3
-// CHECK:STDOUT:       4:               node+4
+// CHECK:STDOUT:       0:               inst+0
+// CHECK:STDOUT:       1:               inst+1
+// CHECK:STDOUT:       2:               inst+2
+// CHECK:STDOUT:       3:               inst+3
+// CHECK:STDOUT:       4:               inst+4
 // CHECK:STDOUT:     block4:
-// CHECK:STDOUT:       0:               node+7
-// CHECK:STDOUT:       1:               node+8
-// CHECK:STDOUT:       2:               node+9
-// CHECK:STDOUT:       3:               node+10
-// CHECK:STDOUT:       4:               node+11
-// CHECK:STDOUT:       5:               node+12
-// CHECK:STDOUT:       6:               node+13
-// CHECK:STDOUT:       7:               node+14
-// CHECK:STDOUT:       8:               node+15
-// CHECK:STDOUT:       9:               node+16
-// CHECK:STDOUT:       10:              node+17
+// CHECK:STDOUT:       0:               inst+7
+// CHECK:STDOUT:       1:               inst+8
+// CHECK:STDOUT:       2:               inst+9
+// CHECK:STDOUT:       3:               inst+10
+// CHECK:STDOUT:       4:               inst+11
+// CHECK:STDOUT:       5:               inst+12
+// CHECK:STDOUT:       6:               inst+13
+// CHECK:STDOUT:       7:               inst+14
+// CHECK:STDOUT:       8:               inst+15
+// CHECK:STDOUT:       9:               inst+16
+// CHECK:STDOUT:       10:              inst+17
 // CHECK:STDOUT:     block5:
-// CHECK:STDOUT:       0:               node+9
-// CHECK:STDOUT:       1:               node+10
+// CHECK:STDOUT:       0:               inst+9
+// CHECK:STDOUT:       1:               inst+10
 // CHECK:STDOUT:     block6:
-// CHECK:STDOUT:       0:               node+13
-// CHECK:STDOUT:       1:               node+15
+// CHECK:STDOUT:       0:               inst+13
+// CHECK:STDOUT:       1:               inst+15
 // CHECK:STDOUT:     block7:
-// CHECK:STDOUT:       0:               node+5
-// CHECK:STDOUT:       1:               node+6
+// CHECK:STDOUT:       0:               inst+5
+// CHECK:STDOUT:       1:               inst+6
 // CHECK:STDOUT: ...

+ 4 - 4
toolchain/check/testdata/basics/verbose.carbon

@@ -8,10 +8,10 @@
 // NOAUTOUPDATE
 // SET-CHECK-SUBSET
 // CHECK:STDERR: Node Push 0: FunctionIntroducer -> <none>
-// CHECK:STDERR: AddNode: {kind: FunctionDeclaration, arg0: {{.*}}, type: type{{[0-9]+}}}
-// CHECK:STDERR: node_block_stack_ Push 1
-// CHECK:STDERR: AddNode: {kind: Return}
-// CHECK:STDERR: node_block_stack_ Pop 1: block{{[0-9]+}}
+// CHECK:STDERR: AddInst: {kind: FunctionDeclaration, arg0: {{.*}}, type: type{{[0-9]+}}}
+// CHECK:STDERR: inst_block_stack_ Push 1
+// CHECK:STDERR: AddInst: {kind: Return}
+// CHECK:STDERR: inst_block_stack_ Pop 1: block{{[0-9]+}}
 
 fn Foo() {
   return;

+ 2 - 2
toolchain/check/testdata/class/fail_redefinition.carbon

@@ -39,8 +39,8 @@ fn Class.H() {}
 // CHECK:STDOUT:   %H: <function> = fn_decl @H
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .F = <unexpected noderef 11>
-// CHECK:STDOUT:   .H = <unexpected noderef 12>
+// CHECK:STDOUT:   .F = <unexpected instref 11>
+// CHECK:STDOUT:   .H = <unexpected instref 12>
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 1
toolchain/check/testdata/class/nested_name.carbon

@@ -32,7 +32,7 @@ fn G(o: Outer) {
 // CHECK:STDOUT:   %.loc10: type = struct_type {.n: i32}
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
-// CHECK:STDOUT:   .Inner = <unexpected noderef 11>
+// CHECK:STDOUT:   .Inner = <unexpected instref 11>
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Inner {

+ 2 - 2
toolchain/lower/BUILD

@@ -43,8 +43,8 @@ cc_library(
         "//common:vlog",
         "//toolchain/sem_ir:entry_point",
         "//toolchain/sem_ir:file",
-        "//toolchain/sem_ir:node",
-        "//toolchain/sem_ir:node_kind",
+        "//toolchain/sem_ir:inst",
+        "//toolchain/sem_ir:inst_kind",
         "@llvm-project//llvm:Core",
         "@llvm-project//llvm:Support",
     ],

+ 33 - 33
toolchain/lower/file_context.cpp

@@ -10,7 +10,7 @@
 #include "toolchain/lower/function_context.h"
 #include "toolchain/sem_ir/entry_point.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Lower {
@@ -35,7 +35,7 @@ auto FileContext::Run() -> std::unique_ptr<llvm::Module> {
   // used.
   types_.resize(sem_ir_->types().size());
   for (auto type_id : sem_ir_->complete_types()) {
-    types_[type_id.index] = BuildType(sem_ir_->types().Get(type_id).node_id);
+    types_[type_id.index] = BuildType(sem_ir_->types().Get(type_id).inst_id);
   }
 
   // Lower function declarations.
@@ -61,8 +61,8 @@ auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id)
   const auto& function = sem_ir().functions().Get(function_id);
   const bool has_return_slot = function.return_slot_id.is_valid();
   auto implicit_param_refs =
-      sem_ir().node_blocks().Get(function.implicit_param_refs_id);
-  auto param_refs = sem_ir().node_blocks().Get(function.param_refs_id);
+      sem_ir().inst_blocks().Get(function.implicit_param_refs_id);
+  auto param_refs = sem_ir().inst_blocks().Get(function.param_refs_id);
 
   SemIR::InitializingRepresentation return_rep =
       function.return_type_id.is_valid()
@@ -73,22 +73,22 @@ auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id)
   CARBON_CHECK(return_rep.has_return_slot() == has_return_slot);
 
   llvm::SmallVector<llvm::Type*> param_types;
-  // TODO: Consider either storing `param_node_ids` somewhere so that we can
+  // TODO: Consider either storing `param_inst_ids` somewhere so that we can
   // reuse it from `BuildFunctionDefinition` and when building calls, or factor
   // out a mechanism to compute the mapping between parameters and arguments on
   // demand.
-  llvm::SmallVector<SemIR::NodeId> param_node_ids;
+  llvm::SmallVector<SemIR::InstId> param_inst_ids;
   auto max_llvm_params =
       has_return_slot + implicit_param_refs.size() + param_refs.size();
   param_types.reserve(max_llvm_params);
-  param_node_ids.reserve(max_llvm_params);
+  param_inst_ids.reserve(max_llvm_params);
   if (has_return_slot) {
     param_types.push_back(GetType(function.return_type_id)->getPointerTo());
-    param_node_ids.push_back(function.return_slot_id);
+    param_inst_ids.push_back(function.return_slot_id);
   }
   for (auto param_ref_id :
-       llvm::concat<const SemIR::NodeId>(implicit_param_refs, param_refs)) {
-    auto param_type_id = sem_ir().nodes().Get(param_ref_id).type_id();
+       llvm::concat<const SemIR::InstId>(implicit_param_refs, param_refs)) {
+    auto param_type_id = sem_ir().insts().Get(param_ref_id).type_id();
     switch (auto value_rep =
                 SemIR::GetValueRepresentation(sem_ir(), param_type_id);
             value_rep.kind) {
@@ -101,7 +101,7 @@ auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id)
       case SemIR::ValueRepresentation::Custom:
       case SemIR::ValueRepresentation::Pointer:
         param_types.push_back(GetType(value_rep.type_id));
-        param_node_ids.push_back(param_ref_id);
+        param_inst_ids.push_back(param_ref_id);
         break;
     }
   }
@@ -129,17 +129,17 @@ auto FileContext::BuildFunctionDeclaration(SemIR::FunctionId function_id)
                              mangled_name, llvm_module());
 
   // Set up parameters and the return slot.
-  for (auto [node_id, arg] :
-       llvm::zip_equal(param_node_ids, llvm_function->args())) {
-    auto node = sem_ir().nodes().Get(node_id);
-    if (node_id == function.return_slot_id) {
+  for (auto [inst_id, arg] :
+       llvm::zip_equal(param_inst_ids, llvm_function->args())) {
+    auto inst = sem_ir().insts().Get(inst_id);
+    if (inst_id == function.return_slot_id) {
       arg.setName("return");
       arg.addAttr(llvm::Attribute::getWithStructRetType(
           llvm_context(), GetType(function.return_type_id)));
-    } else if (node.Is<SemIR::SelfParameter>()) {
+    } else if (inst.Is<SemIR::SelfParameter>()) {
       arg.setName("self");
     } else {
-      arg.setName(sem_ir().strings().Get(node.As<SemIR::Parameter>().name_id));
+      arg.setName(sem_ir().strings().Get(inst.As<SemIR::Parameter>().name_id));
     }
   }
 
@@ -161,12 +161,12 @@ auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id)
   const bool has_return_slot = function.return_slot_id.is_valid();
 
   // Add parameters to locals.
-  // TODO: This duplicates the mapping between semantics nodes and LLVM
+  // TODO: This duplicates the mapping between sem_ir instructions and LLVM
   // function parameters that was already computed in BuildFunctionDeclaration.
   // We should only do that once.
   auto implicit_param_refs =
-      sem_ir().node_blocks().Get(function.implicit_param_refs_id);
-  auto param_refs = sem_ir().node_blocks().Get(function.param_refs_id);
+      sem_ir().inst_blocks().Get(function.implicit_param_refs_id);
+  auto param_refs = sem_ir().inst_blocks().Get(function.param_refs_id);
   int param_index = 0;
   if (has_return_slot) {
     function_lowering.SetLocal(function.return_slot_id,
@@ -174,8 +174,8 @@ auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id)
     ++param_index;
   }
   for (auto param_ref_id :
-       llvm::concat<const SemIR::NodeId>(implicit_param_refs, param_refs)) {
-    auto param_type_id = sem_ir().nodes().Get(param_ref_id).type_id();
+       llvm::concat<const SemIR::InstId>(implicit_param_refs, param_refs)) {
+    auto param_type_id = sem_ir().insts().Get(param_ref_id).type_id();
     if (SemIR::GetValueRepresentation(sem_ir(), param_type_id).kind ==
         SemIR::ValueRepresentation::None) {
       function_lowering.SetLocal(
@@ -206,8 +206,8 @@ auto FileContext::BuildFunctionDefinition(SemIR::FunctionId function_id)
   }
 }
 
-auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
-  switch (node_id.index) {
+auto FileContext::BuildType(SemIR::InstId inst_id) -> llvm::Type* {
+  switch (inst_id.index) {
     case SemIR::BuiltinKind::FloatingPointType.AsInt():
       // TODO: Handle different sizes.
       return llvm::Type::getDoubleTy(*llvm_context_);
@@ -228,10 +228,10 @@ auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
       break;
   }
 
-  auto node = sem_ir_->nodes().Get(node_id);
-  switch (node.kind()) {
+  auto inst = sem_ir_->insts().Get(inst_id);
+  switch (inst.kind()) {
     case SemIR::ArrayType::Kind: {
-      auto array_type = node.As<SemIR::ArrayType>();
+      auto array_type = inst.As<SemIR::ArrayType>();
       return llvm::ArrayType::get(
           GetType(array_type.element_type_id),
           sem_ir_->GetArrayBoundValue(array_type.bound_id));
@@ -239,21 +239,21 @@ auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
     case SemIR::ClassType::Kind: {
       auto object_representation_id =
           sem_ir_->classes()
-              .Get(node.As<SemIR::ClassType>().class_id)
+              .Get(inst.As<SemIR::ClassType>().class_id)
               .object_representation_id;
       return GetType(object_representation_id);
     }
     case SemIR::ConstType::Kind:
-      return GetType(node.As<SemIR::ConstType>().inner_id);
+      return GetType(inst.As<SemIR::ConstType>().inner_id);
     case SemIR::PointerType::Kind:
       return llvm::PointerType::get(*llvm_context_, /*AddressSpace=*/0);
     case SemIR::StructType::Kind: {
       auto fields =
-          sem_ir_->node_blocks().Get(node.As<SemIR::StructType>().fields_id);
+          sem_ir_->inst_blocks().Get(inst.As<SemIR::StructType>().fields_id);
       llvm::SmallVector<llvm::Type*> subtypes;
       subtypes.reserve(fields.size());
       for (auto field_id : fields) {
-        auto field = sem_ir_->nodes().GetAs<SemIR::StructTypeField>(field_id);
+        auto field = sem_ir_->insts().GetAs<SemIR::StructTypeField>(field_id);
         // TODO: Handle recursive types. The restriction for builtins prevents
         // recursion while still letting them cache.
         CARBON_CHECK(field.field_type_id.index < SemIR::BuiltinKind::ValidCount)
@@ -268,7 +268,7 @@ auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
       // function returns. LLVM doesn't allow declaring variables with a void
       // type, so that may require significant special casing.
       auto elements =
-          sem_ir_->type_blocks().Get(node.As<SemIR::TupleType>().elements_id);
+          sem_ir_->type_blocks().Get(inst.As<SemIR::TupleType>().elements_id);
       llvm::SmallVector<llvm::Type*> subtypes;
       subtypes.reserve(elements.size());
       for (auto element_id : elements) {
@@ -281,7 +281,7 @@ auto FileContext::BuildType(SemIR::NodeId node_id) -> llvm::Type* {
       return llvm::StructType::get(*llvm_context_);
     }
     default: {
-      CARBON_FATAL() << "Cannot use node as type: " << node_id << " " << node;
+      CARBON_FATAL() << "Cannot use inst as type: " << inst_id << " " << inst;
     }
   }
 }

+ 4 - 4
toolchain/lower/file_context.h

@@ -9,7 +9,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Lower {
 
@@ -60,9 +60,9 @@ class FileContext {
   // declaration with no definition, does nothing.
   auto BuildFunctionDefinition(SemIR::FunctionId function_id) -> void;
 
-  // Builds the type for the given node, which should then be cached by the
-  // caller.
-  auto BuildType(SemIR::NodeId node_id) -> llvm::Type*;
+  // Builds the type for the given instruction, which should then be cached by
+  // the caller.
+  auto BuildType(SemIR::InstId inst_id) -> llvm::Type*;
 
   // Returns the empty LLVM struct type used to represent the type `type`.
   auto GetTypeType() -> llvm::StructType* {

+ 17 - 17
toolchain/lower/function_context.cpp

@@ -17,7 +17,7 @@ FunctionContext::FunctionContext(FileContext& file_context,
       builder_(file_context.llvm_context()),
       vlog_stream_(vlog_stream) {}
 
-auto FunctionContext::GetBlock(SemIR::NodeBlockId block_id)
+auto FunctionContext::GetBlock(SemIR::InstBlockId block_id)
     -> llvm::BasicBlock* {
   llvm::BasicBlock*& entry = blocks_[block_id];
   if (!entry) {
@@ -26,7 +26,7 @@ auto FunctionContext::GetBlock(SemIR::NodeBlockId block_id)
   return entry;
 }
 
-auto FunctionContext::TryToReuseBlock(SemIR::NodeBlockId block_id,
+auto FunctionContext::TryToReuseBlock(SemIR::InstBlockId block_id,
                                       llvm::BasicBlock* block) -> bool {
   if (!blocks_.insert({block_id, block}).second) {
     return false;
@@ -37,23 +37,23 @@ auto FunctionContext::TryToReuseBlock(SemIR::NodeBlockId block_id,
   return true;
 }
 
-auto FunctionContext::LowerBlock(SemIR::NodeBlockId block_id) -> void {
-  for (const auto& node_id : sem_ir().node_blocks().Get(block_id)) {
-    auto node = sem_ir().nodes().Get(node_id);
-    CARBON_VLOG() << "Lowering " << node_id << ": " << node << "\n";
+auto FunctionContext::LowerBlock(SemIR::InstBlockId block_id) -> void {
+  for (const auto& inst_id : sem_ir().inst_blocks().Get(block_id)) {
+    auto inst = sem_ir().insts().Get(inst_id);
+    CARBON_VLOG() << "Lowering " << inst_id << ": " << inst << "\n";
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (node.kind()) {
-#define CARBON_SEM_IR_NODE_KIND(Name)                     \
+    switch (inst.kind()) {
+#define CARBON_SEM_IR_INST_KIND(Name)                     \
   case SemIR::Name::Kind:                                 \
-    Handle##Name(*this, node_id, node.As<SemIR::Name>()); \
+    Handle##Name(*this, inst_id, inst.As<SemIR::Name>()); \
     break;
 #include "toolchain/sem_ir/node_kind.def"
     }
   }
 }
 
-auto FunctionContext::GetBlockArg(SemIR::NodeBlockId block_id,
+auto FunctionContext::GetBlockArg(SemIR::InstBlockId block_id,
                                   SemIR::TypeId type_id) -> llvm::PHINode* {
   llvm::BasicBlock* block = GetBlock(block_id);
 
@@ -78,8 +78,8 @@ auto FunctionContext::CreateSyntheticBlock() -> llvm::BasicBlock* {
   return synthetic_block_;
 }
 
-auto FunctionContext::GetLocalOrGlobal(SemIR::NodeId node_id) -> llvm::Value* {
-  auto target = sem_ir().nodes().Get(node_id);
+auto FunctionContext::GetLocalOrGlobal(SemIR::InstId inst_id) -> llvm::Value* {
+  auto target = sem_ir().insts().Get(inst_id);
   if (auto function_decl = target.TryAs<SemIR::FunctionDeclaration>()) {
     return GetFunction(function_decl->function_id);
   }
@@ -87,12 +87,12 @@ auto FunctionContext::GetLocalOrGlobal(SemIR::NodeId node_id) -> llvm::Value* {
     return GetTypeAsValue();
   }
   // TODO: Handle other kinds of name references to globals.
-  return GetLocal(node_id);
+  return GetLocal(inst_id);
 }
 
 auto FunctionContext::FinishInitialization(SemIR::TypeId type_id,
-                                           SemIR::NodeId dest_id,
-                                           SemIR::NodeId source_id) -> void {
+                                           SemIR::InstId dest_id,
+                                           SemIR::InstId source_id) -> void {
   switch (SemIR::GetInitializingRepresentation(sem_ir(), type_id).kind) {
     case SemIR::InitializingRepresentation::None:
     case SemIR::InitializingRepresentation::InPlace:
@@ -103,8 +103,8 @@ auto FunctionContext::FinishInitialization(SemIR::TypeId type_id,
   }
 }
 
-auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::NodeId source_id,
-                                SemIR::NodeId dest_id) -> void {
+auto FunctionContext::CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id,
+                                SemIR::InstId dest_id) -> void {
   switch (auto rep = SemIR::GetValueRepresentation(sem_ir(), type_id);
           rep.kind) {
     case SemIR::ValueRepresentation::Unknown:

+ 29 - 29
toolchain/lower/function_context.h

@@ -10,7 +10,7 @@
 #include "llvm/IR/Module.h"
 #include "toolchain/lower/file_context.h"
 #include "toolchain/sem_ir/file.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::Lower {
 
@@ -23,44 +23,44 @@ class FunctionContext {
 
   // Returns a basic block corresponding to the start of the given semantics
   // block, and enqueues it for emission.
-  auto GetBlock(SemIR::NodeBlockId block_id) -> llvm::BasicBlock*;
+  auto GetBlock(SemIR::InstBlockId block_id) -> llvm::BasicBlock*;
 
   // If we have not yet allocated a `BasicBlock` for this `block_id`, set it to
   // `block`, and enqueue `block_id` for emission. Returns whether we set the
   // block.
-  auto TryToReuseBlock(SemIR::NodeBlockId block_id, llvm::BasicBlock* block)
+  auto TryToReuseBlock(SemIR::InstBlockId block_id, llvm::BasicBlock* block)
       -> bool;
 
   // Builds LLVM IR for the sequence of instructions in `block_id`.
-  auto LowerBlock(SemIR::NodeBlockId block_id) -> void;
+  auto LowerBlock(SemIR::InstBlockId block_id) -> void;
 
   // Returns a phi node corresponding to the block argument of the given basic
   // block.
-  auto GetBlockArg(SemIR::NodeBlockId block_id, SemIR::TypeId type_id)
+  auto GetBlockArg(SemIR::InstBlockId block_id, SemIR::TypeId type_id)
       -> llvm::PHINode*;
 
-  // Returns a local (versus global) value for the given node.
-  auto GetLocal(SemIR::NodeId node_id) -> llvm::Value* {
+  // Returns a local (versus global) value for the given instruction.
+  auto GetLocal(SemIR::InstId inst_id) -> llvm::Value* {
     // All builtins are types, with the same empty lowered value.
-    if (node_id.index < SemIR::BuiltinKind::ValidCount) {
+    if (inst_id.index < SemIR::BuiltinKind::ValidCount) {
       return GetTypeAsValue();
     }
 
-    auto it = locals_.find(node_id);
+    auto it = locals_.find(inst_id);
     CARBON_CHECK(it != locals_.end())
-        << "Missing local: " << node_id << " " << sem_ir().nodes().Get(node_id);
+        << "Missing local: " << inst_id << " " << sem_ir().insts().Get(inst_id);
     return it->second;
   }
 
-  // Sets the value for the given node.
-  auto SetLocal(SemIR::NodeId node_id, llvm::Value* value) {
-    bool added = locals_.insert({node_id, value}).second;
-    CARBON_CHECK(added) << "Duplicate local insert: " << node_id << " "
-                        << sem_ir().nodes().Get(node_id);
+  // Sets the value for the given instruction.
+  auto SetLocal(SemIR::InstId inst_id, llvm::Value* value) {
+    bool added = locals_.insert({inst_id, value}).second;
+    CARBON_CHECK(added) << "Duplicate local insert: " << inst_id << " "
+                        << sem_ir().insts().Get(inst_id);
   }
 
-  // Returns a value for the given node, which might not be local.
-  auto GetLocalOrGlobal(SemIR::NodeId node_id) -> llvm::Value*;
+  // Returns a value for the given instruction, which might not be local.
+  auto GetLocalOrGlobal(SemIR::InstId inst_id) -> llvm::Value*;
 
   // Gets a callable's function.
   auto GetFunction(SemIR::FunctionId function_id) -> llvm::Function* {
@@ -77,7 +77,7 @@ class FunctionContext {
     return file_context_->GetTypeAsValue();
   }
 
-  // Create a synthetic block that corresponds to no SemIR::NodeBlockId. Such
+  // Create a synthetic block that corresponds to no SemIR::InstBlockId. Such
   // a block should only ever have a single predecessor, and is used when we
   // need multiple `llvm::BasicBlock`s to model the linear control flow in a
   // single SemIR::File block.
@@ -92,8 +92,8 @@ class FunctionContext {
   // initialization of `dest_id` from that initializer. This is a no-op if the
   // initialization was performed in-place, and otherwise performs a store or a
   // copy.
-  auto FinishInitialization(SemIR::TypeId type_id, SemIR::NodeId dest_id,
-                            SemIR::NodeId init_id) -> void;
+  auto FinishInitialization(SemIR::TypeId type_id, SemIR::InstId dest_id,
+                            SemIR::InstId init_id) -> void;
 
   auto llvm_context() -> llvm::LLVMContext& {
     return file_context_->llvm_context();
@@ -106,8 +106,8 @@ class FunctionContext {
   // Emits a value copy for type `type_id` from `source_id` to `dest_id`.
   // `source_id` must produce a value representation for `type_id`, and
   // `dest_id` must be a pointer to a `type_id` object.
-  auto CopyValue(SemIR::TypeId type_id, SemIR::NodeId source_id,
-                 SemIR::NodeId dest_id) -> void;
+  auto CopyValue(SemIR::TypeId type_id, SemIR::InstId source_id,
+                 SemIR::InstId dest_id) -> void;
 
   // Context for the overall lowering process.
   FileContext* file_context_;
@@ -121,22 +121,22 @@ class FunctionContext {
   llvm::raw_ostream* vlog_stream_;
 
   // Maps a function's SemIR::File blocks to lowered blocks.
-  llvm::DenseMap<SemIR::NodeBlockId, llvm::BasicBlock*> blocks_;
+  llvm::DenseMap<SemIR::InstBlockId, llvm::BasicBlock*> blocks_;
 
   // The synthetic block we most recently created. May be null if there is no
   // such block.
   llvm::BasicBlock* synthetic_block_ = nullptr;
 
-  // Maps a function's SemIR::File nodes to lowered values.
+  // Maps a function's SemIR::File instructions to lowered values.
   // TODO: Handle nested scopes. Right now this is just cleared at the end of
   // every block.
-  llvm::DenseMap<SemIR::NodeId, llvm::Value*> locals_;
+  llvm::DenseMap<SemIR::InstId, llvm::Value*> locals_;
 };
 
-// Declare handlers for each SemIR::File node.
-#define CARBON_SEM_IR_NODE_KIND(Name)                                \
-  auto Handle##Name(FunctionContext& context, SemIR::NodeId node_id, \
-                    SemIR::Name node)                                \
+// Declare handlers for each SemIR::File instruction.
+#define CARBON_SEM_IR_INST_KIND(Name)                                \
+  auto Handle##Name(FunctionContext& context, SemIR::InstId inst_id, \
+                    SemIR::Name inst)                                \
       ->void;
 #include "toolchain/sem_ir/node_kind.def"
 

+ 185 - 185
toolchain/lower/handle.cpp

@@ -5,109 +5,109 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
 #include "toolchain/lower/function_context.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::Lower {
 
 auto HandleCrossReference(FunctionContext& /*context*/,
-                          SemIR::NodeId /*node_id*/, SemIR::CrossReference node)
+                          SemIR::InstId /*inst_id*/, SemIR::CrossReference inst)
     -> void {
-  CARBON_FATAL() << "TODO: Add support: " << node;
+  CARBON_FATAL() << "TODO: Add support: " << inst;
 }
 
-auto HandleAddressOf(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::AddressOf node) -> void {
-  context.SetLocal(node_id, context.GetLocal(node.lvalue_id));
+auto HandleAddressOf(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::AddressOf inst) -> void {
+  context.SetLocal(inst_id, context.GetLocal(inst.lvalue_id));
 }
 
-auto HandleArrayIndex(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::ArrayIndex node) -> void {
-  auto* array_value = context.GetLocal(node.array_id);
+auto HandleArrayIndex(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::ArrayIndex inst) -> void {
+  auto* array_value = context.GetLocal(inst.array_id);
   auto* llvm_type =
-      context.GetType(context.sem_ir().nodes().Get(node.array_id).type_id());
+      context.GetType(context.sem_ir().insts().Get(inst.array_id).type_id());
   llvm::Value* indexes[2] = {
       llvm::ConstantInt::get(llvm::Type::getInt32Ty(context.llvm_context()), 0),
-      context.GetLocal(node.index_id)};
-  context.SetLocal(node_id,
+      context.GetLocal(inst.index_id)};
+  context.SetLocal(inst_id,
                    context.builder().CreateInBoundsGEP(llvm_type, array_value,
                                                        indexes, "array.index"));
 }
 
-auto HandleArrayInit(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::ArrayInit node) -> void {
+auto HandleArrayInit(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::ArrayInit inst) -> void {
   // The result of initialization is the return slot of the initializer.
-  context.SetLocal(node_id,
+  context.SetLocal(inst_id,
                    context.GetLocal(context.sem_ir()
-                                        .node_blocks()
-                                        .Get(node.inits_and_return_slot_id)
+                                        .inst_blocks()
+                                        .Get(inst.inits_and_return_slot_id)
                                         .back()));
 }
 
-auto HandleAssign(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                  SemIR::Assign node) -> void {
-  auto storage_type_id = context.sem_ir().nodes().Get(node.lhs_id).type_id();
-  context.FinishInitialization(storage_type_id, node.lhs_id, node.rhs_id);
+auto HandleAssign(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                  SemIR::Assign inst) -> void {
+  auto storage_type_id = context.sem_ir().insts().Get(inst.lhs_id).type_id();
+  context.FinishInitialization(storage_type_id, inst.lhs_id, inst.rhs_id);
 }
 
 auto HandleBinaryOperatorAdd(FunctionContext& /*context*/,
-                             SemIR::NodeId /*node_id*/,
-                             SemIR::BinaryOperatorAdd node) -> void {
-  CARBON_FATAL() << "TODO: Add support: " << node;
+                             SemIR::InstId /*inst_id*/,
+                             SemIR::BinaryOperatorAdd inst) -> void {
+  CARBON_FATAL() << "TODO: Add support: " << inst;
 }
 
-auto HandleBindName(FunctionContext& context, SemIR::NodeId node_id,
-                    SemIR::BindName node) -> void {
-  context.SetLocal(node_id, context.GetLocal(node.value_id));
+auto HandleBindName(FunctionContext& context, SemIR::InstId inst_id,
+                    SemIR::BindName inst) -> void {
+  context.SetLocal(inst_id, context.GetLocal(inst.value_id));
 }
 
-auto HandleBlockArg(FunctionContext& context, SemIR::NodeId node_id,
-                    SemIR::BlockArg node) -> void {
-  context.SetLocal(node_id, context.GetBlockArg(node.block_id, node.type_id));
+auto HandleBlockArg(FunctionContext& context, SemIR::InstId inst_id,
+                    SemIR::BlockArg inst) -> void {
+  context.SetLocal(inst_id, context.GetBlockArg(inst.block_id, inst.type_id));
 }
 
-auto HandleBoolLiteral(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::BoolLiteral node) -> void {
+auto HandleBoolLiteral(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::BoolLiteral inst) -> void {
   llvm::Value* v =
-      llvm::ConstantInt::get(context.builder().getInt1Ty(), node.value.index);
-  context.SetLocal(node_id, v);
+      llvm::ConstantInt::get(context.builder().getInt1Ty(), inst.value.index);
+  context.SetLocal(inst_id, v);
 }
 
-auto HandleBoundMethod(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::BoundMethod node) -> void {
+auto HandleBoundMethod(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::BoundMethod inst) -> void {
   // Propagate just the function; the object is separately provided to the
   // enclosing call as an implicit argument.
-  context.SetLocal(node_id, context.GetLocalOrGlobal(node.function_id));
+  context.SetLocal(inst_id, context.GetLocalOrGlobal(inst.function_id));
 }
 
-auto HandleBranch(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                  SemIR::Branch node) -> void {
+auto HandleBranch(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                  SemIR::Branch inst) -> void {
   // Opportunistically avoid creating a BasicBlock that contains just a branch.
   // TODO: Don't do this if it would remove a loop preheader block.
   llvm::BasicBlock* block = context.builder().GetInsertBlock();
-  if (block->empty() && context.TryToReuseBlock(node.target_id, block)) {
+  if (block->empty() && context.TryToReuseBlock(inst.target_id, block)) {
     // Reuse this block as the branch target.
   } else {
-    context.builder().CreateBr(context.GetBlock(node.target_id));
+    context.builder().CreateBr(context.GetBlock(inst.target_id));
   }
 
   context.builder().ClearInsertionPoint();
 }
 
-auto HandleBranchIf(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                    SemIR::BranchIf node) -> void {
-  llvm::Value* cond = context.GetLocal(node.cond_id);
-  llvm::BasicBlock* then_block = context.GetBlock(node.target_id);
+auto HandleBranchIf(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                    SemIR::BranchIf inst) -> void {
+  llvm::Value* cond = context.GetLocal(inst.cond_id);
+  llvm::BasicBlock* then_block = context.GetBlock(inst.target_id);
   llvm::BasicBlock* else_block = context.CreateSyntheticBlock();
   context.builder().CreateCondBr(cond, then_block, else_block);
   context.builder().SetInsertPoint(else_block);
 }
 
-auto HandleBranchWithArg(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                         SemIR::BranchWithArg node) -> void {
-  llvm::Value* arg = context.GetLocal(node.arg_id);
+auto HandleBranchWithArg(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                         SemIR::BranchWithArg inst) -> void {
+  llvm::Value* arg = context.GetLocal(inst.arg_id);
   SemIR::TypeId arg_type_id =
-      context.sem_ir().nodes().Get(node.arg_id).type_id();
+      context.sem_ir().insts().Get(inst.arg_id).type_id();
 
   // Opportunistically avoid creating a BasicBlock that contains just a branch.
   // We only do this for a block that we know will only have a single
@@ -116,41 +116,41 @@ auto HandleBranchWithArg(FunctionContext& context, SemIR::NodeId /*node_id*/,
   llvm::BasicBlock* block = context.builder().GetInsertBlock();
   llvm::BasicBlock* phi_predecessor = block;
   if (block->empty() && context.IsCurrentSyntheticBlock(block) &&
-      context.TryToReuseBlock(node.target_id, block)) {
+      context.TryToReuseBlock(inst.target_id, block)) {
     // Reuse this block as the branch target.
     phi_predecessor = block->getSinglePredecessor();
     CARBON_CHECK(phi_predecessor)
         << "Synthetic block did not have a single predecessor";
   } else {
-    context.builder().CreateBr(context.GetBlock(node.target_id));
+    context.builder().CreateBr(context.GetBlock(inst.target_id));
   }
 
-  context.GetBlockArg(node.target_id, arg_type_id)
+  context.GetBlockArg(inst.target_id, arg_type_id)
       ->addIncoming(arg, phi_predecessor);
   context.builder().ClearInsertionPoint();
 }
 
-auto HandleBuiltin(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                   SemIR::Builtin node) -> void {
-  CARBON_FATAL() << "TODO: Add support: " << node;
+auto HandleBuiltin(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                   SemIR::Builtin inst) -> void {
+  CARBON_FATAL() << "TODO: Add support: " << inst;
 }
 
-auto HandleCall(FunctionContext& context, SemIR::NodeId node_id,
-                SemIR::Call node) -> void {
-  auto* callee = llvm::cast<llvm::Function>(context.GetLocal(node.callee_id));
+auto HandleCall(FunctionContext& context, SemIR::InstId inst_id,
+                SemIR::Call inst) -> void {
+  auto* callee = llvm::cast<llvm::Function>(context.GetLocal(inst.callee_id));
 
   std::vector<llvm::Value*> args;
-  llvm::ArrayRef<SemIR::NodeId> arg_ids =
-      context.sem_ir().node_blocks().Get(node.args_id);
+  llvm::ArrayRef<SemIR::InstId> arg_ids =
+      context.sem_ir().inst_blocks().Get(inst.args_id);
 
-  if (SemIR::GetInitializingRepresentation(context.sem_ir(), node.type_id)
+  if (SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
           .has_return_slot()) {
     args.push_back(context.GetLocal(arg_ids.back()));
     arg_ids = arg_ids.drop_back();
   }
 
   for (auto arg_id : arg_ids) {
-    auto arg_type_id = context.sem_ir().nodes().Get(arg_id).type_id();
+    auto arg_type_id = context.sem_ir().insts().Get(arg_id).type_id();
     if (SemIR::GetValueRepresentation(context.sem_ir(), arg_type_id).kind !=
         SemIR::ValueRepresentation::None) {
       args.push_back(context.GetLocal(arg_id));
@@ -158,7 +158,7 @@ auto HandleCall(FunctionContext& context, SemIR::NodeId node_id,
   }
 
   auto* call = context.builder().CreateCall(callee, args);
-  context.SetLocal(node_id, call);
+  context.SetLocal(inst_id, call);
 
   // Name the call's result the same as the callee.
   // TODO: Is this a helpful name?
@@ -168,8 +168,8 @@ auto HandleCall(FunctionContext& context, SemIR::NodeId node_id,
 }
 
 auto HandleClassDeclaration(FunctionContext& /*context*/,
-                            SemIR::NodeId /*node_id*/,
-                            SemIR::ClassDeclaration /*node*/) -> void {
+                            SemIR::InstId /*inst_id*/,
+                            SemIR::ClassDeclaration /*inst*/) -> void {
   // No action to perform.
 }
 
@@ -177,14 +177,14 @@ auto HandleClassDeclaration(FunctionContext& /*context*/,
 // index. Depending on the expression category and value representation of the
 // aggregate input, this will either produce a value or a reference.
 static auto GetAggregateElement(FunctionContext& context,
-                                SemIR::NodeId aggr_node_id,
+                                SemIR::InstId aggr_inst_id,
                                 SemIR::MemberIndex idx,
                                 SemIR::TypeId result_type_id, llvm::Twine name)
     -> llvm::Value* {
-  auto aggr_node = context.sem_ir().nodes().Get(aggr_node_id);
-  auto* aggr_value = context.GetLocal(aggr_node_id);
+  auto aggr_inst = context.sem_ir().insts().Get(aggr_inst_id);
+  auto* aggr_value = context.GetLocal(aggr_inst_id);
 
-  switch (SemIR::GetExpressionCategory(context.sem_ir(), aggr_node_id)) {
+  switch (SemIR::GetExpressionCategory(context.sem_ir(), aggr_inst_id)) {
     case SemIR::ExpressionCategory::Error:
     case SemIR::ExpressionCategory::NotExpression:
     case SemIR::ExpressionCategory::Initializing:
@@ -193,7 +193,7 @@ static auto GetAggregateElement(FunctionContext& context,
 
     case SemIR::ExpressionCategory::Value: {
       auto value_rep =
-          SemIR::GetValueRepresentation(context.sem_ir(), aggr_node.type_id());
+          SemIR::GetValueRepresentation(context.sem_ir(), aggr_inst.type_id());
       CARBON_CHECK(value_rep.aggregate_kind !=
                    SemIR::ValueRepresentation::NotAggregate)
           << "aggregate type should have aggregate value representation";
@@ -237,7 +237,7 @@ static auto GetAggregateElement(FunctionContext& context,
     case SemIR::ExpressionCategory::DurableReference:
     case SemIR::ExpressionCategory::EphemeralReference: {
       // Just locate the aggregate element.
-      auto* aggr_type = context.GetType(aggr_node.type_id());
+      auto* aggr_type = context.GetType(aggr_inst.type_id());
       return context.builder().CreateStructGEP(aggr_type, aggr_value, idx.index,
                                                name);
     }
@@ -247,24 +247,24 @@ static auto GetAggregateElement(FunctionContext& context,
 static auto GetStructFieldName(FunctionContext& context,
                                SemIR::TypeId struct_type_id,
                                SemIR::MemberIndex index) -> llvm::StringRef {
-  auto fields = context.sem_ir().node_blocks().Get(
+  auto fields = context.sem_ir().inst_blocks().Get(
       context.sem_ir()
-          .nodes()
+          .insts()
           .GetAs<SemIR::StructType>(
-              context.sem_ir().types().Get(struct_type_id).node_id)
+              context.sem_ir().types().Get(struct_type_id).inst_id)
           .fields_id);
-  auto field = context.sem_ir().nodes().GetAs<SemIR::StructTypeField>(
+  auto field = context.sem_ir().insts().GetAs<SemIR::StructTypeField>(
       fields[index.index]);
   return context.sem_ir().strings().Get(field.name_id);
 }
 
-auto HandleClassFieldAccess(FunctionContext& context, SemIR::NodeId node_id,
-                            SemIR::ClassFieldAccess node) -> void {
+auto HandleClassFieldAccess(FunctionContext& context, SemIR::InstId inst_id,
+                            SemIR::ClassFieldAccess inst) -> void {
   // Find the class that we're performing access into.
-  auto class_type_id = context.sem_ir().nodes().Get(node.base_id).type_id();
+  auto class_type_id = context.sem_ir().insts().Get(inst.base_id).type_id();
   auto class_id =
       context.sem_ir()
-          .nodes()
+          .insts()
           .GetAs<SemIR::ClassType>(
               context.sem_ir().GetTypeAllowBuiltinTypes(class_type_id))
           .class_id;
@@ -273,97 +273,97 @@ auto HandleClassFieldAccess(FunctionContext& context, SemIR::NodeId node_id,
   // Translate the class field access into a struct access on the object
   // representation.
   context.SetLocal(
-      node_id,
+      inst_id,
       GetAggregateElement(
-          context, node.base_id, node.index, node.type_id,
+          context, inst.base_id, inst.index, inst.type_id,
           GetStructFieldName(context, class_info.object_representation_id,
-                             node.index)));
+                             inst.index)));
 }
 
-auto HandleDereference(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::Dereference node) -> void {
-  context.SetLocal(node_id, context.GetLocal(node.pointer_id));
+auto HandleDereference(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::Dereference inst) -> void {
+  context.SetLocal(inst_id, context.GetLocal(inst.pointer_id));
 }
 
-auto HandleField(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                 SemIR::Field /*node*/) -> void {
+auto HandleField(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                 SemIR::Field /*inst*/) -> void {
   // No action to perform.
 }
 
 auto HandleFunctionDeclaration(FunctionContext& /*context*/,
-                               SemIR::NodeId /*node_id*/,
-                               SemIR::FunctionDeclaration node) -> void {
+                               SemIR::InstId /*inst_id*/,
+                               SemIR::FunctionDeclaration inst) -> void {
   CARBON_FATAL()
       << "Should not be encountered. If that changes, we may want to change "
          "higher-level logic to skip them rather than calling this. "
-      << node;
+      << inst;
 }
 
-auto HandleInitializeFrom(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                          SemIR::InitializeFrom node) -> void {
-  auto storage_type_id = context.sem_ir().nodes().Get(node.dest_id).type_id();
-  context.FinishInitialization(storage_type_id, node.dest_id, node.src_id);
+auto HandleInitializeFrom(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                          SemIR::InitializeFrom inst) -> void {
+  auto storage_type_id = context.sem_ir().insts().Get(inst.dest_id).type_id();
+  context.FinishInitialization(storage_type_id, inst.dest_id, inst.src_id);
 }
 
-auto HandleIntegerLiteral(FunctionContext& context, SemIR::NodeId node_id,
-                          SemIR::IntegerLiteral node) -> void {
-  const llvm::APInt& i = context.sem_ir().integers().Get(node.integer_id);
+auto HandleIntegerLiteral(FunctionContext& context, SemIR::InstId inst_id,
+                          SemIR::IntegerLiteral inst) -> void {
+  const llvm::APInt& i = context.sem_ir().integers().Get(inst.integer_id);
   // TODO: This won't offer correct semantics, but seems close enough for now.
   llvm::Value* v =
       llvm::ConstantInt::get(context.builder().getInt32Ty(), i.getZExtValue());
-  context.SetLocal(node_id, v);
+  context.SetLocal(inst_id, v);
 }
 
-auto HandleNameReference(FunctionContext& context, SemIR::NodeId node_id,
-                         SemIR::NameReference node) -> void {
-  auto type_node_id = context.sem_ir().GetTypeAllowBuiltinTypes(node.type_id);
-  if (type_node_id == SemIR::NodeId::BuiltinNamespaceType) {
+auto HandleNameReference(FunctionContext& context, SemIR::InstId inst_id,
+                         SemIR::NameReference inst) -> void {
+  auto type_inst_id = context.sem_ir().GetTypeAllowBuiltinTypes(inst.type_id);
+  if (type_inst_id == SemIR::InstId::BuiltinNamespaceType) {
     return;
   }
 
-  context.SetLocal(node_id, context.GetLocalOrGlobal(node.value_id));
+  context.SetLocal(inst_id, context.GetLocalOrGlobal(inst.value_id));
 }
 
-auto HandleNamespace(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                     SemIR::Namespace node) -> void {
+auto HandleNamespace(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                     SemIR::Namespace inst) -> void {
   CARBON_FATAL()
       << "Should not be encountered. If that changes, we may want to change "
          "higher-level logic to skip them rather than calling this. "
-      << node;
+      << inst;
 }
 
-auto HandleNoOp(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                SemIR::NoOp /*node*/) -> void {
+auto HandleNoOp(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                SemIR::NoOp /*inst*/) -> void {
   // No action to take.
 }
 
-auto HandleParameter(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                     SemIR::Parameter /*node*/) -> void {
+auto HandleParameter(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                     SemIR::Parameter /*inst*/) -> void {
   CARBON_FATAL() << "Parameters should be lowered by `BuildFunctionDefinition`";
 }
 
-auto HandleRealLiteral(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::RealLiteral node) -> void {
-  const Real& real = context.sem_ir().reals().Get(node.real_id);
+auto HandleRealLiteral(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::RealLiteral inst) -> void {
+  const Real& real = context.sem_ir().reals().Get(inst.real_id);
   // TODO: This will probably have overflow issues, and should be fixed.
   double val =
       real.mantissa.getZExtValue() *
       std::pow((real.is_decimal ? 10 : 2), real.exponent.getSExtValue());
   llvm::APFloat llvm_val(val);
-  context.SetLocal(node_id, llvm::ConstantFP::get(
+  context.SetLocal(inst_id, llvm::ConstantFP::get(
                                 context.builder().getDoubleTy(), llvm_val));
 }
 
-auto HandleReturn(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                  SemIR::Return /*node*/) -> void {
+auto HandleReturn(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                  SemIR::Return /*inst*/) -> void {
   context.builder().CreateRetVoid();
 }
 
-auto HandleReturnExpression(FunctionContext& context, SemIR::NodeId /*node_id*/,
-                            SemIR::ReturnExpression node) -> void {
+auto HandleReturnExpression(FunctionContext& context, SemIR::InstId /*inst_id*/,
+                            SemIR::ReturnExpression inst) -> void {
   switch (SemIR::GetInitializingRepresentation(
               context.sem_ir(),
-              context.sem_ir().nodes().Get(node.expr_id).type_id())
+              context.sem_ir().insts().Get(inst.expr_id).type_id())
               .kind) {
     case SemIR::InitializingRepresentation::None:
     case SemIR::InitializingRepresentation::InPlace:
@@ -372,41 +372,41 @@ auto HandleReturnExpression(FunctionContext& context, SemIR::NodeId /*node_id*/,
       return;
     case SemIR::InitializingRepresentation::ByCopy:
       // The expression produces the value representation for the type.
-      context.builder().CreateRet(context.GetLocal(node.expr_id));
+      context.builder().CreateRet(context.GetLocal(inst.expr_id));
       return;
   }
 }
 
 auto HandleSelfParameter(FunctionContext& /*context*/,
-                         SemIR::NodeId /*node_id*/,
-                         SemIR::SelfParameter /*node*/) -> void {
+                         SemIR::InstId /*inst_id*/,
+                         SemIR::SelfParameter /*inst*/) -> void {
   CARBON_FATAL() << "Parameters should be lowered by `BuildFunctionDefinition`";
 }
 
-auto HandleSpliceBlock(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::SpliceBlock node) -> void {
-  context.LowerBlock(node.block_id);
-  context.SetLocal(node_id, context.GetLocal(node.result_id));
+auto HandleSpliceBlock(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::SpliceBlock inst) -> void {
+  context.LowerBlock(inst.block_id);
+  context.SetLocal(inst_id, context.GetLocal(inst.result_id));
 }
 
 auto HandleStringLiteral(FunctionContext& /*context*/,
-                         SemIR::NodeId /*node_id*/, SemIR::StringLiteral node)
+                         SemIR::InstId /*inst_id*/, SemIR::StringLiteral inst)
     -> void {
-  CARBON_FATAL() << "TODO: Add support: " << node;
+  CARBON_FATAL() << "TODO: Add support: " << inst;
 }
 
-auto HandleStructAccess(FunctionContext& context, SemIR::NodeId node_id,
-                        SemIR::StructAccess node) -> void {
-  auto struct_type_id = context.sem_ir().nodes().Get(node.struct_id).type_id();
+auto HandleStructAccess(FunctionContext& context, SemIR::InstId inst_id,
+                        SemIR::StructAccess inst) -> void {
+  auto struct_type_id = context.sem_ir().insts().Get(inst.struct_id).type_id();
   context.SetLocal(
-      node_id, GetAggregateElement(
-                   context, node.struct_id, node.index, node.type_id,
-                   GetStructFieldName(context, struct_type_id, node.index)));
+      inst_id, GetAggregateElement(
+                   context, inst.struct_id, inst.index, inst.type_id,
+                   GetStructFieldName(context, struct_type_id, inst.index)));
 }
 
 auto HandleStructLiteral(FunctionContext& /*context*/,
-                         SemIR::NodeId /*node_id*/,
-                         SemIR::StructLiteral /*node*/) -> void {
+                         SemIR::InstId /*inst_id*/,
+                         SemIR::StructLiteral /*inst*/) -> void {
   // A StructLiteral should always be converted to a StructInit or StructValue
   // if its value is needed.
 }
@@ -415,7 +415,7 @@ auto HandleStructLiteral(FunctionContext& /*context*/,
 // contents of `refs_id`.
 auto EmitStructOrTupleValueRepresentation(FunctionContext& context,
                                           SemIR::TypeId type_id,
-                                          SemIR::NodeBlockId refs_id,
+                                          SemIR::InstBlockId refs_id,
                                           llvm::Twine name) -> llvm::Value* {
   auto value_rep = SemIR::GetValueRepresentation(context.sem_ir(), type_id);
   switch (value_rep.kind) {
@@ -427,7 +427,7 @@ auto EmitStructOrTupleValueRepresentation(FunctionContext& context,
       return llvm::PoisonValue::get(context.GetType(value_rep.type_id));
 
     case SemIR::ValueRepresentation::Copy: {
-      auto refs = context.sem_ir().node_blocks().Get(refs_id);
+      auto refs = context.sem_ir().inst_blocks().Get(refs_id);
       CARBON_CHECK(refs.size() == 1)
           << "Unexpected size for aggregate with by-copy value representation";
       // TODO: Remove the LLVM StructType wrapper in this case, so we don't
@@ -447,7 +447,7 @@ auto EmitStructOrTupleValueRepresentation(FunctionContext& context,
           context.builder().CreateAlloca(llvm_value_rep_type,
                                          /*ArraySize=*/nullptr, name);
       for (auto [i, ref] :
-           llvm::enumerate(context.sem_ir().node_blocks().Get(refs_id))) {
+           llvm::enumerate(context.sem_ir().inst_blocks().Get(refs_id))) {
         context.builder().CreateStore(
             context.GetLocal(ref),
             context.builder().CreateStructGEP(llvm_value_rep_type, alloca, i));
@@ -461,107 +461,107 @@ auto EmitStructOrTupleValueRepresentation(FunctionContext& context,
   }
 }
 
-auto HandleStructInit(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::StructInit node) -> void {
-  auto* llvm_type = context.GetType(node.type_id);
+auto HandleStructInit(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::StructInit inst) -> void {
+  auto* llvm_type = context.GetType(inst.type_id);
 
-  switch (SemIR::GetInitializingRepresentation(context.sem_ir(), node.type_id)
+  switch (SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
               .kind) {
     case SemIR::InitializingRepresentation::None:
     case SemIR::InitializingRepresentation::InPlace:
       // TODO: Add a helper to poison a value slot.
-      context.SetLocal(node_id, llvm::PoisonValue::get(llvm_type));
+      context.SetLocal(inst_id, llvm::PoisonValue::get(llvm_type));
       break;
 
     case SemIR::InitializingRepresentation::ByCopy: {
       context.SetLocal(
-          node_id, EmitStructOrTupleValueRepresentation(
-                       context, node.type_id, node.elements_id, "struct.init"));
+          inst_id, EmitStructOrTupleValueRepresentation(
+                       context, inst.type_id, inst.elements_id, "struct.init"));
       break;
     }
   }
 }
 
-auto HandleStructValue(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::StructValue node) -> void {
-  context.SetLocal(node_id,
+auto HandleStructValue(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::StructValue inst) -> void {
+  context.SetLocal(inst_id,
                    EmitStructOrTupleValueRepresentation(
-                       context, node.type_id, node.elements_id, "struct"));
+                       context, inst.type_id, inst.elements_id, "struct"));
 }
 
 auto HandleStructTypeField(FunctionContext& /*context*/,
-                           SemIR::NodeId /*node_id*/,
-                           SemIR::StructTypeField /*node*/) -> void {
+                           SemIR::InstId /*inst_id*/,
+                           SemIR::StructTypeField /*inst*/) -> void {
   // No action to take.
 }
 
-auto HandleTupleAccess(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::TupleAccess node) -> void {
-  context.SetLocal(node_id,
-                   GetAggregateElement(context, node.tuple_id, node.index,
-                                       node.type_id, "tuple.elem"));
+auto HandleTupleAccess(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::TupleAccess inst) -> void {
+  context.SetLocal(inst_id,
+                   GetAggregateElement(context, inst.tuple_id, inst.index,
+                                       inst.type_id, "tuple.elem"));
 }
 
-auto HandleTupleIndex(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::TupleIndex node) -> void {
-  auto index_node =
-      context.sem_ir().nodes().GetAs<SemIR::IntegerLiteral>(node.index_id);
+auto HandleTupleIndex(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::TupleIndex inst) -> void {
+  auto index_inst =
+      context.sem_ir().insts().GetAs<SemIR::IntegerLiteral>(inst.index_id);
   auto index =
-      context.sem_ir().integers().Get(index_node.integer_id).getZExtValue();
-  context.SetLocal(node_id, GetAggregateElement(context, node.tuple_id,
+      context.sem_ir().integers().Get(index_inst.integer_id).getZExtValue();
+  context.SetLocal(inst_id, GetAggregateElement(context, inst.tuple_id,
                                                 SemIR::MemberIndex(index),
-                                                node.type_id, "tuple.index"));
+                                                inst.type_id, "tuple.index"));
 }
 
-auto HandleTupleLiteral(FunctionContext& /*context*/, SemIR::NodeId /*node_id*/,
-                        SemIR::TupleLiteral /*node*/) -> void {
+auto HandleTupleLiteral(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
+                        SemIR::TupleLiteral /*inst*/) -> void {
   // A TupleLiteral should always be converted to a TupleInit or TupleValue if
   // its value is needed.
 }
 
-auto HandleTupleInit(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::TupleInit node) -> void {
-  auto* llvm_type = context.GetType(node.type_id);
+auto HandleTupleInit(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::TupleInit inst) -> void {
+  auto* llvm_type = context.GetType(inst.type_id);
 
-  switch (SemIR::GetInitializingRepresentation(context.sem_ir(), node.type_id)
+  switch (SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
               .kind) {
     case SemIR::InitializingRepresentation::None:
     case SemIR::InitializingRepresentation::InPlace:
       // TODO: Add a helper to poison a value slot.
-      context.SetLocal(node_id, llvm::PoisonValue::get(llvm_type));
+      context.SetLocal(inst_id, llvm::PoisonValue::get(llvm_type));
       break;
 
     case SemIR::InitializingRepresentation::ByCopy: {
       context.SetLocal(
-          node_id, EmitStructOrTupleValueRepresentation(
-                       context, node.type_id, node.elements_id, "tuple.init"));
+          inst_id, EmitStructOrTupleValueRepresentation(
+                       context, inst.type_id, inst.elements_id, "tuple.init"));
       break;
     }
   }
 }
 
-auto HandleTupleValue(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::TupleValue node) -> void {
+auto HandleTupleValue(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::TupleValue inst) -> void {
   context.SetLocal(
-      node_id, EmitStructOrTupleValueRepresentation(context, node.type_id,
-                                                    node.elements_id, "tuple"));
+      inst_id, EmitStructOrTupleValueRepresentation(context, inst.type_id,
+                                                    inst.elements_id, "tuple"));
 }
 
-auto HandleUnaryOperatorNot(FunctionContext& context, SemIR::NodeId node_id,
-                            SemIR::UnaryOperatorNot node) -> void {
+auto HandleUnaryOperatorNot(FunctionContext& context, SemIR::InstId inst_id,
+                            SemIR::UnaryOperatorNot inst) -> void {
   context.SetLocal(
-      node_id, context.builder().CreateNot(context.GetLocal(node.operand_id)));
+      inst_id, context.builder().CreateNot(context.GetLocal(inst.operand_id)));
 }
 
-auto HandleVarStorage(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::VarStorage node) -> void {
+auto HandleVarStorage(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::VarStorage inst) -> void {
   // TODO: Eventually this name will be optional, and we'll want to provide
   // something like `var` as a default. However, that's not possible right now
   // so cannot be tested.
-  auto name = context.sem_ir().strings().Get(node.name_id);
-  auto* alloca = context.builder().CreateAlloca(context.GetType(node.type_id),
+  auto name = context.sem_ir().strings().Get(inst.name_id);
+  auto* alloca = context.builder().CreateAlloca(context.GetType(inst.type_id),
                                                 /*ArraySize=*/nullptr, name);
-  context.SetLocal(node_id, alloca);
+  context.SetLocal(inst_id, alloca);
 }
 
 }  // namespace Carbon::Lower

+ 28 - 28
toolchain/lower/handle_expression_category.cpp

@@ -7,10 +7,10 @@
 
 namespace Carbon::Lower {
 
-auto HandleBindValue(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::BindValue node) -> void {
+auto HandleBindValue(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::BindValue inst) -> void {
   switch (auto rep =
-              SemIR::GetValueRepresentation(context.sem_ir(), node.type_id);
+              SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id);
           rep.kind) {
     case SemIR::ValueRepresentation::Unknown:
       CARBON_FATAL()
@@ -19,56 +19,56 @@ auto HandleBindValue(FunctionContext& context, SemIR::NodeId node_id,
       // Nothing should use this value, but StubReference needs a value to
       // propagate.
       // TODO: Remove this now the StubReferences are gone.
-      context.SetLocal(node_id,
-                       llvm::PoisonValue::get(context.GetType(node.type_id)));
+      context.SetLocal(inst_id,
+                       llvm::PoisonValue::get(context.GetType(inst.type_id)));
       break;
     case SemIR::ValueRepresentation::Copy:
-      context.SetLocal(node_id, context.builder().CreateLoad(
-                                    context.GetType(node.type_id),
-                                    context.GetLocal(node.value_id)));
+      context.SetLocal(inst_id, context.builder().CreateLoad(
+                                    context.GetType(inst.type_id),
+                                    context.GetLocal(inst.value_id)));
       break;
     case SemIR::ValueRepresentation::Pointer:
-      context.SetLocal(node_id, context.GetLocal(node.value_id));
+      context.SetLocal(inst_id, context.GetLocal(inst.value_id));
       break;
     case SemIR::ValueRepresentation::Custom:
       CARBON_FATAL() << "TODO: Add support for BindValue with custom value rep";
   }
 }
 
-auto HandleTemporary(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::Temporary node) -> void {
-  context.FinishInitialization(node.type_id, node.storage_id, node.init_id);
-  context.SetLocal(node_id, context.GetLocal(node.storage_id));
+auto HandleTemporary(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::Temporary inst) -> void {
+  context.FinishInitialization(inst.type_id, inst.storage_id, inst.init_id);
+  context.SetLocal(inst_id, context.GetLocal(inst.storage_id));
 }
 
-auto HandleTemporaryStorage(FunctionContext& context, SemIR::NodeId node_id,
-                            SemIR::TemporaryStorage node) -> void {
-  context.SetLocal(node_id,
-                   context.builder().CreateAlloca(context.GetType(node.type_id),
+auto HandleTemporaryStorage(FunctionContext& context, SemIR::InstId inst_id,
+                            SemIR::TemporaryStorage inst) -> void {
+  context.SetLocal(inst_id,
+                   context.builder().CreateAlloca(context.GetType(inst.type_id),
                                                   nullptr, "temp"));
 }
 
-auto HandleValueAsReference(FunctionContext& context, SemIR::NodeId node_id,
-                            SemIR::ValueAsReference node) -> void {
-  CARBON_CHECK(SemIR::GetExpressionCategory(context.sem_ir(), node.value_id) ==
+auto HandleValueAsReference(FunctionContext& context, SemIR::InstId inst_id,
+                            SemIR::ValueAsReference inst) -> void {
+  CARBON_CHECK(SemIR::GetExpressionCategory(context.sem_ir(), inst.value_id) ==
                SemIR::ExpressionCategory::Value);
   CARBON_CHECK(
-      SemIR::GetValueRepresentation(context.sem_ir(), node.type_id).kind ==
+      SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id).kind ==
       SemIR::ValueRepresentation::Pointer);
-  context.SetLocal(node_id, context.GetLocal(node.value_id));
+  context.SetLocal(inst_id, context.GetLocal(inst.value_id));
 }
 
-auto HandleValueOfInitializer(FunctionContext& context, SemIR::NodeId node_id,
-                              SemIR::ValueOfInitializer node) -> void {
-  CARBON_CHECK(SemIR::GetExpressionCategory(context.sem_ir(), node.init_id) ==
+auto HandleValueOfInitializer(FunctionContext& context, SemIR::InstId inst_id,
+                              SemIR::ValueOfInitializer inst) -> void {
+  CARBON_CHECK(SemIR::GetExpressionCategory(context.sem_ir(), inst.init_id) ==
                SemIR::ExpressionCategory::Initializing);
   CARBON_CHECK(
-      SemIR::GetValueRepresentation(context.sem_ir(), node.type_id).kind ==
+      SemIR::GetValueRepresentation(context.sem_ir(), inst.type_id).kind ==
       SemIR::ValueRepresentation::Copy);
   CARBON_CHECK(
-      SemIR::GetInitializingRepresentation(context.sem_ir(), node.type_id)
+      SemIR::GetInitializingRepresentation(context.sem_ir(), inst.type_id)
           .kind == SemIR::InitializingRepresentation::ByCopy);
-  context.SetLocal(node_id, context.GetLocal(node.init_id));
+  context.SetLocal(inst_id, context.GetLocal(inst.init_id));
 }
 
 }  // namespace Carbon::Lower

+ 21 - 21
toolchain/lower/handle_type.cpp

@@ -6,39 +6,39 @@
 
 namespace Carbon::Lower {
 
-auto HandleArrayType(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::ArrayType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleArrayType(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::ArrayType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleClassType(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::ClassType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleClassType(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::ClassType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleConstType(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::ConstType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleConstType(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::ConstType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandlePointerType(FunctionContext& context, SemIR::NodeId node_id,
-                       SemIR::PointerType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandlePointerType(FunctionContext& context, SemIR::InstId inst_id,
+                       SemIR::PointerType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleStructType(FunctionContext& context, SemIR::NodeId node_id,
-                      SemIR::StructType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleStructType(FunctionContext& context, SemIR::InstId inst_id,
+                      SemIR::StructType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleTupleType(FunctionContext& context, SemIR::NodeId node_id,
-                     SemIR::TupleType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleTupleType(FunctionContext& context, SemIR::InstId inst_id,
+                     SemIR::TupleType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
-auto HandleUnboundFieldType(FunctionContext& context, SemIR::NodeId node_id,
-                            SemIR::UnboundFieldType /*node*/) -> void {
-  context.SetLocal(node_id, context.GetTypeAsValue());
+auto HandleUnboundFieldType(FunctionContext& context, SemIR::InstId inst_id,
+                            SemIR::UnboundFieldType /*inst*/) -> void {
+  context.SetLocal(inst_id, context.GetTypeAsValue());
 }
 
 }  // namespace Carbon::Lower

+ 13 - 13
toolchain/sem_ir/BUILD

@@ -26,11 +26,11 @@ cc_library(
 )
 
 cc_library(
-    name = "node_kind",
+    name = "inst_kind",
     srcs = ["node_kind.cpp"],
     hdrs = [
         "node_kind.h",
-        "typed_nodes.h",
+        "typed_insts.h",
     ],
     textual_hdrs = ["node_kind.def"],
     deps = [
@@ -43,12 +43,12 @@ cc_library(
 )
 
 cc_library(
-    name = "node",
-    srcs = ["node.cpp"],
-    hdrs = ["node.h"],
+    name = "inst",
+    srcs = ["inst.cpp"],
+    hdrs = ["inst.h"],
     deps = [
         ":builtin_kind",
-        ":node_kind",
+        ":inst_kind",
         "//common:check",
         "//common:ostream",
         "//common:struct_reflection",
@@ -64,8 +64,8 @@ cc_library(
     hdrs = ["file.h"],
     deps = [
         ":builtin_kind",
-        ":node",
-        ":node_kind",
+        ":inst",
+        ":inst_kind",
         ":value_stores",
         "//common:check",
         "//toolchain/base:value_store",
@@ -80,7 +80,7 @@ cc_library(
     hdrs = ["formatter.h"],
     deps = [
         ":file",
-        ":node_kind",
+        ":inst_kind",
         "//toolchain/lex:tokenized_buffer",
         "//toolchain/parse:tree",
         "@llvm-project//llvm:Support",
@@ -101,7 +101,7 @@ cc_library(
     name = "value_stores",
     hdrs = ["value_stores.h"],
     deps = [
-        ":node",
+        ":inst",
         "//toolchain/base:value_store",
         "//toolchain/base:yaml",
         "@llvm-project//llvm:Support",
@@ -109,12 +109,12 @@ cc_library(
 )
 
 cc_test(
-    name = "typed_nodes_test",
+    name = "typed_insts_test",
     size = "small",
     srcs = ["typed_nodes_test.cpp"],
     deps = [
-        ":node",
-        ":node_kind",
+        ":inst",
+        ":inst_kind",
         "//testing/base:gtest_main",
         "@com_google_googletest//:gtest",
     ],

+ 1 - 1
toolchain/sem_ir/builtin_kind.def

@@ -40,7 +40,7 @@
 // This has a deliberately self-referential type.
 CARBON_SEM_IR_BUILTIN_KIND(TypeType, "type")
 
-// Used when a semantic error has been detected, and a SemanticNodeId is still
+// Used when a semantic error has been detected, and a SemIR InstId is still
 // required. For example, when there is a type checking issue, this will be used
 // in the type_id. It's typically used as a cue that semantic checking doesn't
 // need to issue further diagnostics.

+ 1 - 1
toolchain/sem_ir/builtin_kind.h

@@ -30,7 +30,7 @@ class BuiltinKind : public CARBON_ENUM_BASE(BuiltinKind) {
   // constant.
   static const uint8_t ValidCount;
 
-  // Support conversion to and from an int32_t for SemanticNode storage.
+  // Support conversion to and from an int32_t for SemIR instruction storage.
   using EnumBase::AsInt;
   using EnumBase::FromInt;
 };

+ 90 - 89
toolchain/sem_ir/file.cpp

@@ -10,7 +10,7 @@
 #include "toolchain/base/value_store.h"
 #include "toolchain/base/yaml.h"
 #include "toolchain/sem_ir/builtin_kind.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/node_kind.h"
 
 namespace Carbon::SemIR {
@@ -38,7 +38,7 @@ auto ValueRepresentation::Print(llvm::raw_ostream& out) const -> void {
 }
 
 auto TypeInfo::Print(llvm::raw_ostream& out) const -> void {
-  out << "{node: " << node_id << ", value_rep: " << value_representation << "}";
+  out << "{inst: " << inst_id << ", value_rep: " << value_representation << "}";
 }
 
 File::File(SharedValueStores& value_stores)
@@ -47,25 +47,25 @@ File::File(SharedValueStores& value_stores)
       // Builtins are always the first IR, even when self-referential.
       cross_reference_irs_({this}),
       type_blocks_(allocator_),
-      node_blocks_(allocator_) {
-  // Default entry for NodeBlockId::Empty.
-  node_blocks_.AddDefaultValue();
+      inst_blocks_(allocator_) {
+  // Default entry for InstBlockId::Empty.
+  inst_blocks_.AddDefaultValue();
 
-  nodes_.Reserve(BuiltinKind::ValidCount);
+  insts_.Reserve(BuiltinKind::ValidCount);
 
   // Error uses a self-referential type so that it's not accidentally treated as
   // a normal type. Every other builtin is a type, including the
   // self-referential TypeType.
 #define CARBON_SEM_IR_BUILTIN_KIND(Name, ...)                         \
-  nodes_.AddInNoBlock(Builtin{BuiltinKind::Name == BuiltinKind::Error \
+  insts_.AddInNoBlock(Builtin{BuiltinKind::Name == BuiltinKind::Error \
                                   ? TypeId::Error                     \
                                   : TypeId::TypeType,                 \
                               BuiltinKind::Name});
 #include "toolchain/sem_ir/builtin_kind.def"
 
-  CARBON_CHECK(nodes_.size() == BuiltinKind::ValidCount)
+  CARBON_CHECK(insts_.size() == BuiltinKind::ValidCount)
       << "Builtins should produce " << BuiltinKind::ValidCount
-      << " nodes, actual: " << nodes_.size();
+      << " insts, actual: " << insts_.size();
 }
 
 File::File(SharedValueStores& value_stores, std::string filename,
@@ -75,21 +75,21 @@ File::File(SharedValueStores& value_stores, std::string filename,
       // Builtins are always the first IR.
       cross_reference_irs_({builtins}),
       type_blocks_(allocator_),
-      node_blocks_(allocator_) {
+      inst_blocks_(allocator_) {
   CARBON_CHECK(builtins != nullptr);
   CARBON_CHECK(builtins->cross_reference_irs_[0] == builtins)
       << "Not called with builtins!";
 
-  // Default entry for NodeBlockId::Empty.
-  node_blocks_.AddDefaultValue();
+  // Default entry for InstBlockId::Empty.
+  inst_blocks_.AddDefaultValue();
 
   // Copy builtins over.
-  nodes_.Reserve(BuiltinKind::ValidCount);
+  insts_.Reserve(BuiltinKind::ValidCount);
   static constexpr auto BuiltinIR = CrossReferenceIRId(0);
-  for (auto [i, node] : llvm::enumerate(builtins->nodes_.array_ref())) {
+  for (auto [i, inst] : llvm::enumerate(builtins->insts_.array_ref())) {
     // We can reuse builtin type IDs because they're special-cased values.
-    nodes_.AddInNoBlock(
-        CrossReference{node.type_id(), BuiltinIR, SemIR::NodeId(i)});
+    insts_.AddInNoBlock(
+        CrossReference{inst.type_id(), BuiltinIR, SemIR::InstId(i)});
   }
 }
 
@@ -102,22 +102,22 @@ auto File::Verify() const -> ErrorOr<Success> {
   // Check that every code block has a terminator sequence that appears at the
   // end of the block.
   for (const Function& function : functions_.array_ref()) {
-    for (NodeBlockId block_id : function.body_block_ids) {
+    for (InstBlockId block_id : function.body_block_ids) {
       TerminatorKind prior_kind = TerminatorKind::NotTerminator;
-      for (NodeId node_id : node_blocks().Get(block_id)) {
-        TerminatorKind node_kind =
-            nodes().Get(node_id).kind().terminator_kind();
+      for (InstId inst_id : inst_blocks().Get(block_id)) {
+        TerminatorKind inst_kind =
+            insts().Get(inst_id).kind().terminator_kind();
         if (prior_kind == TerminatorKind::Terminator) {
-          return Error(llvm::formatv("Node {0} in block {1} follows terminator",
-                                     node_id, block_id));
+          return Error(llvm::formatv("Inst {0} in block {1} follows terminator",
+                                     inst_id, block_id));
         }
-        if (prior_kind > node_kind) {
+        if (prior_kind > inst_kind) {
           return Error(
-              llvm::formatv("Non-terminator node {0} in block {1} follows "
+              llvm::formatv("Non-terminator inst {0} in block {1} follows "
                             "terminator sequence",
-                            node_id, block_id));
+                            inst_id, block_id));
         }
-        prior_kind = node_kind;
+        prior_kind = inst_kind;
       }
       if (prior_kind != TerminatorKind::Terminator) {
         return Error(llvm::formatv("No terminator in block {0}", block_id));
@@ -125,8 +125,8 @@ auto File::Verify() const -> ErrorOr<Success> {
     }
   }
 
-  // TODO: Check that a node only references other nodes that are either global
-  // or that dominate it.
+  // TODO: Check that an instruction only references other instructions that are
+  // either global or that dominate it.
   return Success();
 }
 
@@ -141,25 +141,25 @@ auto File::OutputYaml(bool include_builtins) const -> Yaml::OutputMapping {
               map.Add("classes", classes_.OutputYaml());
               map.Add("types", types_.OutputYaml());
               map.Add("type_blocks", type_blocks_.OutputYaml());
-              map.Add("nodes",
+              map.Add("insts",
                       Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
                         int start =
                             include_builtins ? 0 : BuiltinKind::ValidCount;
-                        for (int i : llvm::seq(start, nodes_.size())) {
-                          auto id = NodeId(i);
+                        for (int i : llvm::seq(start, insts_.size())) {
+                          auto id = InstId(i);
                           map.Add(PrintToString(id),
-                                  Yaml::OutputScalar(nodes_.Get(id)));
+                                  Yaml::OutputScalar(insts_.Get(id)));
                         }
                       }));
-              map.Add("node_blocks", node_blocks_.OutputYaml());
+              map.Add("inst_blocks", inst_blocks_.OutputYaml());
             }));
   });
 }
 
-// Map a node kind representing a type into an integer describing the
+// Map an instruction kind representing a type into an integer describing the
 // precedence of that type's syntax. Higher numbers correspond to higher
 // precedence.
-static auto GetTypePrecedence(NodeKind kind) -> int {
+static auto GetTypePrecedence(InstKind kind) -> int {
   // clang warns on unhandled enum values; clang-tidy is incorrect here.
   // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
   switch (kind) {
@@ -228,7 +228,7 @@ static auto GetTypePrecedence(NodeKind kind) -> int {
     case ValueAsReference::Kind:
     case ValueOfInitializer::Kind:
     case VarStorage::Kind:
-      CARBON_FATAL() << "GetTypePrecedence for non-type node kind " << kind;
+      CARBON_FATAL() << "GetTypePrecedence for non-type inst kind " << kind;
   }
 }
 
@@ -238,47 +238,47 @@ auto File::StringifyType(TypeId type_id, bool in_type_context) const
                                  in_type_context);
 }
 
-auto File::StringifyTypeExpression(NodeId outer_node_id,
+auto File::StringifyTypeExpression(InstId outer_inst_id,
                                    bool in_type_context) const -> std::string {
   std::string str;
   llvm::raw_string_ostream out(str);
 
   struct Step {
-    // The node to print.
-    NodeId node_id;
-    // The index into node_id to print. Not used by all types.
+    // The instruction to print.
+    InstId inst_id;
+    // The index into inst_id to print. Not used by all types.
     int index = 0;
 
     auto Next() const -> Step {
-      return {.node_id = node_id, .index = index + 1};
+      return {.inst_id = inst_id, .index = index + 1};
     }
   };
-  llvm::SmallVector<Step> steps = {{.node_id = outer_node_id}};
+  llvm::SmallVector<Step> steps = {{.inst_id = outer_inst_id}};
 
   while (!steps.empty()) {
     auto step = steps.pop_back_val();
-    if (!step.node_id.is_valid()) {
+    if (!step.inst_id.is_valid()) {
       out << "<invalid type>";
       continue;
     }
 
     // Builtins have designated labels.
-    if (step.node_id.index < BuiltinKind::ValidCount) {
-      out << BuiltinKind::FromInt(step.node_id.index).label();
+    if (step.inst_id.index < BuiltinKind::ValidCount) {
+      out << BuiltinKind::FromInt(step.inst_id.index).label();
       continue;
     }
 
-    auto node = nodes().Get(step.node_id);
+    auto inst = insts().Get(step.inst_id);
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (node.kind()) {
+    switch (inst.kind()) {
       case ArrayType::Kind: {
-        auto array = node.As<ArrayType>();
+        auto array = inst.As<ArrayType>();
         if (step.index == 0) {
           out << "[";
           steps.push_back(step.Next());
           steps.push_back(
-              {.node_id = GetTypeAllowBuiltinTypes(array.element_type_id)});
+              {.inst_id = GetTypeAllowBuiltinTypes(array.element_type_id)});
         } else if (step.index == 1) {
           out << "; " << GetArrayBoundValue(array.bound_id) << "]";
         }
@@ -286,7 +286,7 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
       }
       case ClassType::Kind: {
         auto class_name_id =
-            classes().Get(node.As<ClassType>().class_id).name_id;
+            classes().Get(inst.As<ClassType>().class_id).name_id;
         out << strings().Get(class_name_id);
         break;
       }
@@ -295,36 +295,36 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
           out << "const ";
 
           // Add parentheses if required.
-          auto inner_type_node_id =
-              GetTypeAllowBuiltinTypes(node.As<ConstType>().inner_id);
-          if (GetTypePrecedence(nodes().Get(inner_type_node_id).kind()) <
-              GetTypePrecedence(node.kind())) {
+          auto inner_type_inst_id =
+              GetTypeAllowBuiltinTypes(inst.As<ConstType>().inner_id);
+          if (GetTypePrecedence(insts().Get(inner_type_inst_id).kind()) <
+              GetTypePrecedence(inst.kind())) {
             out << "(";
             steps.push_back(step.Next());
           }
 
-          steps.push_back({.node_id = inner_type_node_id});
+          steps.push_back({.inst_id = inner_type_inst_id});
         } else if (step.index == 1) {
           out << ")";
         }
         break;
       }
       case NameReference::Kind: {
-        out << strings().Get(node.As<NameReference>().name_id);
+        out << strings().Get(inst.As<NameReference>().name_id);
         break;
       }
       case PointerType::Kind: {
         if (step.index == 0) {
           steps.push_back(step.Next());
-          steps.push_back({.node_id = GetTypeAllowBuiltinTypes(
-                               node.As<PointerType>().pointee_id)});
+          steps.push_back({.inst_id = GetTypeAllowBuiltinTypes(
+                               inst.As<PointerType>().pointee_id)});
         } else if (step.index == 1) {
           out << "*";
         }
         break;
       }
       case StructType::Kind: {
-        auto refs = node_blocks().Get(node.As<StructType>().fields_id);
+        auto refs = inst_blocks().Get(inst.As<StructType>().fields_id);
         if (refs.empty()) {
           out << "{}";
           break;
@@ -338,18 +338,18 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
         }
 
         steps.push_back(step.Next());
-        steps.push_back({.node_id = refs[step.index]});
+        steps.push_back({.inst_id = refs[step.index]});
         break;
       }
       case StructTypeField::Kind: {
-        auto field = node.As<StructTypeField>();
+        auto field = inst.As<StructTypeField>();
         out << "." << strings().Get(field.name_id) << ": ";
         steps.push_back(
-            {.node_id = GetTypeAllowBuiltinTypes(field.field_type_id)});
+            {.inst_id = GetTypeAllowBuiltinTypes(field.field_type_id)});
         break;
       }
       case TupleType::Kind: {
-        auto refs = type_blocks().Get(node.As<TupleType>().elements_id);
+        auto refs = type_blocks().Get(inst.As<TupleType>().elements_id);
         if (refs.empty()) {
           out << "()";
           break;
@@ -368,15 +368,15 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
         }
         steps.push_back(step.Next());
         steps.push_back(
-            {.node_id = GetTypeAllowBuiltinTypes(refs[step.index])});
+            {.inst_id = GetTypeAllowBuiltinTypes(refs[step.index])});
         break;
       }
       case UnboundFieldType::Kind: {
         if (step.index == 0) {
           out << "<unbound field of class ";
           steps.push_back(step.Next());
-          steps.push_back({.node_id = GetTypeAllowBuiltinTypes(
-                               node.As<UnboundFieldType>().class_type_id)});
+          steps.push_back({.inst_id = GetTypeAllowBuiltinTypes(
+                               inst.As<UnboundFieldType>().class_type_id)});
         } else {
           out << ">";
         }
@@ -429,10 +429,10 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
       case ValueAsReference::Kind:
       case ValueOfInitializer::Kind:
       case VarStorage::Kind:
-        // We don't need to handle stringification for nodes that don't show up
-        // in errors, but make it clear what's going on so that it's clearer
-        // when stringification is needed.
-        out << "<cannot stringify " << step.node_id << ">";
+        // We don't need to handle stringification for instructions that don't
+        // show up in errors, but make it clear what's going on so that it's
+        // clearer when stringification is needed.
+        out << "<cannot stringify " << step.inst_id << ">";
         break;
     }
   }
@@ -440,10 +440,10 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
   // For `{}` or any tuple type, we've printed a non-type expression, so add a
   // conversion to type `type` if it's not implied by the context.
   if (!in_type_context) {
-    auto outer_node = nodes().Get(outer_node_id);
-    if (outer_node.Is<TupleType>() ||
-        (outer_node.Is<StructType>() &&
-         node_blocks().Get(outer_node.As<StructType>().fields_id).empty())) {
+    auto outer_inst = insts().Get(outer_inst_id);
+    if (outer_inst.Is<TupleType>() ||
+        (outer_inst.Is<StructType>() &&
+         inst_blocks().Get(outer_inst.As<StructType>().fields_id).empty())) {
       out << " as type";
     }
   }
@@ -451,18 +451,19 @@ auto File::StringifyTypeExpression(NodeId outer_node_id,
   return str;
 }
 
-auto GetExpressionCategory(const File& file, NodeId node_id)
+auto GetExpressionCategory(const File& file, InstId inst_id)
     -> ExpressionCategory {
   const File* ir = &file;
 
-  // The overall expression category if the current node is a value expression.
+  // The overall expression category if the current instruction is a value
+  // expression.
   ExpressionCategory value_category = ExpressionCategory::Value;
 
   while (true) {
-    auto node = ir->nodes().Get(node_id);
+    auto inst = ir->insts().Get(inst_id);
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (node.kind()) {
+    switch (inst.kind()) {
       case Assign::Kind:
       case Branch::Kind:
       case BranchIf::Kind:
@@ -478,14 +479,14 @@ auto GetExpressionCategory(const File& file, NodeId node_id)
         return ExpressionCategory::NotExpression;
 
       case CrossReference::Kind: {
-        auto xref = node.As<CrossReference>();
+        auto xref = inst.As<CrossReference>();
         ir = &ir->GetCrossReferenceIR(xref.ir_id);
-        node_id = xref.node_id;
+        inst_id = xref.inst_id;
         continue;
       }
 
       case NameReference::Kind: {
-        node_id = node.As<NameReference>().value_id;
+        inst_id = inst.As<NameReference>().value_id;
         continue;
       }
 
@@ -514,24 +515,24 @@ auto GetExpressionCategory(const File& file, NodeId node_id)
         return value_category;
 
       case Builtin::Kind: {
-        if (node.As<Builtin>().builtin_kind == BuiltinKind::Error) {
+        if (inst.As<Builtin>().builtin_kind == BuiltinKind::Error) {
           return ExpressionCategory::Error;
         }
         return value_category;
       }
 
       case BindName::Kind: {
-        node_id = node.As<BindName>().value_id;
+        inst_id = inst.As<BindName>().value_id;
         continue;
       }
 
       case ArrayIndex::Kind: {
-        node_id = node.As<ArrayIndex>().array_id;
+        inst_id = inst.As<ArrayIndex>().array_id;
         continue;
       }
 
       case ClassFieldAccess::Kind: {
-        node_id = node.As<ClassFieldAccess>().base_id;
+        inst_id = inst.As<ClassFieldAccess>().base_id;
         // A value of class type is a pointer to an object representation.
         // Therefore, if the base is a value, the result is an ephemeral
         // reference.
@@ -540,22 +541,22 @@ auto GetExpressionCategory(const File& file, NodeId node_id)
       }
 
       case StructAccess::Kind: {
-        node_id = node.As<StructAccess>().struct_id;
+        inst_id = inst.As<StructAccess>().struct_id;
         continue;
       }
 
       case TupleAccess::Kind: {
-        node_id = node.As<TupleAccess>().tuple_id;
+        inst_id = inst.As<TupleAccess>().tuple_id;
         continue;
       }
 
       case TupleIndex::Kind: {
-        node_id = node.As<TupleIndex>().tuple_id;
+        inst_id = inst.As<TupleIndex>().tuple_id;
         continue;
       }
 
       case SpliceBlock::Kind: {
-        node_id = node.As<SpliceBlock>().result_id;
+        inst_id = inst.As<SpliceBlock>().result_id;
         continue;
       }
 

+ 56 - 54
toolchain/sem_ir/file.h

@@ -11,7 +11,7 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "toolchain/base/value_store.h"
 #include "toolchain/base/yaml.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 #include "toolchain/sem_ir/value_stores.h"
 
 namespace Carbon::SemIR {
@@ -39,11 +39,11 @@ struct Function : public Printable<Function> {
   StringId name_id;
   // The definition, if the function has been defined or is currently being
   // defined. This is a FunctionDeclaration.
-  NodeId definition_id = NodeId::Invalid;
-  // A block containing a single reference node per implicit parameter.
-  NodeBlockId implicit_param_refs_id;
-  // A block containing a single reference node per parameter.
-  NodeBlockId param_refs_id;
+  InstId definition_id = InstId::Invalid;
+  // A block containing a single reference instruction per implicit parameter.
+  InstBlockId implicit_param_refs_id;
+  // A block containing a single reference instruction per parameter.
+  InstBlockId param_refs_id;
   // The return type. This will be invalid if the return type wasn't specified.
   TypeId return_type_id;
   // The storage for the return value, which is a reference expression whose
@@ -51,11 +51,11 @@ struct Function : public Printable<Function> {
   // doesn't have a return slot. If this is valid, a call to the function is
   // expected to have an additional final argument corresponding to the return
   // slot.
-  NodeId return_slot_id;
+  InstId return_slot_id;
   // A list of the statically reachable code blocks in the body of the
   // function, in lexical order. The first block is the entry block. This will
   // be empty for declarations that don't have a visible definition.
-  llvm::SmallVector<NodeBlockId> body_block_ids = {};
+  llvm::SmallVector<InstBlockId> body_block_ids = {};
 };
 
 // A class.
@@ -77,17 +77,17 @@ struct Class : public Printable<Class> {
   // The class type, which is the type of `Self` in the class definition.
   TypeId self_type_id;
   // The first declaration of the class. This is a ClassDeclaration.
-  NodeId declaration_id = NodeId::Invalid;
+  InstId declaration_id = InstId::Invalid;
 
   // The following members are set at the `{` of the class definition.
 
   // The definition of the class. This is a ClassDeclaration.
-  NodeId definition_id = NodeId::Invalid;
+  InstId definition_id = InstId::Invalid;
   // The class scope.
   NameScopeId scope_id = NameScopeId::Invalid;
   // The first block of the class body.
   // TODO: Handle control flow in the class body, such as if-expressions.
-  NodeBlockId body_block_id = NodeBlockId::Invalid;
+  InstBlockId body_block_id = InstBlockId::Invalid;
 
   // The following members are set at the `}` of the class definition.
 
@@ -152,8 +152,8 @@ struct ValueRepresentation : public Printable<ValueRepresentation> {
 struct TypeInfo : public Printable<TypeInfo> {
   auto Print(llvm::raw_ostream& out) const -> void;
 
-  // The node that defines this type.
-  NodeId node_id;
+  // The instruction that defines this type.
+  InstId inst_id;
   // The value representation for this type. Will be `Unknown` if the type is
   // not complete.
   ValueRepresentation value_representation = ValueRepresentation();
@@ -183,10 +183,10 @@ class File : public Printable<File> {
   }
   auto OutputYaml(bool include_builtins) const -> Yaml::OutputMapping;
 
-  // Returns array bound value from the bound node.
-  auto GetArrayBoundValue(NodeId bound_id) const -> uint64_t {
+  // Returns array bound value from the bound instruction.
+  auto GetArrayBoundValue(InstId bound_id) const -> uint64_t {
     return integers()
-        .Get(nodes().GetAs<IntegerLiteral>(bound_id).integer_id)
+        .Get(insts().GetAs<IntegerLiteral>(bound_id).integer_id)
         .getZExtValue();
   }
 
@@ -209,15 +209,15 @@ class File : public Printable<File> {
     complete_types_.push_back(object_type_id);
   }
 
-  auto GetTypeAllowBuiltinTypes(TypeId type_id) const -> NodeId {
+  auto GetTypeAllowBuiltinTypes(TypeId type_id) const -> InstId {
     if (type_id == TypeId::TypeType) {
-      return NodeId::BuiltinTypeType;
+      return InstId::BuiltinTypeType;
     } else if (type_id == TypeId::Error) {
-      return NodeId::BuiltinError;
+      return InstId::BuiltinError;
     } else if (type_id == TypeId::Invalid) {
-      return NodeId::Invalid;
+      return InstId::Invalid;
     } else {
-      return types().Get(type_id).node_id;
+      return types().Get(type_id).inst_id;
     }
   }
 
@@ -239,8 +239,8 @@ class File : public Printable<File> {
 
   // Gets the pointee type of the given type, which must be a pointer type.
   auto GetPointeeType(TypeId pointer_id) const -> TypeId {
-    return nodes()
-        .GetAs<PointerType>(types().Get(pointer_id).node_id)
+    return insts()
+        .GetAs<PointerType>(types().Get(pointer_id).inst_id)
         .pointee_id;
   }
 
@@ -251,9 +251,9 @@ class File : public Printable<File> {
   auto StringifyType(TypeId type_id, bool in_type_context = false) const
       -> std::string;
 
-  // Same as `StringifyType`, but starting with a node representing a type
-  // expression rather than a canonical type.
-  auto StringifyTypeExpression(NodeId outer_node_id,
+  // Same as `StringifyType`, but starting with an instruction representing a
+  // type expression rather than a canonical type.
+  auto StringifyTypeExpression(InstId outer_inst_id,
                                bool in_type_context = false) const
       -> std::string;
 
@@ -289,10 +289,10 @@ class File : public Printable<File> {
   auto type_blocks() const -> const BlockValueStore<TypeBlockId, TypeId>& {
     return type_blocks_;
   }
-  auto nodes() -> NodeStore& { return nodes_; }
-  auto nodes() const -> const NodeStore& { return nodes_; }
-  auto node_blocks() -> NodeBlockStore& { return node_blocks_; }
-  auto node_blocks() const -> const NodeBlockStore& { return node_blocks_; }
+  auto insts() -> InstStore& { return insts_; }
+  auto insts() const -> const InstStore& { return insts_; }
+  auto inst_blocks() -> InstBlockStore& { return inst_blocks_; }
+  auto inst_blocks() const -> const InstBlockStore& { return inst_blocks_; }
 
   // A list of types that were completed in this file, in the order in which
   // they were completed. Earlier types in this list cannot contain instances of
@@ -301,9 +301,9 @@ class File : public Printable<File> {
     return complete_types_;
   }
 
-  auto top_node_block_id() const -> NodeBlockId { return top_node_block_id_; }
-  auto set_top_node_block_id(NodeBlockId block_id) -> void {
-    top_node_block_id_ = block_id;
+  auto top_inst_block_id() const -> InstBlockId { return top_inst_block_id_; }
+  auto set_top_inst_block_id(InstBlockId block_id) -> void {
+    top_inst_block_id_ = block_id;
   }
 
   // Returns true if there were errors creating the semantics IR.
@@ -318,7 +318,7 @@ class File : public Printable<File> {
   // Shared, compile-scoped values.
   SharedValueStores* value_stores_;
 
-  // Slab allocator, used to allocate node and type blocks.
+  // Slab allocator, used to allocate instruction and type blocks.
   llvm::BumpPtrAllocator allocator_;
 
   // The associated filename.
@@ -333,7 +333,7 @@ class File : public Printable<File> {
 
   // Related IRs. There will always be at least 2 entries, the builtin IR (used
   // for references of builtins) followed by the current IR (used for references
-  // crossing node blocks).
+  // crossing instruction blocks).
   llvm::SmallVector<const File*> cross_reference_irs_;
 
   // Storage for name scopes.
@@ -349,38 +349,40 @@ class File : public Printable<File> {
   // the data is provided by allocator_.
   BlockValueStore<TypeBlockId, TypeId> type_blocks_;
 
-  // All nodes. The first entries will always be cross-references to builtins,
-  // at indices matching BuiltinKind ordering.
-  NodeStore nodes_;
+  // All instructions. The first entries will always be cross-references to
+  // builtins, at indices matching BuiltinKind ordering.
+  InstStore insts_;
 
-  // Node blocks within the IR. These reference entries in nodes_. Storage for
-  // the data is provided by allocator_.
-  NodeBlockStore node_blocks_;
+  // Instruction blocks within the IR. These reference entries in
+  // insts_. Storage for the data is provided by allocator_.
+  InstBlockStore inst_blocks_;
 
-  // The top node block ID.
-  NodeBlockId top_node_block_id_ = NodeBlockId::Invalid;
+  // The top instruction block ID.
+  InstBlockId top_inst_block_id_ = InstBlockId::Invalid;
 };
 
-// The expression category of a semantics node. See /docs/design/values.md for
-// details.
+// The expression category of a sem_ir instruction. See /docs/design/values.md
+// for details.
 enum class ExpressionCategory : int8_t {
-  // This node does not correspond to an expression, and as such has no
+  // This instruction does not correspond to an expression, and as such has no
   // category.
   NotExpression,
-  // The category of this node is not known due to an error.
+  // The category of this instruction is not known due to an error.
   Error,
-  // This node represents a value expression.
+  // This instruction represents a value expression.
   Value,
-  // This node represents a durable reference expression, that denotes an
+  // This instruction represents a durable reference expression, that denotes an
   // object that outlives the current full expression context.
   DurableReference,
-  // This node represents an ephemeral reference expression, that denotes an
+  // This instruction represents an ephemeral reference expression, that denotes
+  // an
   // object that does not outlive the current full expression context.
   EphemeralReference,
-  // This node represents an initializing expression, that describes how to
+  // This instruction represents an initializing expression, that describes how
+  // to
   // initialize an object.
   Initializing,
-  // This node represents a syntactic combination of expressions that are
+  // This instruction represents a syntactic combination of expressions that are
   // permitted to have different expression categories. This is used for tuple
   // and struct literals, where the subexpressions for different elements can
   // have different categories.
@@ -388,8 +390,8 @@ enum class ExpressionCategory : int8_t {
   Last = Mixed
 };
 
-// Returns the expression category for a node.
-auto GetExpressionCategory(const File& file, NodeId node_id)
+// Returns the expression category for an instruction.
+auto GetExpressionCategory(const File& file, InstId inst_id)
     -> ExpressionCategory;
 
 // Returns information about the value representation to use for a type.

+ 168 - 167
toolchain/sem_ir/formatter.cpp

@@ -14,14 +14,14 @@
 namespace Carbon::SemIR {
 
 namespace {
-// Assigns names to nodes, blocks, and scopes in the Semantics IR.
+// Assigns names to instructions, blocks, and scopes in the Semantics IR.
 //
 // TODOs / future work ideas:
 // - Add a documentation file for the textual format and link to the
 //   naming section here.
 // - Consider representing literals as just `literal` in the IR and using the
 //   type to distinguish.
-class NodeNamer {
+class InstNamer {
  public:
   // int32_t matches the input value size.
   // NOLINTNEXTLINE(performance-enum-size)
@@ -31,18 +31,18 @@ class NodeNamer {
   };
   static_assert(sizeof(ScopeIndex) == sizeof(FunctionId));
 
-  NodeNamer(const Lex::TokenizedBuffer& tokenized_buffer,
+  InstNamer(const Lex::TokenizedBuffer& tokenized_buffer,
             const Parse::Tree& parse_tree, const File& sem_ir)
       : tokenized_buffer_(tokenized_buffer),
         parse_tree_(parse_tree),
         sem_ir_(sem_ir) {
-    nodes.resize(sem_ir.nodes().size());
-    labels.resize(sem_ir.node_blocks().size());
+    insts.resize(sem_ir.insts().size());
+    labels.resize(sem_ir.inst_blocks().size());
     scopes.resize(1 + sem_ir.functions().size() + sem_ir.classes().size());
 
     // Build the file scope.
     GetScopeInfo(ScopeIndex::File).name = globals.AddNameUnchecked("file");
-    CollectNamesInBlock(ScopeIndex::File, sem_ir.top_node_block_id());
+    CollectNamesInBlock(ScopeIndex::File, sem_ir.top_inst_block_id());
 
     // Build each function scope.
     for (auto [i, fn] : llvm::enumerate(sem_ir.functions().array_ref())) {
@@ -57,10 +57,10 @@ class NodeNamer {
       CollectNamesInBlock(fn_scope, fn.implicit_param_refs_id);
       CollectNamesInBlock(fn_scope, fn.param_refs_id);
       if (fn.return_slot_id.is_valid()) {
-        nodes[fn.return_slot_id.index] = {
+        insts[fn.return_slot_id.index] = {
             fn_scope,
-            GetScopeInfo(fn_scope).nodes.AllocateName(
-                *this, sem_ir.nodes().Get(fn.return_slot_id).parse_node(),
+            GetScopeInfo(fn_scope).insts.AllocateName(
+                *this, sem_ir.insts().Get(fn.return_slot_id).parse_node(),
                 "return")};
       }
       if (!fn.body_block_ids.empty()) {
@@ -118,30 +118,31 @@ class NodeNamer {
     return GetScopeInfo(GetScopeFor(class_id)).name.str();
   }
 
-  // Returns the IR name to use for a node, when referenced from a given scope.
-  auto GetNameFor(ScopeIndex scope_idx, NodeId node_id) -> std::string {
-    if (!node_id.is_valid()) {
+  // Returns the IR name to use for an instruction, when referenced from a given
+  // scope.
+  auto GetNameFor(ScopeIndex scope_idx, InstId inst_id) -> std::string {
+    if (!inst_id.is_valid()) {
       return "invalid";
     }
 
     // Check for a builtin.
-    if (node_id.index < BuiltinKind::ValidCount) {
-      return BuiltinKind::FromInt(node_id.index).label().str();
+    if (inst_id.index < BuiltinKind::ValidCount) {
+      return BuiltinKind::FromInt(inst_id.index).label().str();
     }
 
-    auto& [node_scope, node_name] = nodes[node_id.index];
-    if (!node_name) {
+    auto& [inst_scope, inst_name] = insts[inst_id.index];
+    if (!inst_name) {
       // This should not happen in valid IR.
-      return "<unexpected noderef " + llvm::itostr(node_id.index) + ">";
+      return "<unexpected instref " + llvm::itostr(inst_id.index) + ">";
     }
-    if (node_scope == scope_idx) {
-      return node_name.str().str();
+    if (inst_scope == scope_idx) {
+      return inst_name.str().str();
     }
-    return (GetScopeInfo(node_scope).name.str() + "." + node_name.str()).str();
+    return (GetScopeInfo(inst_scope).name.str() + "." + inst_name.str()).str();
   }
 
   // Returns the IR name to use for a label, when referenced from a given scope.
-  auto GetLabelFor(ScopeIndex scope_idx, NodeBlockId block_id) -> std::string {
+  auto GetLabelFor(ScopeIndex scope_idx, InstBlockId block_id) -> std::string {
     if (!block_id.is_valid()) {
       return "!invalid";
     }
@@ -149,7 +150,7 @@ class NodeNamer {
     auto& [label_scope, label_name] = labels[block_id.index];
     if (!label_name) {
       // This should not happen in valid IR.
-      return "<unexpected nodeblockref " + llvm::itostr(block_id.index) + ">";
+      return "<unexpected instblockref " + llvm::itostr(block_id.index) + ">";
     }
     if (label_scope == scope_idx) {
       return label_name.str().str();
@@ -203,10 +204,10 @@ class NodeNamer {
       return Name(allocated.insert({name, NameResult()}).first);
     }
 
-    auto AllocateName(const NodeNamer& namer, Parse::Node node,
+    auto AllocateName(const InstNamer& namer, Parse::Node node,
                       std::string name = "") -> Name {
-      // The best (shortest) name for this node so far, and the current name
-      // for it.
+      // The best (shortest) name for this instruction so far, and the current
+      // name for it.
       Name best;
       Name current;
 
@@ -217,8 +218,8 @@ class NodeNamer {
 
         if (!added) {
           if (mark_ambiguous) {
-            // This name was allocated for a different node. Mark it as
-            // ambiguous and keep looking for a name for this node.
+            // This name was allocated for a different instruction. Mark it as
+            // ambiguous and keep looking for a name for this instruction.
             new_name.SetAmbiguous();
           }
         } else {
@@ -269,7 +270,7 @@ class NodeNamer {
   // A named scope that contains named entities.
   struct Scope {
     Namespace::Name name;
-    Namespace nodes = {.prefix = "%"};
+    Namespace insts = {.prefix = "%"};
     Namespace labels = {.prefix = "!"};
   };
 
@@ -277,7 +278,7 @@ class NodeNamer {
     return scopes[static_cast<int>(scope_idx)];
   }
 
-  auto AddBlockLabel(ScopeIndex scope_idx, NodeBlockId block_id,
+  auto AddBlockLabel(ScopeIndex scope_idx, InstBlockId block_id,
                      std::string name = "",
                      Parse::Node parse_node = Parse::Node::Invalid) -> void {
     if (!block_id.is_valid() || labels[block_id.index].second) {
@@ -285,9 +286,9 @@ class NodeNamer {
     }
 
     if (parse_node == Parse::Node::Invalid) {
-      if (const auto& block = sem_ir_.node_blocks().Get(block_id);
+      if (const auto& block = sem_ir_.inst_blocks().Get(block_id);
           !block.empty()) {
-        parse_node = sem_ir_.nodes().Get(block.front()).parse_node();
+        parse_node = sem_ir_.insts().Get(block.front()).parse_node();
       }
     }
 
@@ -296,14 +297,14 @@ class NodeNamer {
                                   *this, parse_node, std::move(name))};
   }
 
-  // Finds and adds a suitable block label for the given semantics node that
+  // Finds and adds a suitable block label for the given SemIR instruction that
   // represents some kind of branch.
-  auto AddBlockLabel(ScopeIndex scope_idx, NodeBlockId block_id, Node node)
+  auto AddBlockLabel(ScopeIndex scope_idx, InstBlockId block_id, Inst inst)
       -> void {
     llvm::StringRef name;
-    switch (parse_tree_.node_kind(node.parse_node())) {
+    switch (parse_tree_.node_kind(inst.parse_node())) {
       case Parse::NodeKind::IfExpressionIf:
-        switch (node.kind()) {
+        switch (inst.kind()) {
           case BranchIf::Kind:
             name = "if.expr.then";
             break;
@@ -319,7 +320,7 @@ class NodeNamer {
         break;
 
       case Parse::NodeKind::IfCondition:
-        switch (node.kind()) {
+        switch (inst.kind()) {
           case BranchIf::Kind:
             name = "if.then";
             break;
@@ -336,9 +337,9 @@ class NodeNamer {
         break;
 
       case Parse::NodeKind::ShortCircuitOperand: {
-        bool is_rhs = node.Is<BranchIf>();
+        bool is_rhs = inst.Is<BranchIf>();
         bool is_and = tokenized_buffer_.GetKind(parse_tree_.node_token(
-                          node.parse_node())) == Lex::TokenKind::And;
+                          inst.parse_node())) == Lex::TokenKind::And;
         name = is_and ? (is_rhs ? "and.rhs" : "and.result")
                       : (is_rhs ? "or.rhs" : "or.result");
         break;
@@ -349,11 +350,11 @@ class NodeNamer {
         break;
 
       case Parse::NodeKind::WhileCondition:
-        switch (node.kind()) {
-          case NodeKind::BranchIf:
+        switch (inst.kind()) {
+          case InstKind::BranchIf:
             name = "while.body";
             break;
-          case NodeKind::Branch:
+          case InstKind::Branch:
             name = "while.done";
             break;
           default:
@@ -365,10 +366,10 @@ class NodeNamer {
         break;
     }
 
-    AddBlockLabel(scope_idx, block_id, name.str(), node.parse_node());
+    AddBlockLabel(scope_idx, block_id, name.str(), inst.parse_node());
   }
 
-  auto CollectNamesInBlock(ScopeIndex scope_idx, NodeBlockId block_id) -> void {
+  auto CollectNamesInBlock(ScopeIndex scope_idx, InstBlockId block_id) -> void {
     if (!block_id.is_valid()) {
       return;
     }
@@ -376,73 +377,73 @@ class NodeNamer {
     Scope& scope = GetScopeInfo(scope_idx);
 
     // Use bound names where available. Otherwise, assign a backup name.
-    for (auto node_id : sem_ir_.node_blocks().Get(block_id)) {
-      if (!node_id.is_valid()) {
+    for (auto inst_id : sem_ir_.inst_blocks().Get(block_id)) {
+      if (!inst_id.is_valid()) {
         continue;
       }
 
-      auto node = sem_ir_.nodes().Get(node_id);
-      auto add_node_name = [&](std::string name) {
-        nodes[node_id.index] = {scope_idx, scope.nodes.AllocateName(
-                                               *this, node.parse_node(), name)};
+      auto inst = sem_ir_.insts().Get(inst_id);
+      auto add_inst_name = [&](std::string name) {
+        insts[inst_id.index] = {scope_idx, scope.insts.AllocateName(
+                                               *this, inst.parse_node(), name)};
       };
-      auto add_node_name_id = [&](StringId name_id,
+      auto add_inst_name_id = [&](StringId name_id,
                                   llvm::StringRef suffix = "") {
         if (name_id.is_valid()) {
-          add_node_name((sem_ir_.strings().Get(name_id).str() + suffix).str());
+          add_inst_name((sem_ir_.strings().Get(name_id).str() + suffix).str());
         } else {
-          add_node_name(suffix.str());
+          add_inst_name(suffix.str());
         }
       };
 
-      switch (node.kind()) {
+      switch (inst.kind()) {
         case Branch::Kind: {
-          AddBlockLabel(scope_idx, node.As<Branch>().target_id, node);
+          AddBlockLabel(scope_idx, inst.As<Branch>().target_id, inst);
           break;
         }
         case BranchIf::Kind: {
-          AddBlockLabel(scope_idx, node.As<BranchIf>().target_id, node);
+          AddBlockLabel(scope_idx, inst.As<BranchIf>().target_id, inst);
           break;
         }
         case BranchWithArg::Kind: {
-          AddBlockLabel(scope_idx, node.As<BranchWithArg>().target_id, node);
+          AddBlockLabel(scope_idx, inst.As<BranchWithArg>().target_id, inst);
           break;
         }
         case SpliceBlock::Kind: {
-          CollectNamesInBlock(scope_idx, node.As<SpliceBlock>().block_id);
+          CollectNamesInBlock(scope_idx, inst.As<SpliceBlock>().block_id);
           break;
         }
         case BindName::Kind: {
-          add_node_name_id(node.As<BindName>().name_id);
+          add_inst_name_id(inst.As<BindName>().name_id);
           continue;
         }
         case FunctionDeclaration::Kind: {
-          add_node_name_id(sem_ir_.functions()
-                               .Get(node.As<FunctionDeclaration>().function_id)
+          add_inst_name_id(sem_ir_.functions()
+                               .Get(inst.As<FunctionDeclaration>().function_id)
                                .name_id);
           continue;
         }
         case ClassType::Kind: {
-          add_node_name_id(
-              sem_ir_.classes().Get(node.As<ClassType>().class_id).name_id);
+          add_inst_name_id(
+              sem_ir_.classes().Get(inst.As<ClassType>().class_id).name_id);
           continue;
         }
         case NameReference::Kind: {
-          add_node_name_id(node.As<NameReference>().name_id, ".ref");
+          add_inst_name_id(inst.As<NameReference>().name_id, ".ref");
           continue;
         }
         case Parameter::Kind: {
-          add_node_name_id(node.As<Parameter>().name_id);
+          add_inst_name_id(inst.As<Parameter>().name_id);
           continue;
         }
         case SelfParameter::Kind: {
-          add_node_name(node.As<SelfParameter>().is_addr_self.index
+          add_inst_name(inst.As<SelfParameter>().is_addr_self.index
                             ? "self.addr"
                             : "self");
           continue;
         }
         case VarStorage::Kind: {
-          add_node_name_id(node.As<VarStorage>().name_id, ".var");
+          add_inst_name_id(inst.As<VarStorage>().name_id, ".var");
           continue;
         }
         default: {
@@ -451,8 +452,8 @@ class NodeNamer {
       }
 
       // Sequentially number all remaining values.
-      if (node.kind().value_kind() != NodeValueKind::None) {
-        add_node_name("");
+      if (inst.kind().value_kind() != InstValueKind::None) {
+        add_inst_name("");
       }
     }
   }
@@ -462,7 +463,7 @@ class NodeNamer {
   const File& sem_ir_;
 
   Namespace globals = {.prefix = "@"};
-  std::vector<std::pair<ScopeIndex, Namespace::Name>> nodes;
+  std::vector<std::pair<ScopeIndex, Namespace::Name>> insts;
   std::vector<std::pair<ScopeIndex, Namespace::Name>> labels;
   std::vector<Scope> scopes;
 };
@@ -476,17 +477,17 @@ class Formatter {
                      llvm::raw_ostream& out)
       : sem_ir_(sem_ir),
         out_(out),
-        node_namer_(tokenized_buffer, parse_tree, sem_ir) {}
+        inst_namer_(tokenized_buffer, parse_tree, sem_ir) {}
 
   auto Format() -> void {
     out_ << "file \"" << sem_ir_.filename() << "\" {\n";
     // TODO: Include information from the `package` declaration, once we
     // fully support it.
-    // TODO: Handle the case where there are multiple top-level node blocks.
-    // For example, there may be branching in the initializer of a global or a
-    // type expression.
-    if (auto block_id = sem_ir_.top_node_block_id(); block_id.is_valid()) {
-      llvm::SaveAndRestore file_scope(scope_, NodeNamer::ScopeIndex::File);
+    // TODO: Handle the case where there are multiple top-level instruction
+    // blocks. For example, there may be branching in the initializer of a
+    // global or a type expression.
+    if (auto block_id = sem_ir_.top_inst_block_id(); block_id.is_valid()) {
+      llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeIndex::File);
       FormatCodeBlock(block_id);
     }
     out_ << "}\n";
@@ -506,7 +507,7 @@ class Formatter {
     out_ << "\nclass ";
     FormatClassName(id);
 
-    llvm::SaveAndRestore class_scope(scope_, node_namer_.GetScopeFor(id));
+    llvm::SaveAndRestore class_scope(scope_, inst_namer_.GetScopeFor(id));
 
     if (class_info.scope_id.is_valid()) {
       out_ << " {\n";
@@ -525,9 +526,9 @@ class Formatter {
     out_ << "\nfn ";
     FormatFunctionName(id);
 
-    llvm::SaveAndRestore function_scope(scope_, node_namer_.GetScopeFor(id));
+    llvm::SaveAndRestore function_scope(scope_, inst_namer_.GetScopeFor(id));
 
-    if (fn.implicit_param_refs_id != SemIR::NodeBlockId::Empty) {
+    if (fn.implicit_param_refs_id != SemIR::InstBlockId::Empty) {
       out_ << "[";
       FormatParameterList(fn.implicit_param_refs_id);
       out_ << "]";
@@ -540,7 +541,7 @@ class Formatter {
     if (fn.return_type_id.is_valid()) {
       out_ << " -> ";
       if (fn.return_slot_id.is_valid()) {
-        FormatNodeName(fn.return_slot_id);
+        FormatInstName(fn.return_slot_id);
         out_ << ": ";
       }
       FormatType(fn.return_type_id);
@@ -564,27 +565,27 @@ class Formatter {
     }
   }
 
-  auto FormatParameterList(NodeBlockId param_refs_id) -> void {
+  auto FormatParameterList(InstBlockId param_refs_id) -> void {
     llvm::ListSeparator sep;
-    for (const NodeId param_id : sem_ir_.node_blocks().Get(param_refs_id)) {
+    for (const InstId param_id : sem_ir_.inst_blocks().Get(param_refs_id)) {
       out_ << sep;
       if (!param_id.is_valid()) {
         out_ << "invalid";
         continue;
       }
-      FormatNodeName(param_id);
+      FormatInstName(param_id);
       out_ << ": ";
-      FormatType(sem_ir_.nodes().Get(param_id).type_id());
+      FormatType(sem_ir_.insts().Get(param_id).type_id());
     }
   }
 
-  auto FormatCodeBlock(NodeBlockId block_id) -> void {
+  auto FormatCodeBlock(InstBlockId block_id) -> void {
     if (!block_id.is_valid()) {
       return;
     }
 
-    for (const NodeId node_id : sem_ir_.node_blocks().Get(block_id)) {
-      FormatInstruction(node_id);
+    for (const InstId inst_id : sem_ir_.inst_blocks().Get(block_id)) {
+      FormatInstruction(inst_id);
     }
   }
 
@@ -592,39 +593,39 @@ class Formatter {
                        llvm::StringRef prefix) -> void {
     // Name scopes aren't kept in any particular order. Sort the entries before
     // we print them for stability and consistency.
-    llvm::SmallVector<std::pair<NodeId, StringId>> entries;
-    for (auto [name_id, node_id] : sem_ir_.name_scopes().Get(id)) {
-      entries.push_back({node_id, name_id});
+    llvm::SmallVector<std::pair<InstId, StringId>> entries;
+    for (auto [name_id, inst_id] : sem_ir_.name_scopes().Get(id)) {
+      entries.push_back({inst_id, name_id});
     }
     llvm::sort(entries,
                [](auto a, auto b) { return a.first.index < b.first.index; });
 
     llvm::ListSeparator sep(separator);
-    for (auto [node_id, name_id] : entries) {
+    for (auto [inst_id, name_id] : entries) {
       out_ << sep << prefix;
       FormatString(name_id);
       out_ << " = ";
-      FormatNodeName(node_id);
+      FormatInstName(inst_id);
     }
   }
 
-  auto FormatInstruction(NodeId node_id) -> void {
-    if (!node_id.is_valid()) {
+  auto FormatInstruction(InstId inst_id) -> void {
+    if (!inst_id.is_valid()) {
       Indent();
       out_ << "invalid\n";
       return;
     }
 
-    FormatInstruction(node_id, sem_ir_.nodes().Get(node_id));
+    FormatInstruction(inst_id, sem_ir_.insts().Get(inst_id));
   }
 
-  auto FormatInstruction(NodeId node_id, Node node) -> void {
+  auto FormatInstruction(InstId inst_id, Inst inst) -> void {
     // clang warns on unhandled enum values; clang-tidy is incorrect here.
     // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
-    switch (node.kind()) {
-#define CARBON_SEM_IR_NODE_KIND(NodeT)            \
-  case NodeT::Kind:                               \
-    FormatInstruction(node_id, node.As<NodeT>()); \
+    switch (inst.kind()) {
+#define CARBON_SEM_IR_INST_KIND(InstT)            \
+  case InstT::Kind:                               \
+    FormatInstruction(inst_id, inst.As<InstT>()); \
     break;
 #include "toolchain/sem_ir/node_kind.def"
     }
@@ -632,21 +633,21 @@ class Formatter {
 
   auto Indent() -> void { out_.indent(indent_); }
 
-  template <typename NodeT>
-  auto FormatInstruction(NodeId node_id, NodeT node) -> void {
+  template <typename InstT>
+  auto FormatInstruction(InstId inst_id, InstT inst) -> void {
     Indent();
-    FormatInstructionLHS(node_id, node);
-    out_ << NodeT::Kind.ir_name();
-    FormatInstructionRHS(node);
+    FormatInstructionLHS(inst_id, inst);
+    out_ << InstT::Kind.ir_name();
+    FormatInstructionRHS(inst);
     out_ << "\n";
   }
 
-  auto FormatInstructionLHS(NodeId node_id, Node node) -> void {
-    switch (node.kind().value_kind()) {
-      case NodeValueKind::Typed:
-        FormatNodeName(node_id);
+  auto FormatInstructionLHS(InstId inst_id, Inst inst) -> void {
+    switch (inst.kind().value_kind()) {
+      case InstValueKind::Typed:
+        FormatInstName(inst_id);
         out_ << ": ";
-        switch (GetExpressionCategory(sem_ir_, node_id)) {
+        switch (GetExpressionCategory(sem_ir_, inst_id)) {
           case ExpressionCategory::NotExpression:
           case ExpressionCategory::Error:
           case ExpressionCategory::Value:
@@ -660,99 +661,99 @@ class Formatter {
             out_ << "init ";
             break;
         }
-        FormatType(node.type_id());
+        FormatType(inst.type_id());
         out_ << " = ";
         break;
-      case NodeValueKind::None:
+      case InstValueKind::None:
         break;
     }
   }
 
-  template <typename NodeT>
-  auto FormatInstructionRHS(NodeT node) -> void {
+  template <typename InstT>
+  auto FormatInstructionRHS(InstT inst) -> void {
     // By default, an instruction has a comma-separated argument list.
-    using Info = TypedNodeArgsInfo<NodeT>;
+    using Info = TypedInstArgsInfo<InstT>;
     if constexpr (Info::NumArgs == 2) {
-      FormatArgs(Info::template Get<0>(node), Info::template Get<1>(node));
+      FormatArgs(Info::template Get<0>(inst), Info::template Get<1>(inst));
     } else if constexpr (Info::NumArgs == 1) {
-      FormatArgs(Info::template Get<0>(node));
+      FormatArgs(Info::template Get<0>(inst));
     } else {
       FormatArgs();
     }
   }
 
-  auto FormatInstructionRHS(BlockArg node) -> void {
+  auto FormatInstructionRHS(BlockArg inst) -> void {
     out_ << " ";
-    FormatLabel(node.block_id);
+    FormatLabel(inst.block_id);
   }
 
-  auto FormatInstruction(NodeId /*node_id*/, BranchIf node) -> void {
+  auto FormatInstruction(InstId /*inst_id*/, BranchIf inst) -> void {
     if (!in_terminator_sequence_) {
       Indent();
     }
     out_ << "if ";
-    FormatNodeName(node.cond_id);
+    FormatInstName(inst.cond_id);
     out_ << " " << Branch::Kind.ir_name() << " ";
-    FormatLabel(node.target_id);
+    FormatLabel(inst.target_id);
     out_ << " else ";
     in_terminator_sequence_ = true;
   }
 
-  auto FormatInstruction(NodeId /*node_id*/, BranchWithArg node) -> void {
+  auto FormatInstruction(InstId /*inst_id*/, BranchWithArg inst) -> void {
     if (!in_terminator_sequence_) {
       Indent();
     }
     out_ << BranchWithArg::Kind.ir_name() << " ";
-    FormatLabel(node.target_id);
+    FormatLabel(inst.target_id);
     out_ << "(";
-    FormatNodeName(node.arg_id);
+    FormatInstName(inst.arg_id);
     out_ << ")\n";
     in_terminator_sequence_ = false;
   }
 
-  auto FormatInstruction(NodeId /*node_id*/, Branch node) -> void {
+  auto FormatInstruction(InstId /*inst_id*/, Branch inst) -> void {
     if (!in_terminator_sequence_) {
       Indent();
     }
     out_ << Branch::Kind.ir_name() << " ";
-    FormatLabel(node.target_id);
+    FormatLabel(inst.target_id);
     out_ << "\n";
     in_terminator_sequence_ = false;
   }
 
-  auto FormatInstructionRHS(ArrayInit node) -> void {
+  auto FormatInstructionRHS(ArrayInit inst) -> void {
     out_ << " ";
-    FormatArg(node.tuple_id);
+    FormatArg(inst.tuple_id);
 
-    llvm::ArrayRef<NodeId> inits_and_return_slot =
-        sem_ir_.node_blocks().Get(node.inits_and_return_slot_id);
+    llvm::ArrayRef<InstId> inits_and_return_slot =
+        sem_ir_.inst_blocks().Get(inst.inits_and_return_slot_id);
     auto inits = inits_and_return_slot.drop_back(1);
     auto return_slot_id = inits_and_return_slot.back();
 
     out_ << ", (";
     llvm::ListSeparator sep;
-    for (auto node_id : inits) {
+    for (auto inst_id : inits) {
       out_ << sep;
-      FormatArg(node_id);
+      FormatArg(inst_id);
     }
     out_ << ')';
     FormatReturnSlot(return_slot_id);
   }
 
-  auto FormatInstructionRHS(Call node) -> void {
+  auto FormatInstructionRHS(Call inst) -> void {
     out_ << " ";
-    FormatArg(node.callee_id);
+    FormatArg(inst.callee_id);
 
-    if (!node.args_id.is_valid()) {
+    if (!inst.args_id.is_valid()) {
       out_ << "(<invalid>)";
       return;
     }
 
-    llvm::ArrayRef<NodeId> args = sem_ir_.node_blocks().Get(node.args_id);
+    llvm::ArrayRef<InstId> args = sem_ir_.inst_blocks().Get(inst.args_id);
 
     bool has_return_slot =
-        GetInitializingRepresentation(sem_ir_, node.type_id).has_return_slot();
-    NodeId return_slot_id = NodeId::Invalid;
+        GetInitializingRepresentation(sem_ir_, inst.type_id).has_return_slot();
+    InstId return_slot_id = InstId::Invalid;
     if (has_return_slot) {
       return_slot_id = args.back();
       args = args.drop_back();
@@ -760,9 +761,9 @@ class Formatter {
 
     llvm::ListSeparator sep;
     out_ << '(';
-    for (auto node_id : args) {
+    for (auto inst_id : args) {
       out_ << sep;
-      FormatArg(node_id);
+      FormatArg(inst_id);
     }
     out_ << ')';
 
@@ -771,24 +772,24 @@ class Formatter {
     }
   }
 
-  auto FormatInstructionRHS(InitializeFrom node) -> void {
-    FormatArgs(node.src_id);
-    FormatReturnSlot(node.dest_id);
+  auto FormatInstructionRHS(InitializeFrom inst) -> void {
+    FormatArgs(inst.src_id);
+    FormatReturnSlot(inst.dest_id);
   }
 
-  auto FormatInstructionRHS(CrossReference node) -> void {
+  auto FormatInstructionRHS(CrossReference inst) -> void {
     // TODO: Figure out a way to make this meaningful. We'll need some way to
-    // name cross-reference IRs, perhaps by the node ID of the import?
-    out_ << " " << node.ir_id << "." << node.node_id;
+    // name cross-reference IRs, perhaps by the instruction ID of the import?
+    out_ << " " << inst.ir_id << "." << inst.inst_id;
   }
 
-  auto FormatInstructionRHS(SpliceBlock node) -> void {
-    FormatArgs(node.result_id);
+  auto FormatInstructionRHS(SpliceBlock inst) -> void {
+    FormatArgs(inst.result_id);
     out_ << " {";
-    if (!sem_ir_.node_blocks().Get(node.block_id).empty()) {
+    if (!sem_ir_.inst_blocks().Get(inst.block_id).empty()) {
       out_ << "\n";
       indent_ += 2;
-      FormatCodeBlock(node.block_id);
+      FormatCodeBlock(inst.block_id);
       indent_ -= 2;
       Indent();
     }
@@ -796,15 +797,15 @@ class Formatter {
   }
 
   // StructTypeFields are formatted as part of their StructType.
-  auto FormatInstruction(NodeId /*node_id*/, StructTypeField /*node*/) -> void {
+  auto FormatInstruction(InstId /*inst_id*/, StructTypeField /*inst*/) -> void {
   }
 
-  auto FormatInstructionRHS(StructType node) -> void {
+  auto FormatInstructionRHS(StructType inst) -> void {
     out_ << " {";
     llvm::ListSeparator sep;
-    for (auto field_id : sem_ir_.node_blocks().Get(node.fields_id)) {
+    for (auto field_id : sem_ir_.inst_blocks().Get(inst.fields_id)) {
       out_ << sep << ".";
-      auto field = sem_ir_.nodes().GetAs<StructTypeField>(field_id);
+      auto field = sem_ir_.insts().GetAs<StructTypeField>(field_id);
       FormatString(field.name_id);
       out_ << ": ";
       FormatType(field.field_type_id);
@@ -841,14 +842,14 @@ class Formatter {
     out_ << '}';
   }
 
-  auto FormatArg(NodeId id) -> void { FormatNodeName(id); }
+  auto FormatArg(InstId id) -> void { FormatInstName(id); }
 
-  auto FormatArg(NodeBlockId id) -> void {
+  auto FormatArg(InstBlockId id) -> void {
     out_ << '(';
     llvm::ListSeparator sep;
-    for (auto node_id : sem_ir_.node_blocks().Get(id)) {
+    for (auto inst_id : sem_ir_.inst_blocks().Get(id)) {
       out_ << sep;
-      FormatArg(node_id);
+      FormatArg(inst_id);
     }
     out_ << ')';
   }
@@ -878,27 +879,27 @@ class Formatter {
     out_ << ')';
   }
 
-  auto FormatReturnSlot(NodeId dest_id) -> void {
+  auto FormatReturnSlot(InstId dest_id) -> void {
     out_ << " to ";
     FormatArg(dest_id);
   }
 
-  auto FormatNodeName(NodeId id) -> void {
-    out_ << node_namer_.GetNameFor(scope_, id);
+  auto FormatInstName(InstId id) -> void {
+    out_ << inst_namer_.GetNameFor(scope_, id);
   }
 
-  auto FormatLabel(NodeBlockId id) -> void {
-    out_ << node_namer_.GetLabelFor(scope_, id);
+  auto FormatLabel(InstBlockId id) -> void {
+    out_ << inst_namer_.GetLabelFor(scope_, id);
   }
 
   auto FormatString(StringId id) -> void { out_ << sem_ir_.strings().Get(id); }
 
   auto FormatFunctionName(FunctionId id) -> void {
-    out_ << node_namer_.GetNameFor(id);
+    out_ << inst_namer_.GetNameFor(id);
   }
 
   auto FormatClassName(ClassId id) -> void {
-    out_ << node_namer_.GetNameFor(id);
+    out_ << inst_namer_.GetNameFor(id);
   }
 
   auto FormatType(TypeId id) -> void {
@@ -912,8 +913,8 @@ class Formatter {
  private:
   const File& sem_ir_;
   llvm::raw_ostream& out_;
-  NodeNamer node_namer_;
-  NodeNamer::ScopeIndex scope_ = NodeNamer::ScopeIndex::None;
+  InstNamer inst_namer_;
+  InstNamer::ScopeIndex scope_ = InstNamer::ScopeIndex::None;
   bool in_terminator_sequence_ = false;
   int indent_ = 2;
 };

+ 30 - 30
toolchain/sem_ir/ids.h

@@ -14,24 +14,24 @@
 
 namespace Carbon::SemIR {
 
-// The ID of a node.
-struct NodeId : public IndexBase, public Printable<NodeId> {
-  // An explicitly invalid node ID.
-  static const NodeId Invalid;
+// The ID of an instruction.
+struct InstId : public IndexBase, public Printable<InstId> {
+  // An explicitly invalid instruction ID.
+  static const InstId Invalid;
 
-// Builtin node IDs.
-#define CARBON_SEM_IR_BUILTIN_KIND_NAME(Name) static const NodeId Builtin##Name;
+// Builtin instruction IDs.
+#define CARBON_SEM_IR_BUILTIN_KIND_NAME(Name) static const InstId Builtin##Name;
 #include "toolchain/sem_ir/builtin_kind.def"
 
-  // Returns the cross-reference node ID for a builtin. This relies on File
-  // guarantees for builtin cross-reference placement.
-  static constexpr auto ForBuiltin(BuiltinKind kind) -> NodeId {
-    return NodeId(kind.AsInt());
+  // Returns the cross-reference instruction ID for a builtin. This relies on
+  // File guarantees for builtin cross-reference placement.
+  static constexpr auto ForBuiltin(BuiltinKind kind) -> InstId {
+    return InstId(kind.AsInt());
   }
 
   using IndexBase::IndexBase;
   auto Print(llvm::raw_ostream& out) const -> void {
-    out << "node";
+    out << "inst";
     if (!is_valid()) {
       IndexBase::Print(out);
     } else if (index < BuiltinKind::ValidCount) {
@@ -44,11 +44,11 @@ struct NodeId : public IndexBase, public Printable<NodeId> {
   }
 };
 
-constexpr NodeId NodeId::Invalid = NodeId(NodeId::InvalidIndex);
+constexpr InstId InstId::Invalid = InstId(InstId::InvalidIndex);
 
 #define CARBON_SEM_IR_BUILTIN_KIND_NAME(Name) \
-  constexpr NodeId NodeId::Builtin##Name =    \
-      NodeId::ForBuiltin(BuiltinKind::Name);
+  constexpr InstId InstId::Builtin##Name =    \
+      InstId::ForBuiltin(BuiltinKind::Name);
 #include "toolchain/sem_ir/builtin_kind.def"
 
 // The ID of a function.
@@ -127,16 +127,16 @@ struct NameScopeId : public IndexBase, public Printable<NameScopeId> {
 constexpr NameScopeId NameScopeId::Invalid =
     NameScopeId(NameScopeId::InvalidIndex);
 
-// The ID of a node block.
-struct NodeBlockId : public IndexBase, public Printable<NodeBlockId> {
-  // All File instances must provide the 0th node block as empty.
-  static const NodeBlockId Empty;
+// The ID of an instruction block.
+struct InstBlockId : public IndexBase, public Printable<InstBlockId> {
+  // All File instances must provide the 0th instruction block as empty.
+  static const InstBlockId Empty;
 
   // An explicitly invalid ID.
-  static const NodeBlockId Invalid;
+  static const InstBlockId Invalid;
 
   // An ID for unreachable code.
-  static const NodeBlockId Unreachable;
+  static const InstBlockId Unreachable;
 
   using IndexBase::IndexBase;
   auto Print(llvm::raw_ostream& out) const -> void {
@@ -149,13 +149,13 @@ struct NodeBlockId : public IndexBase, public Printable<NodeBlockId> {
   }
 };
 
-constexpr NodeBlockId NodeBlockId::Empty = NodeBlockId(0);
-constexpr NodeBlockId NodeBlockId::Invalid =
-    NodeBlockId(NodeBlockId::InvalidIndex);
-constexpr NodeBlockId NodeBlockId::Unreachable =
-    NodeBlockId(NodeBlockId::InvalidIndex - 1);
+constexpr InstBlockId InstBlockId::Empty = InstBlockId(0);
+constexpr InstBlockId InstBlockId::Invalid =
+    InstBlockId(InstBlockId::InvalidIndex);
+constexpr InstBlockId InstBlockId::Unreachable =
+    InstBlockId(InstBlockId::InvalidIndex - 1);
 
-// The ID of a node block.
+// The ID of a type.
 struct TypeId : public IndexBase, public Printable<TypeId> {
   // The builtin TypeType.
   static const TypeId TypeType;
@@ -205,10 +205,10 @@ struct MemberIndex : public IndexBase, public Printable<MemberIndex> {
 
 // Support use of Id types as DenseMap/DenseSet keys.
 template <>
-struct llvm::DenseMapInfo<Carbon::SemIR::NodeBlockId>
-    : public Carbon::IndexMapInfo<Carbon::SemIR::NodeBlockId> {};
+struct llvm::DenseMapInfo<Carbon::SemIR::InstBlockId>
+    : public Carbon::IndexMapInfo<Carbon::SemIR::InstBlockId> {};
 template <>
-struct llvm::DenseMapInfo<Carbon::SemIR::NodeId>
-    : public Carbon::IndexMapInfo<Carbon::SemIR::NodeId> {};
+struct llvm::DenseMapInfo<Carbon::SemIR::InstId>
+    : public Carbon::IndexMapInfo<Carbon::SemIR::InstId> {};
 
 #endif  // CARBON_TOOLCHAIN_SEM_IR_IDS_H_

+ 4 - 4
toolchain/sem_ir/node.cpp → toolchain/sem_ir/inst.cpp

@@ -2,11 +2,11 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::SemIR {
 
-auto Node::Print(llvm::raw_ostream& out) const -> void {
+auto Inst::Print(llvm::raw_ostream& out) const -> void {
   out << "{kind: " << kind_;
 
   auto print_args = [&](auto info) {
@@ -22,9 +22,9 @@ auto Node::Print(llvm::raw_ostream& out) const -> void {
   // clang warns on unhandled enum values; clang-tidy is incorrect here.
   // NOLINTNEXTLINE(bugprone-switch-missing-default-case)
   switch (kind_) {
-#define CARBON_SEM_IR_NODE_KIND(Name)      \
+#define CARBON_SEM_IR_INST_KIND(Name)      \
   case Name::Kind:                         \
-    print_args(TypedNodeArgsInfo<Name>()); \
+    print_args(TypedInstArgsInfo<Name>()); \
     break;
 #include "toolchain/sem_ir/node_kind.def"
   }

+ 69 - 66
toolchain/sem_ir/node.h → toolchain/sem_ir/inst.h

@@ -2,8 +2,8 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#ifndef CARBON_TOOLCHAIN_SEM_IR_NODE_H_
-#define CARBON_TOOLCHAIN_SEM_IR_NODE_H_
+#ifndef CARBON_TOOLCHAIN_SEM_IR_INST_H_
+#define CARBON_TOOLCHAIN_SEM_IR_INST_H_
 
 #include <cstdint>
 
@@ -14,98 +14,101 @@
 #include "toolchain/parse/tree.h"
 #include "toolchain/sem_ir/builtin_kind.h"
 #include "toolchain/sem_ir/node_kind.h"
-#include "toolchain/sem_ir/typed_nodes.h"
+#include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::SemIR {
 
-// Data about the arguments of a typed node, to aid in type erasure. The `KindT`
-// parameter is used to check that `TypedNode` is a typed node.
-template <typename TypedNode,
-          const NodeKind::Definition& KindT = TypedNode::Kind>
-struct TypedNodeArgsInfo {
+// Data about the arguments of a typed instruction, to aid in type erasure. The
+// `KindT` parameter is used to check that `TypedInst` is a typed instruction.
+template <typename TypedInst,
+          const InstKind::Definition& KindT = TypedInst::Kind>
+struct TypedInstArgsInfo {
   // A corresponding std::tuple<...> type.
-  using Tuple = decltype(StructReflection::AsTuple(std::declval<TypedNode>()));
+  using Tuple = decltype(StructReflection::AsTuple(std::declval<TypedInst>()));
 
   static constexpr int FirstArgField =
-      HasParseNode<TypedNode> + HasTypeId<TypedNode>;
+      HasParseNode<TypedInst> + HasTypeId<TypedInst>;
 
   static constexpr int NumArgs = std::tuple_size_v<Tuple> - FirstArgField;
   static_assert(NumArgs <= 2,
-                "Unsupported: typed node has more than two data fields");
+                "Unsupported: typed inst has more than two data fields");
 
   template <int N>
   using ArgType = std::tuple_element_t<FirstArgField + N, Tuple>;
 
   template <int N>
-  static auto Get(TypedNode node) -> ArgType<N> {
-    return std::get<FirstArgField + N>(StructReflection::AsTuple(node));
+  static auto Get(TypedInst inst) -> ArgType<N> {
+    return std::get<FirstArgField + N>(StructReflection::AsTuple(inst));
   }
 };
 
-// A type-erased representation of a SemIR node, that may be constructed from
-// the specific kinds of node defined in `typed_nodes.h`. This provides access
-// to common fields present on most or all kinds of nodes:
+// A type-erased representation of a SemIR instruction, that may be constructed
+// from the specific kinds of instruction defined in `typed_insts.h`. This
+// provides access to common fields present on most or all kinds of
+// instructions:
 //
 // - `parse_node` for error placement.
 // - `kind` for run-time logic when the input Kind is unknown.
 // - `type_id` for quick type checking.
 //
 // In addition, kind-specific data can be accessed by casting to the specific
-// kind of node:
+// kind of instruction:
 //
-// - Use `node.kind()` or `Is<TypedNode>` to determine what kind of node it is.
-// - Cast to a specific type using `node.As<TypedNode>()`
-//   - Using the wrong kind in `node.As<TypedNode>()` is a programming error,
+// - Use `inst.kind()` or `Is<TypedInst>` to determine what kind of instruction
+// it is.
+// - Cast to a specific type using `inst.As<TypedInst>()`
+//   - Using the wrong kind in `inst.As<TypedInst>()` is a programming error,
 //     and will CHECK-fail in debug modes (opt may too, but it's not an API
 //     guarantee).
-// - Use `node.TryAs<TypedNode>()` to safely access type-specific node data
-//   where the node's kind is not known.
-class Node : public Printable<Node> {
+// - Use `inst.TryAs<TypedInst>()` to safely access type-specific instruction
+// data
+//   where the instruction's kind is not known.
+class Inst : public Printable<Inst> {
  public:
-  template <typename TypedNode, typename Info = TypedNodeArgsInfo<TypedNode>>
+  template <typename TypedInst, typename Info = TypedInstArgsInfo<TypedInst>>
   // NOLINTNEXTLINE(google-explicit-constructor)
-  Node(TypedNode typed_node)
+  Inst(TypedInst typed_inst)
       : parse_node_(Parse::Node::Invalid),
-        kind_(TypedNode::Kind),
+        kind_(TypedInst::Kind),
         type_id_(TypeId::Invalid),
-        arg0_(NodeId::InvalidIndex),
-        arg1_(NodeId::InvalidIndex) {
-    if constexpr (HasParseNode<TypedNode>) {
-      parse_node_ = typed_node.parse_node;
+        arg0_(InstId::InvalidIndex),
+        arg1_(InstId::InvalidIndex) {
+    if constexpr (HasParseNode<TypedInst>) {
+      parse_node_ = typed_inst.parse_node;
     }
-    if constexpr (HasTypeId<TypedNode>) {
-      type_id_ = typed_node.type_id;
+    if constexpr (HasTypeId<TypedInst>) {
+      type_id_ = typed_inst.type_id;
     }
     if constexpr (Info::NumArgs > 0) {
-      arg0_ = ToRaw(Info::template Get<0>(typed_node));
+      arg0_ = ToRaw(Info::template Get<0>(typed_inst));
     }
     if constexpr (Info::NumArgs > 1) {
-      arg1_ = ToRaw(Info::template Get<1>(typed_node));
+      arg1_ = ToRaw(Info::template Get<1>(typed_inst));
     }
   }
 
-  // Returns whether this node has the specified type.
-  template <typename TypedNode>
+  // Returns whether this instruction has the specified type.
+  template <typename TypedInst>
   auto Is() const -> bool {
-    return kind() == TypedNode::Kind;
+    return kind() == TypedInst::Kind;
   }
 
-  // Casts this node to the given typed node, which must match the node's kind,
-  // and returns the typed node.
-  template <typename TypedNode, typename Info = TypedNodeArgsInfo<TypedNode>>
-  auto As() const -> TypedNode {
-    CARBON_CHECK(Is<TypedNode>()) << "Casting node of kind " << kind()
-                                  << " to wrong kind " << TypedNode::Kind;
+  // Casts this instruction to the given typed instruction, which must match the
+  // instruction's kind, and returns the typed instruction.
+  template <typename TypedInst, typename Info = TypedInstArgsInfo<TypedInst>>
+  auto As() const -> TypedInst {
+    CARBON_CHECK(Is<TypedInst>()) << "Casting inst of kind " << kind()
+                                  << " to wrong kind " << TypedInst::Kind;
     auto build_with_type_id_and_args = [&](auto... type_id_and_args) {
-      if constexpr (HasParseNode<TypedNode>) {
-        return TypedNode{parse_node(), type_id_and_args...};
+      if constexpr (HasParseNode<TypedInst>) {
+        return TypedInst{parse_node(), type_id_and_args...};
       } else {
-        return TypedNode{type_id_and_args...};
+        return TypedInst{type_id_and_args...};
       }
     };
 
     auto build_with_args = [&](auto... args) {
-      if constexpr (HasTypeId<TypedNode>) {
+      if constexpr (HasTypeId<TypedInst>) {
         return build_with_type_id_and_args(type_id(), args...);
       } else {
         return build_with_type_id_and_args(args...);
@@ -124,30 +127,30 @@ class Node : public Printable<Node> {
     }
   }
 
-  // If this node is the given kind, returns a typed node, otherwise returns
-  // nullopt.
-  template <typename TypedNode>
-  auto TryAs() const -> std::optional<TypedNode> {
-    if (Is<TypedNode>()) {
-      return As<TypedNode>();
+  // If this instruction is the given kind, returns a typed instruction,
+  // otherwise returns nullopt.
+  template <typename TypedInst>
+  auto TryAs() const -> std::optional<TypedInst> {
+    if (Is<TypedInst>()) {
+      return As<TypedInst>();
     } else {
       return std::nullopt;
     }
   }
 
   auto parse_node() const -> Parse::Node { return parse_node_; }
-  auto kind() const -> NodeKind { return kind_; }
+  auto kind() const -> InstKind { return kind_; }
 
-  // Gets the type of the value produced by evaluating this node.
+  // Gets the type of the value produced by evaluating this instruction.
   auto type_id() const -> TypeId { return type_id_; }
 
   auto Print(llvm::raw_ostream& out) const -> void;
 
  private:
-  friend class NodeTestHelper;
+  friend class InstTestHelper;
 
   // Raw constructor, used for testing.
-  explicit Node(NodeKind kind, Parse::Node parse_node, TypeId type_id,
+  explicit Inst(InstKind kind, Parse::Node parse_node, TypeId type_id,
                 int32_t arg0, int32_t arg1)
       : parse_node_(parse_node),
         kind_(kind),
@@ -172,7 +175,7 @@ class Node : public Printable<Node> {
   }
 
   Parse::Node parse_node_;
-  NodeKind kind_;
+  InstKind kind_;
   TypeId type_id_;
 
   // Use `As` to access arg0 and arg1.
@@ -181,18 +184,18 @@ class Node : public Printable<Node> {
 };
 
 // TODO: This is currently 20 bytes because we sometimes have 2 arguments for a
-// pair of Nodes. However, NodeKind is 1 byte; if args
-// were 3.5 bytes, we could potentially shrink Node by 4 bytes. This
+// pair of Insts. However, InstKind is 1 byte; if args
+// were 3.5 bytes, we could potentially shrink Inst by 4 bytes. This
 // may be worth investigating further.
-static_assert(sizeof(Node) == 20, "Unexpected Node size");
+static_assert(sizeof(Inst) == 20, "Unexpected Inst size");
 
-// Typed nodes can be printed by converting them to nodes.
-template <typename TypedNode, typename = TypedNodeArgsInfo<TypedNode>>
-inline llvm::raw_ostream& operator<<(llvm::raw_ostream& out, TypedNode node) {
-  Node(node).Print(out);
+// Typed instructions can be printed by converting them to instructions.
+template <typename TypedInst, typename = TypedInstArgsInfo<TypedInst>>
+inline llvm::raw_ostream& operator<<(llvm::raw_ostream& out, TypedInst inst) {
+  Inst(inst).Print(out);
   return out;
 }
 
 }  // namespace Carbon::SemIR
 
-#endif  // CARBON_TOOLCHAIN_SEM_IR_NODE_H_
+#endif  // CARBON_TOOLCHAIN_SEM_IR_INST_H_

+ 11 - 11
toolchain/sem_ir/node_kind.cpp

@@ -4,35 +4,35 @@
 
 #include "toolchain/sem_ir/node_kind.h"
 
-#include "toolchain/sem_ir/typed_nodes.h"
+#include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::SemIR {
 
-CARBON_DEFINE_ENUM_CLASS_NAMES(NodeKind) = {
-#define CARBON_SEM_IR_NODE_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
+CARBON_DEFINE_ENUM_CLASS_NAMES(InstKind) = {
+#define CARBON_SEM_IR_INST_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
 #include "toolchain/sem_ir/node_kind.def"
 };
 
-auto NodeKind::ir_name() const -> llvm::StringLiteral {
+auto InstKind::ir_name() const -> llvm::StringLiteral {
   return definition().ir_name();
 }
 
-auto NodeKind::value_kind() const -> NodeValueKind {
-  static constexpr NodeValueKind Table[] = {
-#define CARBON_SEM_IR_NODE_KIND(Name) \
-  HasTypeId<SemIR::Name> ? NodeValueKind::Typed : NodeValueKind::None,
+auto InstKind::value_kind() const -> InstValueKind {
+  static constexpr InstValueKind Table[] = {
+#define CARBON_SEM_IR_INST_KIND(Name) \
+  HasTypeId<SemIR::Name> ? InstValueKind::Typed : InstValueKind::None,
 #include "toolchain/sem_ir/node_kind.def"
   };
   return Table[AsInt()];
 }
 
-auto NodeKind::terminator_kind() const -> TerminatorKind {
+auto InstKind::terminator_kind() const -> TerminatorKind {
   return definition().terminator_kind();
 }
 
-auto NodeKind::definition() const -> const Definition& {
+auto InstKind::definition() const -> const Definition& {
   static constexpr const Definition* Table[] = {
-#define CARBON_SEM_IR_NODE_KIND(Name) &SemIR::Name::Kind,
+#define CARBON_SEM_IR_INST_KIND(Name) &SemIR::Name::Kind,
 #include "toolchain/sem_ir/node_kind.def"
   };
   return *Table[AsInt()];

+ 62 - 62
toolchain/sem_ir/node_kind.def

@@ -8,70 +8,70 @@
 // at the end of this file.
 //
 // This macro should be defined before including this header:
-// - CARBON_SEM_IR_NODE_KIND(Name)
-//   Invoked for each kind of semantic node.
+// - CARBON_SEM_IR_INST_KIND(Name)
+//   Invoked for each kind of semantic instruction.
 
-#ifndef CARBON_SEM_IR_NODE_KIND
+#ifndef CARBON_SEM_IR_INST_KIND
 #error "Must define the x-macro to use this file."
 #endif
 
-// For each node kind declared here there is a matching definition in
-// `typed.nodes.h`.
-CARBON_SEM_IR_NODE_KIND(AddressOf)
-CARBON_SEM_IR_NODE_KIND(ArrayIndex)
-CARBON_SEM_IR_NODE_KIND(ArrayInit)
-CARBON_SEM_IR_NODE_KIND(ArrayType)
-CARBON_SEM_IR_NODE_KIND(Assign)
-CARBON_SEM_IR_NODE_KIND(BinaryOperatorAdd)
-CARBON_SEM_IR_NODE_KIND(BindName)
-CARBON_SEM_IR_NODE_KIND(BindValue)
-CARBON_SEM_IR_NODE_KIND(BlockArg)
-CARBON_SEM_IR_NODE_KIND(BoolLiteral)
-CARBON_SEM_IR_NODE_KIND(BoundMethod)
-CARBON_SEM_IR_NODE_KIND(Branch)
-CARBON_SEM_IR_NODE_KIND(BranchIf)
-CARBON_SEM_IR_NODE_KIND(BranchWithArg)
-CARBON_SEM_IR_NODE_KIND(Builtin)
-CARBON_SEM_IR_NODE_KIND(Call)
-CARBON_SEM_IR_NODE_KIND(ClassDeclaration)
-CARBON_SEM_IR_NODE_KIND(ClassFieldAccess)
-CARBON_SEM_IR_NODE_KIND(ClassType)
-CARBON_SEM_IR_NODE_KIND(ConstType)
-CARBON_SEM_IR_NODE_KIND(CrossReference)
-CARBON_SEM_IR_NODE_KIND(Dereference)
-CARBON_SEM_IR_NODE_KIND(Field)
-CARBON_SEM_IR_NODE_KIND(FunctionDeclaration)
-CARBON_SEM_IR_NODE_KIND(InitializeFrom)
-CARBON_SEM_IR_NODE_KIND(IntegerLiteral)
-CARBON_SEM_IR_NODE_KIND(NameReference)
-CARBON_SEM_IR_NODE_KIND(Namespace)
-CARBON_SEM_IR_NODE_KIND(NoOp)
-CARBON_SEM_IR_NODE_KIND(Parameter)
-CARBON_SEM_IR_NODE_KIND(PointerType)
-CARBON_SEM_IR_NODE_KIND(RealLiteral)
-CARBON_SEM_IR_NODE_KIND(ReturnExpression)
-CARBON_SEM_IR_NODE_KIND(Return)
-CARBON_SEM_IR_NODE_KIND(SelfParameter)
-CARBON_SEM_IR_NODE_KIND(SpliceBlock)
-CARBON_SEM_IR_NODE_KIND(StringLiteral)
-CARBON_SEM_IR_NODE_KIND(StructAccess)
-CARBON_SEM_IR_NODE_KIND(StructInit)
-CARBON_SEM_IR_NODE_KIND(StructLiteral)
-CARBON_SEM_IR_NODE_KIND(StructTypeField)
-CARBON_SEM_IR_NODE_KIND(StructType)
-CARBON_SEM_IR_NODE_KIND(StructValue)
-CARBON_SEM_IR_NODE_KIND(TemporaryStorage)
-CARBON_SEM_IR_NODE_KIND(Temporary)
-CARBON_SEM_IR_NODE_KIND(TupleAccess)
-CARBON_SEM_IR_NODE_KIND(TupleIndex)
-CARBON_SEM_IR_NODE_KIND(TupleInit)
-CARBON_SEM_IR_NODE_KIND(TupleLiteral)
-CARBON_SEM_IR_NODE_KIND(TupleType)
-CARBON_SEM_IR_NODE_KIND(TupleValue)
-CARBON_SEM_IR_NODE_KIND(UnaryOperatorNot)
-CARBON_SEM_IR_NODE_KIND(UnboundFieldType)
-CARBON_SEM_IR_NODE_KIND(ValueAsReference)
-CARBON_SEM_IR_NODE_KIND(ValueOfInitializer)
-CARBON_SEM_IR_NODE_KIND(VarStorage)
+// For each instruction kind declared here there is a matching definition in
+// `typed_insts.h`.
+CARBON_SEM_IR_INST_KIND(AddressOf)
+CARBON_SEM_IR_INST_KIND(ArrayIndex)
+CARBON_SEM_IR_INST_KIND(ArrayInit)
+CARBON_SEM_IR_INST_KIND(ArrayType)
+CARBON_SEM_IR_INST_KIND(Assign)
+CARBON_SEM_IR_INST_KIND(BinaryOperatorAdd)
+CARBON_SEM_IR_INST_KIND(BindName)
+CARBON_SEM_IR_INST_KIND(BindValue)
+CARBON_SEM_IR_INST_KIND(BlockArg)
+CARBON_SEM_IR_INST_KIND(BoolLiteral)
+CARBON_SEM_IR_INST_KIND(BoundMethod)
+CARBON_SEM_IR_INST_KIND(Branch)
+CARBON_SEM_IR_INST_KIND(BranchIf)
+CARBON_SEM_IR_INST_KIND(BranchWithArg)
+CARBON_SEM_IR_INST_KIND(Builtin)
+CARBON_SEM_IR_INST_KIND(Call)
+CARBON_SEM_IR_INST_KIND(ClassDeclaration)
+CARBON_SEM_IR_INST_KIND(ClassFieldAccess)
+CARBON_SEM_IR_INST_KIND(ClassType)
+CARBON_SEM_IR_INST_KIND(ConstType)
+CARBON_SEM_IR_INST_KIND(CrossReference)
+CARBON_SEM_IR_INST_KIND(Dereference)
+CARBON_SEM_IR_INST_KIND(Field)
+CARBON_SEM_IR_INST_KIND(FunctionDeclaration)
+CARBON_SEM_IR_INST_KIND(InitializeFrom)
+CARBON_SEM_IR_INST_KIND(IntegerLiteral)
+CARBON_SEM_IR_INST_KIND(NameReference)
+CARBON_SEM_IR_INST_KIND(Namespace)
+CARBON_SEM_IR_INST_KIND(NoOp)
+CARBON_SEM_IR_INST_KIND(Parameter)
+CARBON_SEM_IR_INST_KIND(PointerType)
+CARBON_SEM_IR_INST_KIND(RealLiteral)
+CARBON_SEM_IR_INST_KIND(ReturnExpression)
+CARBON_SEM_IR_INST_KIND(Return)
+CARBON_SEM_IR_INST_KIND(SelfParameter)
+CARBON_SEM_IR_INST_KIND(SpliceBlock)
+CARBON_SEM_IR_INST_KIND(StringLiteral)
+CARBON_SEM_IR_INST_KIND(StructAccess)
+CARBON_SEM_IR_INST_KIND(StructInit)
+CARBON_SEM_IR_INST_KIND(StructLiteral)
+CARBON_SEM_IR_INST_KIND(StructTypeField)
+CARBON_SEM_IR_INST_KIND(StructType)
+CARBON_SEM_IR_INST_KIND(StructValue)
+CARBON_SEM_IR_INST_KIND(TemporaryStorage)
+CARBON_SEM_IR_INST_KIND(Temporary)
+CARBON_SEM_IR_INST_KIND(TupleAccess)
+CARBON_SEM_IR_INST_KIND(TupleIndex)
+CARBON_SEM_IR_INST_KIND(TupleInit)
+CARBON_SEM_IR_INST_KIND(TupleLiteral)
+CARBON_SEM_IR_INST_KIND(TupleType)
+CARBON_SEM_IR_INST_KIND(TupleValue)
+CARBON_SEM_IR_INST_KIND(UnaryOperatorNot)
+CARBON_SEM_IR_INST_KIND(UnboundFieldType)
+CARBON_SEM_IR_INST_KIND(ValueAsReference)
+CARBON_SEM_IR_INST_KIND(ValueOfInitializer)
+CARBON_SEM_IR_INST_KIND(VarStorage)
 
-#undef CARBON_SEM_IR_NODE_KIND
+#undef CARBON_SEM_IR_INST_KIND

+ 45 - 42
toolchain/sem_ir/node_kind.h

@@ -12,102 +12,105 @@
 
 namespace Carbon::SemIR {
 
-// Whether a node produces or represents a value, and if so, what kind of value.
-enum class NodeValueKind : int8_t {
-  // This node doesn't produce a value, and shouldn't be referenced by other
-  // nodes.
+// Whether an instruction produces or represents a value, and if so, what kind
+// of value.
+enum class InstValueKind : int8_t {
+  // This instruction doesn't produce a value, and shouldn't be referenced by
+  // other
+  // instructions.
   None,
-  // This node represents an expression or expression-like construct that
+  // This instruction represents an expression or expression-like construct that
   // produces a value of the type indicated by its `type_id` field.
   Typed,
 };
 
-// Whether a node is a terminator or part of the terminator sequence. The nodes
-// in a block appear in the order NotTerminator, then TerminatorSequence, then
-// Terminator, which is also the numerical order of these values.
+// Whether an instruction is a terminator or part of the terminator sequence.
+// The instructions in a block appear in the order NotTerminator, then
+// TerminatorSequence, then Terminator, which is also the numerical order of
+// these values.
 enum class TerminatorKind : int8_t {
-  // This node is not a terminator.
+  // This instruction is not a terminator.
   NotTerminator,
-  // This node is not itself a terminator, but forms part of a terminator
+  // This instruction is not itself a terminator, but forms part of a terminator
   // sequence.
   TerminatorSequence,
-  // This node is a terminator.
+  // This instruction is a terminator.
   Terminator,
 };
 
-CARBON_DEFINE_RAW_ENUM_CLASS(NodeKind, uint8_t) {
-#define CARBON_SEM_IR_NODE_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
+CARBON_DEFINE_RAW_ENUM_CLASS(InstKind, uint8_t) {
+#define CARBON_SEM_IR_INST_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
 #include "toolchain/sem_ir/node_kind.def"
 };
 
-class NodeKind : public CARBON_ENUM_BASE(NodeKind) {
+class InstKind : public CARBON_ENUM_BASE(InstKind) {
  public:
-#define CARBON_SEM_IR_NODE_KIND(Name) CARBON_ENUM_CONSTANT_DECLARATION(Name)
+#define CARBON_SEM_IR_INST_KIND(Name) CARBON_ENUM_CONSTANT_DECLARATION(Name)
 #include "toolchain/sem_ir/node_kind.def"
 
   using EnumBase::Create;
 
-  // Returns the name to use for this node kind in Semantics IR.
+  // Returns the name to use for this instruction kind in Semantics IR.
   [[nodiscard]] auto ir_name() const -> llvm::StringLiteral;
 
-  // Returns whether this kind of node is expected to produce a value.
-  [[nodiscard]] auto value_kind() const -> NodeValueKind;
+  // Returns whether this kind of instruction is expected to produce a value.
+  [[nodiscard]] auto value_kind() const -> InstValueKind;
 
-  // Returns whether this node kind is a code block terminator, such as an
-  // unconditional branch instruction, or part of the termination sequence,
+  // Returns whether this instruction kind is a code block terminator, such as
+  // an unconditional branch instruction, or part of the termination sequence,
   // such as a conditional branch instruction. The termination sequence of a
   // code block appears after all other instructions, and ends with a
   // terminator instruction.
   [[nodiscard]] auto terminator_kind() const -> TerminatorKind;
 
-  // Compute a fingerprint for this node kind, allowing its use as part of the
-  // key in a `FoldingSet`.
+  // Compute a fingerprint for this instruction kind, allowing its use as part
+  // of the key in a `FoldingSet`.
   void Profile(llvm::FoldingSetNodeID& id) { id.AddInteger(AsInt()); }
 
   class Definition;
 
-  // Provides a definition for this node kind. Should only be called once, to
-  // construct the kind as part of defining it in `typed_nodes.h`.
+  // Provides a definition for this instruction kind. Should only be called
+  // once, to construct the kind as part of defining it in `typed_insts.h`.
   constexpr auto Define(llvm::StringLiteral ir_name,
                         TerminatorKind terminator_kind =
                             TerminatorKind::NotTerminator) const -> Definition;
 
  private:
-  // Looks up the definition for this node kind.
+  // Looks up the definition for this instruction kind.
   [[nodiscard]] auto definition() const -> const Definition&;
 };
 
-#define CARBON_SEM_IR_NODE_KIND(Name) \
-  CARBON_ENUM_CONSTANT_DEFINITION(NodeKind, Name)
+#define CARBON_SEM_IR_INST_KIND(Name) \
+  CARBON_ENUM_CONSTANT_DEFINITION(InstKind, Name)
 #include "toolchain/sem_ir/node_kind.def"
 
-// We expect the node kind to fit compactly into 8 bits.
-static_assert(sizeof(NodeKind) == 1, "Kind objects include padding!");
+// We expect the instruction kind to fit compactly into 8 bits.
+static_assert(sizeof(InstKind) == 1, "Kind objects include padding!");
 
-// A definition of a node kind. This is a NodeKind value, plus ancillary data
-// such as the name to use for the node kind in LLVM IR. These are not
-// copyable, and only one instance of this type is expected to exist per node
-// kind, specifically `TypedNode::Kind`. Use `NodeKind` instead as a thin
-// wrapper around a node kind index.
-class NodeKind::Definition : public NodeKind {
+// A definition of an instruction kind. This is an InstKind value, plus
+// ancillary data such as the name to use for the node kind in LLVM IR. These
+// are not copyable, and only one instance of this type is expected to exist per
+// instruction kind, specifically `TypedInst::Kind`. Use `InstKind` instead as a
+// thin wrapper around an instruction kind index.
+class InstKind::Definition : public InstKind {
  public:
-  // Returns the name to use for this node kind in Semantics IR.
+  // Returns the name to use for this instruction kind in Semantics IR.
   [[nodiscard]] constexpr auto ir_name() const -> llvm::StringLiteral {
     return ir_name_;
   }
 
-  // Returns whether this node kind is a code block terminator. See
-  // NodeKind::terminator_kind().
+  // Returns whether this instruction kind is a code block terminator. See
+  // InstKind::terminator_kind().
   [[nodiscard]] constexpr auto terminator_kind() const -> TerminatorKind {
     return terminator_kind_;
   }
 
  private:
-  friend class NodeKind;
+  friend class InstKind;
 
-  constexpr Definition(NodeKind kind, llvm::StringLiteral ir_name,
+  constexpr Definition(InstKind kind, llvm::StringLiteral ir_name,
                        TerminatorKind terminator_kind)
-      : NodeKind(kind), ir_name_(ir_name), terminator_kind_(terminator_kind) {}
+      : InstKind(kind), ir_name_(ir_name), terminator_kind_(terminator_kind) {}
 
   // Not copyable.
   Definition(const Definition&) = delete;
@@ -117,7 +120,7 @@ class NodeKind::Definition : public NodeKind {
   TerminatorKind terminator_kind_;
 };
 
-constexpr auto NodeKind::Define(llvm::StringLiteral ir_name,
+constexpr auto InstKind::Define(llvm::StringLiteral ir_name,
                                 TerminatorKind terminator_kind) const
     -> Definition {
   return Definition(*this, ir_name, terminator_kind);

+ 135 - 134
toolchain/sem_ir/typed_nodes.h → toolchain/sem_ir/typed_insts.h

@@ -2,55 +2,55 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#ifndef CARBON_TOOLCHAIN_SEM_IR_TYPED_NODES_H_
-#define CARBON_TOOLCHAIN_SEM_IR_TYPED_NODES_H_
+#ifndef CARBON_TOOLCHAIN_SEM_IR_TYPED_INSTS_H_
+#define CARBON_TOOLCHAIN_SEM_IR_TYPED_INSTS_H_
 
 #include "toolchain/parse/tree.h"
 #include "toolchain/sem_ir/builtin_kind.h"
 #include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/node_kind.h"
 
-// Representations for specific kinds of nodes.
+// Representations for specific kinds of instructions.
 //
 // Each type should be a struct with up to four members:
 //
-// - Optionally, a `Parse::Node parse_node;` member, for nodes with an
-//   associated location. Almost all nodes should have this, with exceptions
-//   being things that are generated internally, without any relation to source
-//   syntax, such as predeclared builtins.
-// - Optionally, a `TypeId type_id;` member, for nodes that produce a value.
-//   This includes nodes that produce an abstract value, such as a `Namespace`,
-//   for which a placeholder type should be used.
+// - Optionally, a `Parse::Node parse_node;` member, for instructions with an
+//   associated location. Almost all instructions should have this, with
+//   exceptions being things that are generated internally, without any relation
+//   to source syntax, such as predeclared builtins.
+// - Optionally, a `TypeId type_id;` member, for instructions that produce a
+//   value. This includes instructions that produce an abstract value, such as a
+//   `Namespace`, for which a placeholder type should be used.
 // - Up to two `[...]Id` members describing the contents of the struct.
 //
 // The field names here matter -- the first two fields must have the names
-// specified above, when present. When converting to a `SemIR::Node`, they will
-// become the parse node and type associated with the type-erased node.
+// specified above, when present. When converting to a `SemIR::Inst`, they will
+// become the parse node and type associated with the type-erased instruction.
 //
 // In addition, each type provides a constant `Kind` that associates the type
-// with a particular member of the `NodeKind` enumeration. This `Kind`
-// declaration also defines the node kind by calling `NodeKind::Define` and
-// specifying additional information about the node kind. This information is
-// available through the member functions of the `NodeKind` value declared in
-// `node_kind.h`, and includes the name used in textual IR and whether the node
-// is a terminator instruction.
+// with a particular member of the `InstKind` enumeration. This `Kind`
+// declaration also defines the instruction kind by calling `InstKind::Define`
+// and specifying additional information about the instruction kind. This
+// information is available through the member functions of the `InstKind` value
+// declared in `inst_kind.h`, and includes the name used in textual IR and
+// whether the instruction is a terminator instruction.
 namespace Carbon::SemIR {
 
 struct AddressOf {
-  static constexpr auto Kind = NodeKind::AddressOf.Define("address_of");
+  static constexpr auto Kind = InstKind::AddressOf.Define("address_of");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId lvalue_id;
+  InstId lvalue_id;
 };
 
 struct ArrayIndex {
-  static constexpr auto Kind = NodeKind::ArrayIndex.Define("array_index");
+  static constexpr auto Kind = InstKind::ArrayIndex.Define("array_index");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId array_id;
-  NodeId index_id;
+  InstId array_id;
+  InstId index_id;
 };
 
 // Initializes an array from a tuple. `tuple_id` is the source tuple
@@ -58,20 +58,20 @@ struct ArrayIndex {
 // element, plus a final element that is the return slot for the
 // initialization.
 struct ArrayInit {
-  static constexpr auto Kind = NodeKind::ArrayInit.Define("array_init");
+  static constexpr auto Kind = InstKind::ArrayInit.Define("array_init");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId tuple_id;
-  NodeBlockId inits_and_return_slot_id;
+  InstId tuple_id;
+  InstBlockId inits_and_return_slot_id;
 };
 
 struct ArrayType {
-  static constexpr auto Kind = NodeKind::ArrayType.Define("array_type");
+  static constexpr auto Kind = InstKind::ArrayType.Define("array_type");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId bound_id;
+  InstId bound_id;
   TypeId element_type_id;
 };
 
@@ -79,50 +79,50 @@ struct ArrayType {
 // `rhs_id`. This finishes initialization of `lhs_id` in the same way as
 // `InitializeFrom`.
 struct Assign {
-  static constexpr auto Kind = NodeKind::Assign.Define("assign");
+  static constexpr auto Kind = InstKind::Assign.Define("assign");
 
   Parse::Node parse_node;
   // Assignments are statements, and so have no type.
-  NodeId lhs_id;
-  NodeId rhs_id;
+  InstId lhs_id;
+  InstId rhs_id;
 };
 
 struct BinaryOperatorAdd {
-  static constexpr auto Kind = NodeKind::BinaryOperatorAdd.Define("add");
+  static constexpr auto Kind = InstKind::BinaryOperatorAdd.Define("add");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId lhs_id;
-  NodeId rhs_id;
+  InstId lhs_id;
+  InstId rhs_id;
 };
 
 struct BindName {
-  static constexpr auto Kind = NodeKind::BindName.Define("bind_name");
+  static constexpr auto Kind = InstKind::BindName.Define("bind_name");
 
   Parse::Node parse_node;
   TypeId type_id;
   StringId name_id;
-  NodeId value_id;
+  InstId value_id;
 };
 
 struct BindValue {
-  static constexpr auto Kind = NodeKind::BindValue.Define("bind_value");
+  static constexpr auto Kind = InstKind::BindValue.Define("bind_value");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId value_id;
+  InstId value_id;
 };
 
 struct BlockArg {
-  static constexpr auto Kind = NodeKind::BlockArg.Define("block_arg");
+  static constexpr auto Kind = InstKind::BlockArg.Define("block_arg");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeBlockId block_id;
+  InstBlockId block_id;
 };
 
 struct BoolLiteral {
-  static constexpr auto Kind = NodeKind::BoolLiteral.Define("bool_literal");
+  static constexpr auto Kind = InstKind::BoolLiteral.Define("bool_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -132,48 +132,48 @@ struct BoolLiteral {
 // A bound method, that combines a function with the value to use for its
 // `self` parameter, such as `object.MethodName`.
 struct BoundMethod {
-  static constexpr auto Kind = NodeKind::BoundMethod.Define("bound_method");
+  static constexpr auto Kind = InstKind::BoundMethod.Define("bound_method");
 
   Parse::Node parse_node;
   TypeId type_id;
   // The object argument in the bound method, which will be used to initialize
   // `self`, or whose address will be used to initialize `self` for an `addr
   // self` parameter.
-  NodeId object_id;
-  NodeId function_id;
+  InstId object_id;
+  InstId function_id;
 };
 
 struct Branch {
   static constexpr auto Kind =
-      NodeKind::Branch.Define("br", TerminatorKind::Terminator);
+      InstKind::Branch.Define("br", TerminatorKind::Terminator);
 
   Parse::Node parse_node;
   // Branches don't produce a value, so have no type.
-  NodeBlockId target_id;
+  InstBlockId target_id;
 };
 
 struct BranchIf {
   static constexpr auto Kind =
-      NodeKind::BranchIf.Define("br", TerminatorKind::TerminatorSequence);
+      InstKind::BranchIf.Define("br", TerminatorKind::TerminatorSequence);
 
   Parse::Node parse_node;
   // Branches don't produce a value, so have no type.
-  NodeBlockId target_id;
-  NodeId cond_id;
+  InstBlockId target_id;
+  InstId cond_id;
 };
 
 struct BranchWithArg {
   static constexpr auto Kind =
-      NodeKind::BranchWithArg.Define("br", TerminatorKind::Terminator);
+      InstKind::BranchWithArg.Define("br", TerminatorKind::Terminator);
 
   Parse::Node parse_node;
   // Branches don't produce a value, so have no type.
-  NodeBlockId target_id;
-  NodeId arg_id;
+  InstBlockId target_id;
+  InstId arg_id;
 };
 
 struct Builtin {
-  static constexpr auto Kind = NodeKind::Builtin.Define("builtin");
+  static constexpr auto Kind = InstKind::Builtin.Define("builtin");
 
   // Builtins don't have a parse node associated with them.
   TypeId type_id;
@@ -181,21 +181,21 @@ struct Builtin {
 };
 
 struct Call {
-  static constexpr auto Kind = NodeKind::Call.Define("call");
+  static constexpr auto Kind = InstKind::Call.Define("call");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId callee_id;
+  InstId callee_id;
   // The arguments block contains IDs for the following arguments, in order:
   //  - The argument for each implicit parameter.
   //  - The argument for each explicit parameter.
   //  - The argument for the return slot, if present.
-  NodeBlockId args_id;
+  InstBlockId args_id;
 };
 
 struct ClassDeclaration {
   static constexpr auto Kind =
-      NodeKind::ClassDeclaration.Define("class_declaration");
+      InstKind::ClassDeclaration.Define("class_declaration");
 
   Parse::Node parse_node;
   // No type: a class declaration is not itself a value. The name of a class
@@ -205,21 +205,21 @@ struct ClassDeclaration {
   ClassId class_id;
   // The declaration block, containing the class name's qualifiers and the
   // class's generic parameters.
-  NodeBlockId decl_block_id;
+  InstBlockId decl_block_id;
 };
 
 struct ClassFieldAccess {
   static constexpr auto Kind =
-      NodeKind::ClassFieldAccess.Define("class_field_access");
+      InstKind::ClassFieldAccess.Define("class_field_access");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId base_id;
+  InstId base_id;
   MemberIndex index;
 };
 
 struct ClassType {
-  static constexpr auto Kind = NodeKind::ClassType.Define("class_type");
+  static constexpr auto Kind = InstKind::ClassType.Define("class_type");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -228,7 +228,7 @@ struct ClassType {
 };
 
 struct ConstType {
-  static constexpr auto Kind = NodeKind::ConstType.Define("const_type");
+  static constexpr auto Kind = InstKind::ConstType.Define("const_type");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -237,28 +237,28 @@ struct ConstType {
 
 // A cross-reference between IRs.
 struct CrossReference {
-  static constexpr auto Kind = NodeKind::CrossReference.Define("xref");
+  static constexpr auto Kind = InstKind::CrossReference.Define("xref");
 
-  // No parse node: a node's parse tree node must refer to a node in the
-  // current parse tree. This cannot use the cross-referenced node's parse tree
-  // node because it will be in a different parse tree.
+  // No parse node: an instruction's parse tree node must refer to a node in the
+  // current parse tree. This cannot use the cross-referenced instruction's
+  // parse tree node because it will be in a different parse tree.
   TypeId type_id;
   CrossReferenceIRId ir_id;
-  NodeId node_id;
+  InstId inst_id;
 };
 
 struct Dereference {
-  static constexpr auto Kind = NodeKind::Dereference.Define("dereference");
+  static constexpr auto Kind = InstKind::Dereference.Define("dereference");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId pointer_id;
+  InstId pointer_id;
 };
 
 // A field in a class, of the form `var field: field_type;`. The type of the
-// `Field` node is an `UnboundFieldType`.
+// `Field` instruction is an `UnboundFieldType`.
 struct Field {
-  static constexpr auto Kind = NodeKind::Field.Define("field");
+  static constexpr auto Kind = InstKind::Field.Define("field");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -267,7 +267,7 @@ struct Field {
 };
 
 struct FunctionDeclaration {
-  static constexpr auto Kind = NodeKind::FunctionDeclaration.Define("fn_decl");
+  static constexpr auto Kind = InstKind::FunctionDeclaration.Define("fn_decl");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -279,16 +279,16 @@ struct FunctionDeclaration {
 // whose initialization is not in-place.
 struct InitializeFrom {
   static constexpr auto Kind =
-      NodeKind::InitializeFrom.Define("initialize_from");
+      InstKind::InitializeFrom.Define("initialize_from");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId src_id;
-  NodeId dest_id;
+  InstId src_id;
+  InstId dest_id;
 };
 
 struct IntegerLiteral {
-  static constexpr auto Kind = NodeKind::IntegerLiteral.Define("int_literal");
+  static constexpr auto Kind = InstKind::IntegerLiteral.Define("int_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -296,16 +296,16 @@ struct IntegerLiteral {
 };
 
 struct NameReference {
-  static constexpr auto Kind = NodeKind::NameReference.Define("name_reference");
+  static constexpr auto Kind = InstKind::NameReference.Define("name_reference");
 
   Parse::Node parse_node;
   TypeId type_id;
   StringId name_id;
-  NodeId value_id;
+  InstId value_id;
 };
 
 struct Namespace {
-  static constexpr auto Kind = NodeKind::Namespace.Define("namespace");
+  static constexpr auto Kind = InstKind::Namespace.Define("namespace");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -313,14 +313,14 @@ struct Namespace {
 };
 
 struct NoOp {
-  static constexpr auto Kind = NodeKind::NoOp.Define("no_op");
+  static constexpr auto Kind = InstKind::NoOp.Define("no_op");
 
   Parse::Node parse_node;
-  // This node doesn't produce a value, so has no type.
+  // This instruction doesn't produce a value, so has no type.
 };
 
 struct Parameter {
-  static constexpr auto Kind = NodeKind::Parameter.Define("parameter");
+  static constexpr auto Kind = InstKind::Parameter.Define("parameter");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -328,7 +328,7 @@ struct Parameter {
 };
 
 struct PointerType {
-  static constexpr auto Kind = NodeKind::PointerType.Define("ptr_type");
+  static constexpr auto Kind = InstKind::PointerType.Define("ptr_type");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -336,7 +336,7 @@ struct PointerType {
 };
 
 struct RealLiteral {
-  static constexpr auto Kind = NodeKind::RealLiteral.Define("real_literal");
+  static constexpr auto Kind = InstKind::RealLiteral.Define("real_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -345,7 +345,7 @@ struct RealLiteral {
 
 struct Return {
   static constexpr auto Kind =
-      NodeKind::Return.Define("return", TerminatorKind::Terminator);
+      InstKind::Return.Define("return", TerminatorKind::Terminator);
 
   Parse::Node parse_node;
   // This is a statement, so has no type.
@@ -353,15 +353,15 @@ struct Return {
 
 struct ReturnExpression {
   static constexpr auto Kind =
-      NodeKind::ReturnExpression.Define("return", TerminatorKind::Terminator);
+      InstKind::ReturnExpression.Define("return", TerminatorKind::Terminator);
 
   Parse::Node parse_node;
   // This is a statement, so has no type.
-  NodeId expr_id;
+  InstId expr_id;
 };
 
 struct SelfParameter {
-  static constexpr auto Kind = NodeKind::SelfParameter.Define("self_parameter");
+  static constexpr auto Kind = InstKind::SelfParameter.Define("self_parameter");
   static constexpr llvm::StringLiteral Name = "self";
 
   Parse::Node parse_node;
@@ -370,16 +370,16 @@ struct SelfParameter {
 };
 
 struct SpliceBlock {
-  static constexpr auto Kind = NodeKind::SpliceBlock.Define("splice_block");
+  static constexpr auto Kind = InstKind::SpliceBlock.Define("splice_block");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeBlockId block_id;
-  NodeId result_id;
+  InstBlockId block_id;
+  InstId result_id;
 };
 
 struct StringLiteral {
-  static constexpr auto Kind = NodeKind::StringLiteral.Define("string_literal");
+  static constexpr auto Kind = InstKind::StringLiteral.Define("string_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -387,113 +387,114 @@ struct StringLiteral {
 };
 
 struct StructAccess {
-  static constexpr auto Kind = NodeKind::StructAccess.Define("struct_access");
+  static constexpr auto Kind = InstKind::StructAccess.Define("struct_access");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId struct_id;
+  InstId struct_id;
   MemberIndex index;
 };
 
 struct StructInit {
-  static constexpr auto Kind = NodeKind::StructInit.Define("struct_init");
+  static constexpr auto Kind = InstKind::StructInit.Define("struct_init");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId src_id;
-  NodeBlockId elements_id;
+  InstId src_id;
+  InstBlockId elements_id;
 };
 
 struct StructLiteral {
-  static constexpr auto Kind = NodeKind::StructLiteral.Define("struct_literal");
+  static constexpr auto Kind = InstKind::StructLiteral.Define("struct_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeBlockId elements_id;
+  InstBlockId elements_id;
 };
 
 struct StructType {
-  static constexpr auto Kind = NodeKind::StructType.Define("struct_type");
+  static constexpr auto Kind = InstKind::StructType.Define("struct_type");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeBlockId fields_id;
+  InstBlockId fields_id;
 };
 
 struct StructTypeField {
   static constexpr auto Kind =
-      NodeKind::StructTypeField.Define("struct_type_field");
+      InstKind::StructTypeField.Define("struct_type_field");
 
   Parse::Node parse_node;
-  // This node is an implementation detail of `StructType`, and doesn't produce
-  // a value, so has no type, even though it declares a field with a type.
+  // This instruction is an implementation detail of `StructType`, and doesn't
+  // produce a value, so has no type, even though it declares a field with a
+  // type.
   StringId name_id;
   TypeId field_type_id;
 };
 
 struct StructValue {
-  static constexpr auto Kind = NodeKind::StructValue.Define("struct_value");
+  static constexpr auto Kind = InstKind::StructValue.Define("struct_value");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId src_id;
-  NodeBlockId elements_id;
+  InstId src_id;
+  InstBlockId elements_id;
 };
 
 struct Temporary {
-  static constexpr auto Kind = NodeKind::Temporary.Define("temporary");
+  static constexpr auto Kind = InstKind::Temporary.Define("temporary");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId storage_id;
-  NodeId init_id;
+  InstId storage_id;
+  InstId init_id;
 };
 
 struct TemporaryStorage {
   static constexpr auto Kind =
-      NodeKind::TemporaryStorage.Define("temporary_storage");
+      InstKind::TemporaryStorage.Define("temporary_storage");
 
   Parse::Node parse_node;
   TypeId type_id;
 };
 
 struct TupleAccess {
-  static constexpr auto Kind = NodeKind::TupleAccess.Define("tuple_access");
+  static constexpr auto Kind = InstKind::TupleAccess.Define("tuple_access");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId tuple_id;
+  InstId tuple_id;
   MemberIndex index;
 };
 
 struct TupleIndex {
-  static constexpr auto Kind = NodeKind::TupleIndex.Define("tuple_index");
+  static constexpr auto Kind = InstKind::TupleIndex.Define("tuple_index");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId tuple_id;
-  NodeId index_id;
+  InstId tuple_id;
+  InstId index_id;
 };
 
 struct TupleInit {
-  static constexpr auto Kind = NodeKind::TupleInit.Define("tuple_init");
+  static constexpr auto Kind = InstKind::TupleInit.Define("tuple_init");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId src_id;
-  NodeBlockId elements_id;
+  InstId src_id;
+  InstBlockId elements_id;
 };
 
 struct TupleLiteral {
-  static constexpr auto Kind = NodeKind::TupleLiteral.Define("tuple_literal");
+  static constexpr auto Kind = InstKind::TupleLiteral.Define("tuple_literal");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeBlockId elements_id;
+  InstBlockId elements_id;
 };
 
 struct TupleType {
-  static constexpr auto Kind = NodeKind::TupleType.Define("tuple_type");
+  static constexpr auto Kind = InstKind::TupleType.Define("tuple_type");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -501,20 +502,20 @@ struct TupleType {
 };
 
 struct TupleValue {
-  static constexpr auto Kind = NodeKind::TupleValue.Define("tuple_value");
+  static constexpr auto Kind = InstKind::TupleValue.Define("tuple_value");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId src_id;
-  NodeBlockId elements_id;
+  InstId src_id;
+  InstBlockId elements_id;
 };
 
 struct UnaryOperatorNot {
-  static constexpr auto Kind = NodeKind::UnaryOperatorNot.Define("not");
+  static constexpr auto Kind = InstKind::UnaryOperatorNot.Define("not");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId operand_id;
+  InstId operand_id;
 };
 
 // The type of an expression naming an unbound field, such as `Class.field`.
@@ -522,7 +523,7 @@ struct UnaryOperatorNot {
 // such as `instance.(Class.field)`.
 struct UnboundFieldType {
   static constexpr auto Kind =
-      NodeKind::UnboundFieldType.Define("unbound_field_type");
+      InstKind::UnboundFieldType.Define("unbound_field_type");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -534,24 +535,24 @@ struct UnboundFieldType {
 
 struct ValueAsReference {
   static constexpr auto Kind =
-      NodeKind::ValueAsReference.Define("value_as_reference");
+      InstKind::ValueAsReference.Define("value_as_reference");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId value_id;
+  InstId value_id;
 };
 
 struct ValueOfInitializer {
   static constexpr auto Kind =
-      NodeKind::ValueOfInitializer.Define("value_of_initializer");
+      InstKind::ValueOfInitializer.Define("value_of_initializer");
 
   Parse::Node parse_node;
   TypeId type_id;
-  NodeId init_id;
+  InstId init_id;
 };
 
 struct VarStorage {
-  static constexpr auto Kind = NodeKind::VarStorage.Define("var");
+  static constexpr auto Kind = InstKind::VarStorage.Define("var");
 
   Parse::Node parse_node;
   TypeId type_id;
@@ -572,4 +573,4 @@ constexpr bool HasTypeId<T, decltype(&T::type_id)> = true;
 
 }  // namespace Carbon::SemIR
 
-#endif  // CARBON_TOOLCHAIN_SEM_IR_TYPED_NODES_H_
+#endif  // CARBON_TOOLCHAIN_SEM_IR_TYPED_INSTS_H_

+ 71 - 70
toolchain/sem_ir/typed_nodes_test.cpp

@@ -2,21 +2,20 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-#include "toolchain/sem_ir/typed_nodes.h"
-
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
+#include "toolchain/sem_ir/typed_insts.h"
 
 namespace Carbon::SemIR {
 
-// A friend of `SemIR::Node` that is used to pierce the abstraction.
-class NodeTestHelper {
+// A friend of `SemIR::Inst` that is used to pierce the abstraction.
+class InstTestHelper {
  public:
-  static auto MakeNode(NodeKind node_kind, Parse::Node parse_node,
-                       TypeId type_id, int32_t arg0, int32_t arg1) -> Node {
-    return Node(node_kind, parse_node, type_id, arg0, arg1);
+  static auto MakeInst(InstKind inst_kind, Parse::Node parse_node,
+                       TypeId type_id, int32_t arg0, int32_t arg1) -> Inst {
+    return Inst(inst_kind, parse_node, type_id, arg0, arg1);
   }
 };
 
@@ -25,120 +24,122 @@ class NodeTestHelper {
 namespace Carbon::SemIR {
 namespace {
 
-// Check that each node kind defines a Kind member using the correct NodeKind
-// enumerator.
-#define CARBON_SEM_IR_NODE_KIND(Name) \
-  static_assert(Name::Kind == NodeKind::Name);
+// Check that each instruction kind defines a Kind member using the correct
+// InstKind enumerator.
+#define CARBON_SEM_IR_INST_KIND(Name) \
+  static_assert(Name::Kind == InstKind::Name);
 #include "toolchain/sem_ir/node_kind.def"
 
 template <typename Ignored, typename... Types>
 using TypesExceptFirst = ::testing::Types<Types...>;
 
-// Form a list of all typed node types. Use `TypesExceptFirst` and a leading
-// `void` to handle the problem that we only want N-1 commas in this list.
-using TypedNodeTypes = TypesExceptFirst<void
-#define CARBON_SEM_IR_NODE_KIND(Name) , Name
+// Form a list of all typed instruction types. Use `TypesExceptFirst` and a
+// leading `void` to handle the problem that we only want N-1 commas in this
+// list.
+using TypedInstTypes = TypesExceptFirst<void
+#define CARBON_SEM_IR_INST_KIND(Name) , Name
 #include "toolchain/sem_ir/node_kind.def"
                                         >;
 
 // Set up the test fixture.
-template <typename TypedNode>
-class TypedNodeTest : public testing::Test {};
+template <typename TypedInst>
+class TypedInstTest : public testing::Test {};
 
-TYPED_TEST_SUITE(TypedNodeTest, TypedNodeTypes);
+TYPED_TEST_SUITE(TypedInstTest, TypedInstTypes);
 
-TYPED_TEST(TypedNodeTest, CommonFieldOrder) {
-  using TypedNode = TypeParam;
+TYPED_TEST(TypedInstTest, CommonFieldOrder) {
+  using TypedInst = TypeParam;
 
-  Node node = NodeTestHelper::MakeNode(TypeParam::Kind, Parse::Node(1),
+  Inst inst = InstTestHelper::MakeInst(TypeParam::Kind, Parse::Node(1),
                                        TypeId(2), 3, 4);
-  EXPECT_EQ(node.kind(), TypeParam::Kind);
-  EXPECT_EQ(node.parse_node(), Parse::Node(1));
-  EXPECT_EQ(node.type_id(), TypeId(2));
+  EXPECT_EQ(inst.kind(), TypeParam::Kind);
+  EXPECT_EQ(inst.parse_node(), Parse::Node(1));
+  EXPECT_EQ(inst.type_id(), TypeId(2));
 
-  TypedNode typed = node.As<TypedNode>();
-  if constexpr (HasParseNode<TypedNode>) {
+  TypedInst typed = inst.As<TypedInst>();
+  if constexpr (HasParseNode<TypedInst>) {
     EXPECT_EQ(typed.parse_node, Parse::Node(1));
   }
-  if constexpr (HasTypeId<TypedNode>) {
+  if constexpr (HasTypeId<TypedInst>) {
     EXPECT_EQ(typed.type_id, TypeId(2));
   }
 }
 
-TYPED_TEST(TypedNodeTest, RoundTrip) {
-  using TypedNode = TypeParam;
+TYPED_TEST(TypedInstTest, RoundTrip) {
+  using TypedInst = TypeParam;
 
-  Node node1 = NodeTestHelper::MakeNode(TypeParam::Kind, Parse::Node(1),
+  Inst inst1 = InstTestHelper::MakeInst(TypeParam::Kind, Parse::Node(1),
                                         TypeId(2), 3, 4);
-  EXPECT_EQ(node1.kind(), TypeParam::Kind);
-  EXPECT_EQ(node1.parse_node(), Parse::Node(1));
-  EXPECT_EQ(node1.type_id(), TypeId(2));
+  EXPECT_EQ(inst1.kind(), TypeParam::Kind);
+  EXPECT_EQ(inst1.parse_node(), Parse::Node(1));
+  EXPECT_EQ(inst1.type_id(), TypeId(2));
 
-  TypedNode typed1 = node1.As<TypedNode>();
-  Node node2 = typed1;
+  TypedInst typed1 = inst1.As<TypedInst>();
+  Inst inst2 = typed1;
 
-  EXPECT_EQ(node1.kind(), node2.kind());
-  if constexpr (HasParseNode<TypedNode>) {
-    EXPECT_EQ(node1.parse_node(), node2.parse_node());
+  EXPECT_EQ(inst1.kind(), inst2.kind());
+  if constexpr (HasParseNode<TypedInst>) {
+    EXPECT_EQ(inst1.parse_node(), inst2.parse_node());
   }
-  if constexpr (HasTypeId<TypedNode>) {
-    EXPECT_EQ(node1.type_id(), node2.type_id());
+  if constexpr (HasTypeId<TypedInst>) {
+    EXPECT_EQ(inst1.type_id(), inst2.type_id());
   }
 
-  // If the typed node has no padding, we should get exactly the same thing
-  // if we convert back from a node.
-  TypedNode typed2 = node2.As<TypedNode>();
-  if constexpr (std::has_unique_object_representations_v<TypedNode>) {
-    EXPECT_EQ(std::memcmp(&typed1, &typed2, sizeof(TypedNode)), 0);
+  // If the typed instruction has no padding, we should get exactly the same
+  // thing if we convert back from an instruction.
+  TypedInst typed2 = inst2.As<TypedInst>();
+  if constexpr (std::has_unique_object_representations_v<TypedInst>) {
+    EXPECT_EQ(std::memcmp(&typed1, &typed2, sizeof(TypedInst)), 0);
   }
 
-  // The original node might not be identical after one round trip, because the
-  // fields not carried by the typed node are lost. But they should be stable
-  // if we round-trip again.
-  Node node3 = typed2;
-  if constexpr (std::has_unique_object_representations_v<Node>) {
-    EXPECT_EQ(std::memcmp(&node2, &node3, sizeof(Node)), 0);
+  // The original instruction might not be identical after one round trip,
+  // because the fields not carried by the typed instruction are lost. But they
+  // should be stable if we round-trip again.
+  Inst inst3 = typed2;
+  if constexpr (std::has_unique_object_representations_v<Inst>) {
+    EXPECT_EQ(std::memcmp(&inst2, &inst3, sizeof(Inst)), 0);
   }
 }
 
-TYPED_TEST(TypedNodeTest, StructLayout) {
-  using TypedNode = TypeParam;
+TYPED_TEST(TypedInstTest, StructLayout) {
+  using TypedInst = TypeParam;
 
-  TypedNode typed =
-      NodeTestHelper::MakeNode(TypeParam::Kind, Parse::Node(1), TypeId(2), 3, 4)
-          .template As<TypedNode>();
+  TypedInst typed =
+      InstTestHelper::MakeInst(TypeParam::Kind, Parse::Node(1), TypeId(2), 3, 4)
+          .template As<TypedInst>();
 
-  // Check that the memory representation of the typed node is what we expect.
+  // Check that the memory representation of the typed instruction is what we
+  // expect.
   // TODO: Struct layout is not guaranteed, and this test could fail in some
   // build environment. If so, we should disable it.
   int32_t fields[4] = {};
   int field = 0;
-  if constexpr (HasParseNode<TypedNode>) {
+  if constexpr (HasParseNode<TypedInst>) {
     fields[field++] = 1;
   }
-  if constexpr (HasTypeId<TypedNode>) {
+  if constexpr (HasTypeId<TypedInst>) {
     fields[field++] = 2;
   }
   fields[field++] = 3;
   fields[field++] = 4;
 
-  ASSERT_LE(sizeof(TypedNode), sizeof(fields));
-  // We can only do this check if the typed node has no padding.
-  if constexpr (std::has_unique_object_representations_v<TypedNode>) {
-    EXPECT_EQ(std::memcmp(&fields, &typed, sizeof(TypedNode)), 0);
+  ASSERT_LE(sizeof(TypedInst), sizeof(fields));
+  // We can only do this check if the typed instruction has no padding.
+  if constexpr (std::has_unique_object_representations_v<TypedInst>) {
+    EXPECT_EQ(std::memcmp(&fields, &typed, sizeof(TypedInst)), 0);
   }
 }
 
-TYPED_TEST(TypedNodeTest, NodeKindMatches) {
-  using TypedNode = TypeParam;
+TYPED_TEST(TypedInstTest, InstKindMatches) {
+  using TypedInst = TypeParam;
 
-  // TypedNode::Kind is a NodeKind::Definition that extends NodeKind, but
+  // TypedInst::Kind is an InstKind::Definition that extends InstKind, but
   // has different definitions of the `ir_name()` and `terminator_kind()`
   // methods. Here we test that values returned by the two different versions
   // of those functions match.
-  NodeKind as_kind = TypedNode::Kind;
-  EXPECT_EQ(TypedNode::Kind.ir_name(), as_kind.ir_name());
-  EXPECT_EQ(TypedNode::Kind.terminator_kind(), as_kind.terminator_kind());
+  InstKind as_kind = TypedInst::Kind;
+  EXPECT_EQ(TypedInst::Kind.ir_name(), as_kind.ir_name());
+  EXPECT_EQ(TypedInst::Kind.terminator_kind(), as_kind.terminator_kind());
 }
 
 }  // namespace

+ 35 - 33
toolchain/sem_ir/value_stores.h

@@ -8,39 +8,41 @@
 #include "llvm/ADT/DenseMap.h"
 #include "toolchain/base/value_store.h"
 #include "toolchain/base/yaml.h"
-#include "toolchain/sem_ir/node.h"
+#include "toolchain/sem_ir/inst.h"
 
 namespace Carbon::SemIR {
 
-// Provides a ValueStore wrapper for an API specific to nodes.
-class NodeStore {
+// Provides a ValueStore wrapper for an API specific to instructions.
+class InstStore {
  public:
-  // Adds a node to the node list, returning an ID to reference the node. Note
-  // that this doesn't add the node to any node block. Check::Context::AddNode
-  // or NodeBlockStack::AddNode should usually be used instead, to add the node
-  // to the current block.
-  auto AddInNoBlock(Node node) -> NodeId { return values_.Add(node); }
-
-  // Returns the requested node.
-  auto Get(NodeId node_id) const -> Node { return values_.Get(node_id); }
-
-  // Returns the requested node, which is known to have the specified type.
-  template <typename NodeT>
-  auto GetAs(NodeId node_id) const -> NodeT {
-    return Get(node_id).As<NodeT>();
+  // Adds an instruction to the instruction list, returning an ID to reference
+  // the instruction. Note that this doesn't add the instruction to any
+  // instruction block. Check::Context::AddInst or InstBlockStack::AddInst
+  // should usually be used instead, to add the instruction to the current
+  // block.
+  auto AddInNoBlock(Inst inst) -> InstId { return values_.Add(inst); }
+
+  // Returns the requested instruction.
+  auto Get(InstId inst_id) const -> Inst { return values_.Get(inst_id); }
+
+  // Returns the requested instruction, which is known to have the specified
+  // type.
+  template <typename InstT>
+  auto GetAs(InstId inst_id) const -> InstT {
+    return Get(inst_id).As<InstT>();
   }
 
-  // Overwrites a given node with a new value.
-  auto Set(NodeId node_id, Node node) -> void { values_.Get(node_id) = node; }
+  // Overwrites a given instruction with a new value.
+  auto Set(InstId inst_id, Inst inst) -> void { values_.Get(inst_id) = inst; }
 
   // Reserves space.
   auto Reserve(size_t size) -> void { values_.Reserve(size); }
 
-  auto array_ref() const -> llvm::ArrayRef<Node> { return values_.array_ref(); }
+  auto array_ref() const -> llvm::ArrayRef<Inst> { return values_.array_ref(); }
   auto size() const -> int { return values_.size(); }
 
  private:
-  ValueStore<NodeId, Node> values_;
+  ValueStore<InstId, Inst> values_;
 };
 
 // Provides a ValueStore wrapper for an API specific to name scopes.
@@ -51,19 +53,19 @@ class NameScopeStore {
 
   // Adds an entry to a name scope. Returns true on success, false on
   // duplicates.
-  auto AddEntry(NameScopeId scope_id, StringId name_id, NodeId target_id)
+  auto AddEntry(NameScopeId scope_id, StringId name_id, InstId target_id)
       -> bool {
     return values_.Get(scope_id).insert({name_id, target_id}).second;
   }
 
   // Returns the requested name scope.
   auto Get(NameScopeId scope_id) const
-      -> const llvm::DenseMap<StringId, NodeId>& {
+      -> const llvm::DenseMap<StringId, InstId>& {
     return values_.Get(scope_id);
   }
 
  private:
-  ValueStore<NameScopeId, llvm::DenseMap<StringId, NodeId>> values_;
+  ValueStore<NameScopeId, llvm::DenseMap<StringId, InstId>> values_;
 };
 
 // Provides a block-based ValueStore, which uses slab allocation of added
@@ -109,17 +111,17 @@ class BlockValueStore : public Yaml::Printable<BlockValueStore<IdT, ValueT>> {
  protected:
   // Reserves and returns a block ID. The contents of the block
   // should be specified by calling Set, or similar.
-  auto AddDefaultValue() -> NodeBlockId { return values_.AddDefaultValue(); }
+  auto AddDefaultValue() -> InstBlockId { return values_.AddDefaultValue(); }
 
   // Adds an uninitialized block of the given size.
-  auto AddUninitialized(size_t size) -> NodeBlockId {
+  auto AddUninitialized(size_t size) -> InstBlockId {
     return values_.Add(AllocateUninitialized(size));
   }
 
   // Sets the contents of an empty block to the given content.
-  auto Set(NodeBlockId block_id, llvm::ArrayRef<NodeId> content) -> void {
+  auto Set(InstBlockId block_id, llvm::ArrayRef<InstId> content) -> void {
     CARBON_CHECK(Get(block_id).empty())
-        << "node block content set more than once";
+        << "inst block content set more than once";
     values_.Get(block_id) = AllocateCopy(content);
   }
 
@@ -147,18 +149,18 @@ class BlockValueStore : public Yaml::Printable<BlockValueStore<IdT, ValueT>> {
   ValueStore<IdT, llvm::MutableArrayRef<ValueT>> values_;
 };
 
-// Adapts BlockValueStore for node blocks.
-class NodeBlockStore : public BlockValueStore<NodeBlockId, NodeId> {
+// Adapts BlockValueStore for instruction blocks.
+class InstBlockStore : public BlockValueStore<InstBlockId, InstId> {
  public:
-  using BaseType = BlockValueStore<NodeBlockId, NodeId>;
+  using BaseType = BlockValueStore<InstBlockId, InstId>;
 
   using BaseType::AddDefaultValue;
   using BaseType::AddUninitialized;
   using BaseType::BaseType;
 
-  auto Set(NodeBlockId block_id, llvm::ArrayRef<NodeId> content) -> void {
-    CARBON_CHECK(block_id != NodeBlockId::Unreachable);
-    BlockValueStore<NodeBlockId, NodeId>::Set(block_id, content);
+  auto Set(InstBlockId block_id, llvm::ArrayRef<InstId> content) -> void {
+    CARBON_CHECK(block_id != InstBlockId::Unreachable);
+    BlockValueStore<InstBlockId, InstId>::Set(block_id, content);
   }
 };
 

+ 15 - 15
toolchain/sem_ir/yaml_test.cpp

@@ -38,14 +38,14 @@ TEST(SemIRTest, YAML) {
   d.RunCommand(
       {"compile", "--phase=check", "--dump-raw-sem-ir", "test.carbon"});
 
-  // Matches the ID of a node. The numbers may change because of builtin
+  // Matches the ID of an instruction. The numbers may change because of builtin
   // cross-references, so this code is only doing loose structural checks.
   auto integer_id = Yaml::Scalar(MatchesRegex(R"(int\d+)"));
-  auto node_id = Yaml::Scalar(MatchesRegex(R"(node\+\d+)"));
-  auto node_builtin = Yaml::Scalar(MatchesRegex(R"(node\w+)"));
+  auto inst_id = Yaml::Scalar(MatchesRegex(R"(inst\+\d+)"));
+  auto inst_builtin = Yaml::Scalar(MatchesRegex(R"(inst\w+)"));
   auto type_id = Yaml::Scalar(MatchesRegex(R"(type\d+)"));
   auto type_builtin = Pair(
-      type_id, Yaml::Mapping(ElementsAre(Pair("node", node_builtin),
+      type_id, Yaml::Mapping(ElementsAre(Pair("inst", inst_builtin),
                                          Pair("value_rep", Yaml::Mapping(_)))));
 
   auto file = Yaml::Mapping(ElementsAre(
@@ -54,30 +54,30 @@ TEST(SemIRTest, YAML) {
       Pair("classes", Yaml::Mapping(SizeIs(0))),
       Pair("types", Yaml::Mapping(Each(type_builtin))),
       Pair("type_blocks", Yaml::Mapping(IsEmpty())),
-      Pair("nodes",
+      Pair("insts",
            Yaml::Mapping(AllOf(
-               Each(Key(node_id)),
+               Each(Key(inst_id)),
                // kind is required, other parts are optional.
                Each(Pair(_, Yaml::Mapping(Contains(Pair("kind", _))))),
-               // A 0-arg node.
+               // A 0-arg instruction.
                Contains(
                    Pair(_, Yaml::Mapping(ElementsAre(Pair("kind", "Return"))))),
-               // A 1-arg node.
+               // A 1-arg instruction.
                Contains(Pair(
                    _, Yaml::Mapping(ElementsAre(Pair("kind", "IntegerLiteral"),
                                                 Pair("arg0", integer_id),
                                                 Pair("type", type_id))))),
-               // A 2-arg node.
+               // A 2-arg instruction.
                Contains(Pair(
                    _, Yaml::Mapping(ElementsAre(Pair("kind", "Assign"),
-                                                Pair("arg0", node_id),
-                                                Pair("arg1", node_id)))))))),
-      // This production has only two node blocks.
-      Pair("node_blocks",
+                                                Pair("arg0", inst_id),
+                                                Pair("arg1", inst_id)))))))),
+      // This production has only two instruction blocks.
+      Pair("inst_blocks",
            Yaml::Mapping(ElementsAre(
                Pair("block0", Yaml::Mapping(IsEmpty())),
-               Pair("block1", Yaml::Mapping(Each(Pair(_, node_id)))),
-               Pair("block2", Yaml::Mapping(Each(Pair(_, node_id)))))))));
+               Pair("block1", Yaml::Mapping(Each(Pair(_, inst_id)))),
+               Pair("block2", Yaml::Mapping(Each(Pair(_, inst_id)))))))));
 
   auto root = Yaml::Sequence(ElementsAre(Yaml::Mapping(
       ElementsAre(Pair("filename", "test.carbon"), Pair("sem_ir", file)))));