Refactor AddInst-family functions to their own file (#4941)

This in particular uses free functions because it's likely to end up
more consistent with types (versus a wrapper object for InstStore).
Note, this is unlikely to have a performance impact, but if it does, we
can look into related approaches (and we've already discussed using
LTO).

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