mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:40:12 +01:00
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:
@@ -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
@@ -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});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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_;
|
||||
|
||||
|
||||
@@ -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
@@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 +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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user