mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:50:14 +01:00
Remove inst_id from the public interface of ConstantId. (#4053)
Require mapping from a `ConstantId` to an `InstId` to go through the `ConstantValueStore`. This is a preparatory step for an upcoming generics change where symbolic `ConstantId`s are no longer just a thin wrapper around an `InstId` but instead are indexes into a table with additional information about the symbolic constant beyond its `InstId`.
This commit is contained in:
@@ -80,7 +80,7 @@ auto Context::AddInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst)
|
||||
auto const_id = TryEvalInst(*this, inst_id, loc_id_and_inst.inst);
|
||||
if (const_id.is_constant()) {
|
||||
CARBON_VLOG() << "Constant: " << loc_id_and_inst.inst << " -> "
|
||||
<< const_id.inst_id() << "\n";
|
||||
<< constant_values().GetInstId(const_id) << "\n";
|
||||
constant_values().Set(inst_id, const_id);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ auto Context::ReplaceLocIdAndInstBeforeConstantUse(
|
||||
auto const_id = TryEvalInst(*this, inst_id, loc_id_and_inst.inst);
|
||||
if (const_id.is_constant()) {
|
||||
CARBON_VLOG() << "Constant: " << loc_id_and_inst.inst << " -> "
|
||||
<< const_id.inst_id() << "\n";
|
||||
<< constant_values().GetInstId(const_id) << "\n";
|
||||
}
|
||||
constant_values().Set(inst_id, const_id);
|
||||
}
|
||||
@@ -144,8 +144,8 @@ auto Context::ReplaceInstBeforeConstantUse(SemIR::InstId inst_id,
|
||||
// ensure.
|
||||
auto const_id = TryEvalInst(*this, inst_id, inst);
|
||||
if (const_id.is_constant()) {
|
||||
CARBON_VLOG() << "Constant: " << inst << " -> " << const_id.inst_id()
|
||||
<< "\n";
|
||||
CARBON_VLOG() << "Constant: " << inst << " -> "
|
||||
<< constant_values().GetInstId(const_id) << "\n";
|
||||
}
|
||||
constant_values().Set(inst_id, const_id);
|
||||
}
|
||||
@@ -470,7 +470,7 @@ auto Context::LookupNameInCore(SemIRLoc loc, llvm::StringRef name)
|
||||
}
|
||||
|
||||
// Look through import_refs and aliases.
|
||||
return constant_values().Get(inst_id).inst_id();
|
||||
return constant_values().GetConstantInstId(inst_id);
|
||||
}
|
||||
|
||||
template <typename BranchNode, typename... Args>
|
||||
@@ -558,7 +558,7 @@ auto Context::SetBlockArgResultBeforeConstantUse(SemIR::InstId select_id,
|
||||
if (!cond_const_id.is_template()) {
|
||||
// Symbolic or non-constant condition means a non-constant result.
|
||||
} else if (auto literal = insts().TryGetAs<SemIR::BoolLiteral>(
|
||||
cond_const_id.inst_id())) {
|
||||
constant_values().GetInstId(cond_const_id))) {
|
||||
const_id = constant_values().Get(literal.value().value.ToBool() ? if_true
|
||||
: if_false);
|
||||
} else {
|
||||
@@ -569,7 +569,7 @@ auto Context::SetBlockArgResultBeforeConstantUse(SemIR::InstId select_id,
|
||||
|
||||
if (const_id.is_constant()) {
|
||||
CARBON_VLOG() << "Constant: " << insts().Get(select_id) << " -> "
|
||||
<< const_id.inst_id() << "\n";
|
||||
<< constant_values().GetInstId(const_id) << "\n";
|
||||
constant_values().Set(select_id, const_id);
|
||||
}
|
||||
}
|
||||
@@ -892,13 +892,8 @@ class TypeCompleter {
|
||||
if (field_value_rep.type_id != field.field_type_id) {
|
||||
same_as_object_rep = false;
|
||||
field.field_type_id = field_value_rep.type_id;
|
||||
// TODO: Use `TryEvalInst` to form this value.
|
||||
field_id = context_
|
||||
.AddConstant(field, context_.constant_values()
|
||||
.Get(context_.types().GetInstId(
|
||||
field.field_type_id))
|
||||
.is_symbolic())
|
||||
.inst_id();
|
||||
field_id = context_.constant_values().GetInstId(
|
||||
TryEvalInst(context_, SemIR::InstId::Invalid, field));
|
||||
}
|
||||
value_rep_fields.push_back(field_id);
|
||||
}
|
||||
|
||||
@@ -302,7 +302,8 @@ static auto DiagnoseQualifiedDeclInUndefinedInterfaceScope(
|
||||
auto builder = context.emitter().Build(
|
||||
loc, QualifiedDeclInUndefinedInterfaceScope,
|
||||
context.sem_ir().StringifyTypeExpr(
|
||||
context.sem_ir().constant_values().Get(interface_inst_id).inst_id()));
|
||||
context.sem_ir().constant_values().GetConstantInstId(
|
||||
interface_inst_id)));
|
||||
context.NoteUndefinedInterface(interface_id, builder);
|
||||
builder.Emit();
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ static auto GetConstantValue(Context& context, SemIR::InstId inst_id,
|
||||
Phase* phase) -> SemIR::InstId {
|
||||
auto const_id = context.constant_values().Get(inst_id);
|
||||
*phase = LatestPhase(*phase, GetPhase(const_id));
|
||||
return const_id.inst_id();
|
||||
return context.constant_values().GetInstId(const_id);
|
||||
}
|
||||
|
||||
// A type is always constant, but we still need to extract its phase.
|
||||
@@ -1156,8 +1156,8 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
auto const_id = context.constant_values().Get(typed_inst.operand_id);
|
||||
auto phase = GetPhase(const_id);
|
||||
if (phase == Phase::Template) {
|
||||
auto value =
|
||||
context.insts().GetAs<SemIR::BoolLiteral>(const_id.inst_id());
|
||||
auto value = context.insts().GetAs<SemIR::BoolLiteral>(
|
||||
context.constant_values().GetInstId(const_id));
|
||||
return MakeBoolResult(context, value.type_id, !value.value.ToBool());
|
||||
}
|
||||
if (phase == Phase::UnknownDueToError) {
|
||||
@@ -1172,7 +1172,9 @@ auto TryEvalInst(Context& context, SemIR::InstId inst_id, SemIR::Inst inst)
|
||||
auto inner_id = context.constant_values().Get(
|
||||
context.types().GetInstId(typed_inst.inner_id));
|
||||
if (inner_id.is_constant() &&
|
||||
context.insts().Get(inner_id.inst_id()).Is<SemIR::ConstType>()) {
|
||||
context.insts()
|
||||
.Get(context.constant_values().GetInstId(inner_id))
|
||||
.Is<SemIR::ConstType>()) {
|
||||
return inner_id;
|
||||
}
|
||||
return MakeConstantResult(context, inst, GetPhase(inner_id));
|
||||
|
||||
@@ -145,8 +145,8 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,
|
||||
}
|
||||
|
||||
// Use the constant value to get the ID.
|
||||
auto decl_value =
|
||||
context.insts().Get(context.constant_values().Get(prev_id).inst_id());
|
||||
auto decl_value = context.insts().Get(
|
||||
context.constant_values().GetConstantInstId(prev_id));
|
||||
if (auto class_type = decl_value.TryAs<SemIR::ClassType>()) {
|
||||
prev_class_id = class_type->class_id;
|
||||
prev_import_ir_id = import_ir_inst.ir_id;
|
||||
|
||||
@@ -163,7 +163,7 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,
|
||||
|
||||
// Use the type to get the ID.
|
||||
if (auto struct_value = context.insts().TryGetAs<SemIR::StructValue>(
|
||||
context.constant_values().Get(prev_id).inst_id())) {
|
||||
context.constant_values().GetConstantInstId(prev_id))) {
|
||||
if (auto function_type = context.types().TryGetAs<SemIR::FunctionType>(
|
||||
struct_value->type_id)) {
|
||||
prev_function_id = function_type->function_id;
|
||||
|
||||
@@ -88,8 +88,8 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
|
||||
context.emitter().Emit(node_id, TupleIndexNotConstant);
|
||||
index_inst_id = SemIR::InstId::BuiltinError;
|
||||
} else {
|
||||
auto index_literal =
|
||||
context.insts().GetAs<SemIR::IntLiteral>(index_const_id.inst_id());
|
||||
auto index_literal = context.insts().GetAs<SemIR::IntLiteral>(
|
||||
context.constant_values().GetInstId(index_const_id));
|
||||
auto type_block = context.type_blocks().Get(tuple_type.elements_id);
|
||||
if (const auto* index_val =
|
||||
ValidateTupleIndex(context, node_id, operand_inst,
|
||||
|
||||
@@ -92,9 +92,9 @@ static auto BuildInterfaceWitness(
|
||||
|
||||
for (auto decl_id : assoc_entities) {
|
||||
LoadImportRef(context, decl_id);
|
||||
auto const_id = context.constant_values().Get(decl_id);
|
||||
CARBON_CHECK(const_id.is_constant()) << "Non-constant associated entity";
|
||||
auto decl = context.insts().Get(const_id.inst_id());
|
||||
decl_id = context.constant_values().GetConstantInstId(decl_id);
|
||||
CARBON_CHECK(decl_id.is_valid()) << "Non-constant associated entity";
|
||||
auto decl = context.insts().Get(decl_id);
|
||||
CARBON_KIND_SWITCH(decl) {
|
||||
case CARBON_KIND(SemIR::StructValue struct_value): {
|
||||
if (struct_value.type_id == SemIR::TypeId::Error) {
|
||||
|
||||
@@ -365,6 +365,16 @@ class ImportRefResolver {
|
||||
return const_id;
|
||||
}
|
||||
|
||||
// Returns the local constant InstId for an imported InstId.
|
||||
auto GetLocalConstantInstId(SemIR::InstId inst_id) -> SemIR::InstId {
|
||||
auto const_id = import_ir_constant_values().Get(inst_id);
|
||||
if (!const_id.is_valid()) {
|
||||
work_stack_.push_back({.inst_id = inst_id});
|
||||
return SemIR::InstId::Invalid;
|
||||
}
|
||||
return context_.constant_values().GetInstId(const_id);
|
||||
}
|
||||
|
||||
// Returns the ConstantId for a TypeId. Adds unresolved constants to
|
||||
// work_stack_.
|
||||
auto GetLocalConstantId(SemIR::TypeId type_id) -> SemIR::ConstantId {
|
||||
@@ -385,7 +395,7 @@ class ImportRefResolver {
|
||||
inst_ids.reserve(import_block.size());
|
||||
for (auto import_inst_id : import_block) {
|
||||
auto const_id = GetLocalConstantId(import_inst_id);
|
||||
inst_ids.push_back(const_id.inst_id_if_valid());
|
||||
inst_ids.push_back(context_.constant_values().GetInstIdIfValid(const_id));
|
||||
}
|
||||
|
||||
return inst_ids;
|
||||
@@ -488,7 +498,7 @@ class ImportRefResolver {
|
||||
case SemIR::BindSymbolicName::Kind: {
|
||||
// The symbolic name will be created on first reference, so might
|
||||
// already exist. Update the value in it to refer to the parameter.
|
||||
auto new_bind_inst_id = GetLocalConstantId(bind_id).inst_id();
|
||||
auto new_bind_inst_id = GetLocalConstantInstId(bind_id);
|
||||
auto new_bind_inst =
|
||||
context_.insts().GetAs<SemIR::BindSymbolicName>(
|
||||
new_bind_inst_id);
|
||||
@@ -540,11 +550,11 @@ class ImportRefResolver {
|
||||
// TODO: Import the scope for an `impl` definition.
|
||||
return SemIR::NameScopeId::Invalid;
|
||||
}
|
||||
auto const_id = GetLocalConstantId(inst_id);
|
||||
if (!const_id.is_valid()) {
|
||||
auto const_inst_id = GetLocalConstantInstId(inst_id);
|
||||
if (!const_inst_id.is_valid()) {
|
||||
return SemIR::NameScopeId::Invalid;
|
||||
}
|
||||
auto name_scope_inst = context_.insts().Get(const_id.inst_id());
|
||||
auto name_scope_inst = context_.insts().Get(const_inst_id);
|
||||
CARBON_KIND_SWITCH(name_scope_inst) {
|
||||
case CARBON_KIND(SemIR::Namespace inst): {
|
||||
return inst.name_scope_id;
|
||||
@@ -571,7 +581,7 @@ class ImportRefResolver {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (const_id == SemIR::ConstantId::Error) {
|
||||
if (const_inst_id == SemIR::InstId::BuiltinError) {
|
||||
return SemIR::NameScopeId::Invalid;
|
||||
}
|
||||
break;
|
||||
@@ -761,7 +771,7 @@ class ImportRefResolver {
|
||||
|
||||
auto initial_work = work_stack_.size();
|
||||
auto entity_type_const_id = GetLocalConstantId(inst.entity_type_id);
|
||||
auto interface_const_id = GetLocalConstantId(
|
||||
auto interface_inst_id = GetLocalConstantInstId(
|
||||
import_ir_.interfaces().Get(inst.interface_id).decl_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
@@ -769,10 +779,9 @@ class ImportRefResolver {
|
||||
|
||||
return ResolveAs<SemIR::AssociatedEntityType>(
|
||||
{.type_id = SemIR::TypeId::TypeType,
|
||||
.interface_id =
|
||||
context_.insts()
|
||||
.GetAs<SemIR::InterfaceType>(interface_const_id.inst_id())
|
||||
.interface_id,
|
||||
.interface_id = context_.insts()
|
||||
.GetAs<SemIR::InterfaceType>(interface_inst_id)
|
||||
.interface_id,
|
||||
.entity_type_id =
|
||||
context_.GetTypeIdForTypeConstant(entity_type_const_id)});
|
||||
}
|
||||
@@ -871,7 +880,7 @@ class ImportRefResolver {
|
||||
auto AddClassDefinition(const SemIR::Class& import_class,
|
||||
SemIR::Class& new_class,
|
||||
SemIR::ConstantId object_repr_const_id,
|
||||
SemIR::ConstantId base_const_id) -> void {
|
||||
SemIR::InstId base_id) -> void {
|
||||
new_class.definition_id = new_class.decl_id;
|
||||
|
||||
new_class.object_repr_id =
|
||||
@@ -889,7 +898,7 @@ class ImportRefResolver {
|
||||
new_class.body_block_id = context_.inst_block_stack().Pop();
|
||||
|
||||
if (import_class.base_id.is_valid()) {
|
||||
new_class.base_id = base_const_id.inst_id();
|
||||
new_class.base_id = base_id;
|
||||
// Add the base scope to extended scopes.
|
||||
auto base_inst_id = context_.types().GetInstId(
|
||||
context_.insts()
|
||||
@@ -918,7 +927,8 @@ class ImportRefResolver {
|
||||
} else {
|
||||
// On the second pass, compute the class ID from the constant value of the
|
||||
// declaration.
|
||||
auto class_const_inst = context_.insts().Get(class_const_id.inst_id());
|
||||
auto class_const_inst = context_.insts().Get(
|
||||
context_.constant_values().GetInstId(class_const_id));
|
||||
if (auto class_type = class_const_inst.TryAs<SemIR::ClassType>()) {
|
||||
class_id = class_type->class_id;
|
||||
} else {
|
||||
@@ -942,9 +952,9 @@ class ImportRefResolver {
|
||||
import_class.object_repr_id.is_valid()
|
||||
? GetLocalConstantId(import_class.object_repr_id)
|
||||
: SemIR::ConstantId::Invalid;
|
||||
auto base_const_id = import_class.base_id.is_valid()
|
||||
? GetLocalConstantId(import_class.base_id)
|
||||
: SemIR::ConstantId::Invalid;
|
||||
auto base_id = import_class.base_id.is_valid()
|
||||
? GetLocalConstantInstId(import_class.base_id)
|
||||
: SemIR::InstId::Invalid;
|
||||
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry(class_const_id);
|
||||
@@ -960,7 +970,7 @@ class ImportRefResolver {
|
||||
|
||||
if (import_class.is_defined()) {
|
||||
AddClassDefinition(import_class, new_class, object_repr_const_id,
|
||||
base_const_id);
|
||||
base_id);
|
||||
}
|
||||
|
||||
return {.const_id = class_const_id};
|
||||
@@ -979,7 +989,8 @@ class ImportRefResolver {
|
||||
// Find the corresponding class type. For a non-generic class, this is the
|
||||
// type of the class declaration. For a generic class, build a class type
|
||||
// referencing this specialization of the generic class.
|
||||
auto class_const_inst = context_.insts().Get(class_const_id.inst_id());
|
||||
auto class_const_inst = context_.insts().Get(
|
||||
context_.constant_values().GetInstId(class_const_id));
|
||||
if (class_const_inst.Is<SemIR::ClassType>()) {
|
||||
return {.const_id = class_const_id};
|
||||
} else {
|
||||
@@ -1094,12 +1105,12 @@ class ImportRefResolver {
|
||||
auto TryResolveTypedInst(SemIR::FunctionType inst) -> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
|
||||
auto fn_const_id = GetLocalConstantId(
|
||||
auto fn_val_id = GetLocalConstantInstId(
|
||||
import_ir_.functions().Get(inst.function_id).decl_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto fn_val = context_.insts().Get(fn_const_id.inst_id());
|
||||
auto fn_val = context_.insts().Get(fn_val_id);
|
||||
CARBON_CHECK(context_.types().Is<SemIR::FunctionType>(fn_val.type_id()));
|
||||
return {.const_id = context_.types().GetConstantId(fn_val.type_id())};
|
||||
}
|
||||
@@ -1107,12 +1118,12 @@ class ImportRefResolver {
|
||||
auto TryResolveTypedInst(SemIR::GenericClassType inst) -> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
|
||||
auto class_const_id =
|
||||
GetLocalConstantId(import_ir_.classes().Get(inst.class_id).decl_id);
|
||||
auto class_val_id =
|
||||
GetLocalConstantInstId(import_ir_.classes().Get(inst.class_id).decl_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto class_val = context_.insts().Get(class_const_id.inst_id());
|
||||
auto class_val = context_.insts().Get(class_val_id);
|
||||
CARBON_CHECK(
|
||||
context_.types().Is<SemIR::GenericClassType>(class_val.type_id()));
|
||||
return {.const_id = context_.types().GetConstantId(class_val.type_id())};
|
||||
@@ -1121,12 +1132,12 @@ class ImportRefResolver {
|
||||
auto TryResolveTypedInst(SemIR::GenericInterfaceType inst) -> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
|
||||
auto interface_const_id = GetLocalConstantId(
|
||||
auto interface_val_id = GetLocalConstantInstId(
|
||||
import_ir_.interfaces().Get(inst.interface_id).decl_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto interface_val = context_.insts().Get(interface_const_id.inst_id());
|
||||
auto interface_val = context_.insts().Get(interface_val_id);
|
||||
CARBON_CHECK(context_.types().Is<SemIR::GenericInterfaceType>(
|
||||
interface_val.type_id()));
|
||||
return {.const_id =
|
||||
@@ -1147,7 +1158,8 @@ class ImportRefResolver {
|
||||
return {.const_id = SemIR::ConstantId::Error};
|
||||
}
|
||||
|
||||
auto new_constant_id = GetLocalConstantId(constant_id.inst_id());
|
||||
auto new_constant_id =
|
||||
GetLocalConstantId(import_ir_.constant_values().GetInstId(constant_id));
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
@@ -1201,7 +1213,7 @@ class ImportRefResolver {
|
||||
// declaration.
|
||||
auto AddInterfaceDefinition(const SemIR::Interface& import_interface,
|
||||
SemIR::Interface& new_interface,
|
||||
SemIR::ConstantId self_param_id) -> void {
|
||||
SemIR::InstId self_param_id) -> void {
|
||||
new_interface.scope_id = context_.name_scopes().Add(
|
||||
new_interface.decl_id, SemIR::NameId::Invalid,
|
||||
new_interface.parent_scope_id);
|
||||
@@ -1215,7 +1227,7 @@ class ImportRefResolver {
|
||||
new_interface.associated_entities_id =
|
||||
AddAssociatedEntities(import_interface.associated_entities_id);
|
||||
new_interface.body_block_id = context_.inst_block_stack().Pop();
|
||||
new_interface.self_param_id = self_param_id.inst_id();
|
||||
new_interface.self_param_id = self_param_id;
|
||||
|
||||
CARBON_CHECK(import_scope.extended_scopes.empty())
|
||||
<< "Interfaces don't currently have extended scopes to support.";
|
||||
@@ -1235,8 +1247,8 @@ class ImportRefResolver {
|
||||
} else {
|
||||
// On the second pass, compute the interface ID from the constant value of
|
||||
// the declaration.
|
||||
auto interface_const_inst =
|
||||
context_.insts().Get(interface_const_id.inst_id());
|
||||
auto interface_const_inst = context_.insts().Get(
|
||||
context_.constant_values().GetInstId(interface_const_id));
|
||||
if (auto interface_type =
|
||||
interface_const_inst.TryAs<SemIR::InterfaceType>()) {
|
||||
interface_id = interface_type->interface_id;
|
||||
@@ -1256,7 +1268,7 @@ class ImportRefResolver {
|
||||
GetLocalParamConstantIds(import_interface.implicit_param_refs_id);
|
||||
llvm::SmallVector<SemIR::ConstantId> param_const_ids =
|
||||
GetLocalParamConstantIds(import_interface.param_refs_id);
|
||||
auto self_param_id = GetLocalConstantId(import_interface.self_param_id);
|
||||
auto self_param_id = GetLocalConstantInstId(import_interface.self_param_id);
|
||||
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry(interface_const_id);
|
||||
@@ -1289,8 +1301,8 @@ class ImportRefResolver {
|
||||
// is the type of the interface declaration. For a generic interface, build
|
||||
// a interface type referencing this specialization of the generic
|
||||
// interface.
|
||||
auto interface_const_inst =
|
||||
context_.insts().Get(interface_const_id.inst_id());
|
||||
auto interface_const_inst = context_.insts().Get(
|
||||
context_.constant_values().GetInstId(interface_const_id));
|
||||
if (interface_const_inst.Is<SemIR::InterfaceType>()) {
|
||||
return {.const_id = interface_const_id};
|
||||
} else {
|
||||
@@ -1307,22 +1319,12 @@ class ImportRefResolver {
|
||||
|
||||
auto TryResolveTypedInst(SemIR::InterfaceWitness inst) -> ResolveResult {
|
||||
auto initial_work = work_stack_.size();
|
||||
llvm::SmallVector<SemIR::InstId> elements;
|
||||
auto import_elements = import_ir_.inst_blocks().Get(inst.elements_id);
|
||||
elements.reserve(import_elements.size());
|
||||
for (auto import_elem_id : import_elements) {
|
||||
if (auto const_id = GetLocalConstantId(import_elem_id);
|
||||
const_id.is_valid()) {
|
||||
elements.push_back(const_id.inst_id());
|
||||
}
|
||||
}
|
||||
auto elements = GetLocalInstBlockContents(inst.elements_id);
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
CARBON_CHECK(elements.size() == import_elements.size())
|
||||
<< "Failed to import an element without adding new work.";
|
||||
|
||||
auto elements_id = context_.inst_blocks().Add(elements);
|
||||
auto elements_id = GetLocalCanonicalInstBlockId(inst.elements_id, elements);
|
||||
return ResolveAs<SemIR::InterfaceWitness>(
|
||||
{.type_id = context_.GetBuiltinType(SemIR::BuiltinKind::WitnessType),
|
||||
.elements_id = elements_id});
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace Carbon::Check {
|
||||
static auto GetAsNameScope(Context& context, Parse::NodeId node_id,
|
||||
SemIR::ConstantId base_const_id)
|
||||
-> std::optional<SemIR::NameScopeId> {
|
||||
auto base = context.insts().Get(base_const_id.inst_id());
|
||||
auto base_id = context.constant_values().GetInstId(base_const_id);
|
||||
auto base = context.insts().Get(base_id);
|
||||
if (auto base_as_namespace = base.TryAs<SemIR::Namespace>()) {
|
||||
return base_as_namespace->name_scope_id;
|
||||
}
|
||||
@@ -35,7 +36,7 @@ static auto GetAsNameScope(Context& context, Parse::NodeId node_id,
|
||||
std::string);
|
||||
auto builder = context.emitter().Build(
|
||||
node_id, QualifiedExprInIncompleteClassScope,
|
||||
context.sem_ir().StringifyTypeExpr(base_const_id.inst_id()));
|
||||
context.sem_ir().StringifyType(base_const_id));
|
||||
context.NoteIncompleteClass(base_as_class->class_id, builder);
|
||||
builder.Emit();
|
||||
}
|
||||
@@ -50,7 +51,7 @@ static auto GetAsNameScope(Context& context, Parse::NodeId node_id,
|
||||
std::string);
|
||||
auto builder = context.emitter().Build(
|
||||
node_id, QualifiedExprInUndefinedInterfaceScope,
|
||||
context.sem_ir().StringifyTypeExpr(base_const_id.inst_id()));
|
||||
context.sem_ir().StringifyType(base_const_id));
|
||||
context.NoteUndefinedInterface(base_as_interface->interface_id, builder);
|
||||
builder.Emit();
|
||||
}
|
||||
@@ -131,7 +132,8 @@ static auto LookupInterfaceWitness(Context& context,
|
||||
// considering impls that are for the same interface we're querying. We can
|
||||
// also skip impls that mention any types that aren't part of our impl query.
|
||||
for (const auto& impl : context.impls().array_ref()) {
|
||||
if (context.types().GetInstId(impl.self_id) != type_const_id.inst_id()) {
|
||||
if (context.types().GetInstId(impl.self_id) !=
|
||||
context.constant_values().GetInstId(type_const_id)) {
|
||||
continue;
|
||||
}
|
||||
auto interface_type =
|
||||
@@ -168,22 +170,22 @@ static auto PerformImplLookup(Context& context, Parse::NodeId node_id,
|
||||
"Cannot access member of interface {0} in type {1} "
|
||||
"that does not implement that interface.",
|
||||
SemIR::NameId, std::string);
|
||||
context.emitter().Emit(
|
||||
node_id, MissingImplInMemberAccess, interface.name_id,
|
||||
context.sem_ir().StringifyTypeExpr(type_const_id.inst_id()));
|
||||
context.emitter().Emit(node_id, MissingImplInMemberAccess,
|
||||
interface.name_id,
|
||||
context.sem_ir().StringifyType(type_const_id));
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
|
||||
auto const_id = context.constant_values().Get(member_id);
|
||||
if (!const_id.is_constant()) {
|
||||
if (const_id != SemIR::ConstantId::Error) {
|
||||
auto member_value_id = context.constant_values().GetConstantInstId(member_id);
|
||||
if (!member_value_id.is_valid()) {
|
||||
if (member_value_id != SemIR::InstId::BuiltinError) {
|
||||
context.TODO(member_id, "non-constant associated entity");
|
||||
}
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
|
||||
auto assoc_entity =
|
||||
context.insts().TryGetAs<SemIR::AssociatedEntity>(const_id.inst_id());
|
||||
context.insts().TryGetAs<SemIR::AssociatedEntity>(member_value_id);
|
||||
if (!assoc_entity) {
|
||||
context.TODO(member_id, "unexpected value for associated entity");
|
||||
return SemIR::InstId::BuiltinError;
|
||||
@@ -256,11 +258,11 @@ static auto PerformInstanceBinding(Context& context, Parse::NodeId node_id,
|
||||
|
||||
// Find the specified element, which could be either a field or a base
|
||||
// class, and build an element access expression.
|
||||
auto element_id = context.constant_values().Get(member_id);
|
||||
CARBON_CHECK(element_id.is_constant())
|
||||
auto element_id = context.constant_values().GetConstantInstId(member_id);
|
||||
CARBON_CHECK(element_id.is_valid())
|
||||
<< "Non-constant value " << context.insts().Get(member_id)
|
||||
<< " of unbound element type";
|
||||
auto index = GetClassElementIndex(context, element_id.inst_id());
|
||||
auto index = GetClassElementIndex(context, element_id);
|
||||
auto access_id = context.AddInst<SemIR::ClassElementAccess>(
|
||||
node_id, {.type_id = unbound_element_type.element_type_id,
|
||||
.base_id = base_id,
|
||||
@@ -329,7 +331,7 @@ auto PerformMemberAccess(Context& context, Parse::NodeId node_id,
|
||||
if (!name_scope_id) {
|
||||
// The base type is not a name scope. Try some fallback options.
|
||||
if (auto struct_type = context.insts().TryGetAs<SemIR::StructType>(
|
||||
base_type_const_id.inst_id())) {
|
||||
context.constant_values().GetInstId(base_type_const_id))) {
|
||||
// TODO: Do we need to optimize this with a lookup table for O(1)?
|
||||
for (auto [i, ref_id] :
|
||||
llvm::enumerate(context.inst_blocks().Get(struct_type->fields_id))) {
|
||||
|
||||
@@ -47,7 +47,7 @@ static auto GetOperatorOpFunction(Context& context, Parse::AnyExprId node_id,
|
||||
}
|
||||
|
||||
// Look through import_refs and aliases.
|
||||
op_id = context.constant_values().Get(op_id).inst_id();
|
||||
op_id = context.constant_values().GetConstantInstId(op_id);
|
||||
|
||||
// We expect it to be an associated function.
|
||||
if (context.insts().Is<SemIR::AssociatedEntity>(op_id)) {
|
||||
|
||||
@@ -148,7 +148,7 @@ static auto Rebuild(Context& context, Worklist& worklist, SemIR::InstId inst_id)
|
||||
auto result_id = TryEvalInst(context, SemIR::InstId::Invalid, inst);
|
||||
CARBON_CHECK(result_id.is_constant())
|
||||
<< "Substitution into constant produced non-constant";
|
||||
return result_id.inst_id();
|
||||
return context.constant_values().GetInstId(result_id);
|
||||
}
|
||||
|
||||
auto SubstConstant(Context& context, SemIR::ConstantId const_id,
|
||||
@@ -165,7 +165,7 @@ auto SubstConstant(Context& context, SemIR::ConstantId const_id,
|
||||
return const_id;
|
||||
}
|
||||
|
||||
Worklist worklist(const_id.inst_id());
|
||||
Worklist worklist(context.constant_values().GetInstId(const_id));
|
||||
|
||||
// For each instruction that forms part of the constant, we will visit it
|
||||
// twice:
|
||||
@@ -208,7 +208,7 @@ auto SubstConstant(Context& context, SemIR::ConstantId const_id,
|
||||
if (context.bind_names().Get(bind->bind_name_id).bind_index ==
|
||||
bind_index) {
|
||||
// This is the binding we're replacing. Perform substitution.
|
||||
item.inst_id = replacement_id.inst_id();
|
||||
item.inst_id = context.constant_values().GetInstId(replacement_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,15 @@ class ConstantContext {
|
||||
// Gets the lowered constant value for a constant that has already been
|
||||
// lowered.
|
||||
auto GetConstant(SemIR::ConstantId const_id) const -> llvm::Constant* {
|
||||
CARBON_CHECK(const_id.is_template() && const_id.inst_id().index >= 0)
|
||||
CARBON_CHECK(const_id.is_template())
|
||||
<< "Unexpected constant ID " << const_id;
|
||||
CARBON_CHECK(const_id.inst_id().index <= last_lowered_constant_index_)
|
||||
<< "Queried constant " << const_id << " that has not been lowered yet";
|
||||
return constants_[const_id.inst_id().index];
|
||||
auto inst_id =
|
||||
file_context_->sem_ir().constant_values().GetInstId(const_id);
|
||||
CARBON_CHECK(inst_id.index >= 0 &&
|
||||
inst_id.index <= last_lowered_constant_index_)
|
||||
<< "Queried constant " << const_id << " with instruction " << inst_id
|
||||
<< " that has not been lowered yet";
|
||||
return constants_[inst_id.index];
|
||||
}
|
||||
|
||||
// Returns a constant for the case of a value that should never be used.
|
||||
@@ -238,13 +242,14 @@ auto LowerConstants(FileContext& file_context,
|
||||
// We are only interested in lowering template constants.
|
||||
continue;
|
||||
}
|
||||
auto inst_id = file_context.sem_ir().constant_values().GetInstId(const_id);
|
||||
|
||||
if (const_id.inst_id().index != static_cast<int32_t>(inst_id_val)) {
|
||||
if (inst_id.index != static_cast<int32_t>(inst_id_val)) {
|
||||
// This isn't the instruction that defines the constant.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto inst = file_context.sem_ir().insts().Get(const_id.inst_id());
|
||||
auto inst = file_context.sem_ir().insts().Get(inst_id);
|
||||
llvm::Constant* value = nullptr;
|
||||
CARBON_KIND_SWITCH(inst) {
|
||||
#define CARBON_SEM_IR_INST_KIND_CONSTANT_NEVER(...)
|
||||
@@ -259,8 +264,8 @@ auto LowerConstants(FileContext& file_context,
|
||||
CARBON_FATAL() << "Unexpected constant instruction kind " << inst;
|
||||
}
|
||||
|
||||
constants[const_id.inst_id().index] = value;
|
||||
context.SetLastLoweredConstantIndex(const_id.inst_id().index);
|
||||
constants[inst_id.index] = value;
|
||||
context.SetLastLoweredConstantIndex(inst_id.index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,11 +70,13 @@ auto FileContext::GetGlobal(SemIR::InstId inst_id) -> llvm::Value* {
|
||||
|
||||
auto const_id = sem_ir().constant_values().Get(inst_id);
|
||||
if (const_id.is_template()) {
|
||||
auto const_inst_id = sem_ir().constant_values().GetInstId(const_id);
|
||||
|
||||
// For value expressions and initializing expressions, the value produced by
|
||||
// a constant instruction is a value representation of the constant. For
|
||||
// initializing expressions, `FinishInit` will perform a copy if needed.
|
||||
// TODO: Handle reference expression constants.
|
||||
auto* const_value = constants_[const_id.inst_id().index];
|
||||
auto* const_value = constants_[const_inst_id.index];
|
||||
|
||||
// If we want a pointer to the constant, materialize a global to hold it.
|
||||
// TODO: We could reuse the same global if the constant is used more than
|
||||
@@ -86,7 +88,7 @@ auto FileContext::GetGlobal(SemIR::InstId inst_id) -> llvm::Value* {
|
||||
llvm::StringRef const_name;
|
||||
llvm::StringRef use_name;
|
||||
if (inst_namer_) {
|
||||
const_name = inst_namer_->GetUnscopedNameFor(const_id.inst_id());
|
||||
const_name = inst_namer_->GetUnscopedNameFor(const_inst_id);
|
||||
use_name = inst_namer_->GetUnscopedNameFor(inst_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,24 @@ class ConstantValueStore {
|
||||
values_[inst_id.index] = const_id;
|
||||
}
|
||||
|
||||
// Gets the instruction ID that defines the value of the given constant.
|
||||
// Returns Invalid if the constant ID is non-constant. Requires is_valid.
|
||||
auto GetInstId(ConstantId const_id) const -> InstId {
|
||||
return const_id.inst_id();
|
||||
}
|
||||
|
||||
// Gets the instruction ID that defines the value of the given constant.
|
||||
// Returns Invalid if the constant ID is non-constant or invalid.
|
||||
auto GetInstIdIfValid(ConstantId const_id) const -> InstId {
|
||||
return const_id.is_valid() ? GetInstId(const_id) : InstId::Invalid;
|
||||
}
|
||||
|
||||
// Given an instruction, returns the unique constant instruction that is
|
||||
// equivalent to it. Returns Invalid for a non-constant instruction.
|
||||
auto GetConstantInstId(InstId inst_id) const -> InstId {
|
||||
return GetInstId(Get(inst_id));
|
||||
}
|
||||
|
||||
// Returns the constant values mapping as an ArrayRef whose keys are
|
||||
// instruction indexes. Some of the elements in this mapping may be Invalid or
|
||||
// NotConstant.
|
||||
|
||||
@@ -496,6 +496,11 @@ auto File::StringifyType(TypeId type_id) const -> std::string {
|
||||
return StringifyTypeExprImpl(*this, types().GetInstId(type_id));
|
||||
}
|
||||
|
||||
auto File::StringifyType(ConstantId type_const_id) const -> std::string {
|
||||
return StringifyTypeExprImpl(*this,
|
||||
constant_values().GetInstId(type_const_id));
|
||||
}
|
||||
|
||||
auto File::StringifyTypeExpr(InstId outer_inst_id) const -> std::string {
|
||||
return StringifyTypeExprImpl(*this, outer_inst_id);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ class File : public Printable<File> {
|
||||
// Produces a string version of a type.
|
||||
auto StringifyType(TypeId type_id) const -> std::string;
|
||||
|
||||
// Same, but with a constant ID rather than a type ID.
|
||||
auto StringifyType(ConstantId type_const_id) const -> std::string;
|
||||
|
||||
// Same as `StringifyType`, but starting with an instruction representing a
|
||||
// type expression rather than a canonical type.
|
||||
auto StringifyTypeExpr(InstId outer_inst_id) const -> std::string;
|
||||
@@ -238,7 +241,7 @@ class File : public Printable<File> {
|
||||
ConstantStore constants_;
|
||||
|
||||
// Descriptions of types used in this file.
|
||||
TypeStore types_ = TypeStore(&insts_);
|
||||
TypeStore types_ = TypeStore(&insts_, &constant_values_);
|
||||
|
||||
// Types that were completed in this file.
|
||||
llvm::SmallVector<TypeId> complete_types_;
|
||||
|
||||
@@ -401,7 +401,7 @@ class Formatter {
|
||||
out_ << InstT::Kind.ir_name();
|
||||
pending_constant_value_ = sem_ir_.constant_values().Get(inst_id);
|
||||
pending_constant_value_is_self_ =
|
||||
pending_constant_value_.inst_id() == inst_id;
|
||||
sem_ir_.constant_values().GetInstId(pending_constant_value_) == inst_id;
|
||||
FormatInstructionRHS(inst);
|
||||
FormatPendingConstantValue(AddSpace::Before);
|
||||
out_ << "\n";
|
||||
@@ -433,7 +433,8 @@ class Formatter {
|
||||
out_ << (pending_constant_value_.is_symbolic() ? "symbolic" : "template");
|
||||
if (!pending_constant_value_is_self_) {
|
||||
out_ << " = ";
|
||||
FormatInstName(pending_constant_value_.inst_id());
|
||||
FormatInstName(
|
||||
sem_ir_.constant_values().GetInstId(pending_constant_value_));
|
||||
}
|
||||
} else {
|
||||
out_ << pending_constant_value_;
|
||||
|
||||
@@ -19,11 +19,11 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id) -> CalleeFunction {
|
||||
}
|
||||
|
||||
// Identify the function we're calling.
|
||||
auto val_id = sem_ir.constant_values().Get(callee_id);
|
||||
if (!val_id.is_constant()) {
|
||||
auto val_id = sem_ir.constant_values().GetConstantInstId(callee_id);
|
||||
if (!val_id.is_valid()) {
|
||||
return result;
|
||||
}
|
||||
auto val_inst = sem_ir.insts().Get(val_id.inst_id());
|
||||
auto val_inst = sem_ir.insts().Get(val_id);
|
||||
auto struct_val = val_inst.TryAs<StructValue>();
|
||||
if (!struct_val) {
|
||||
result.is_error = val_inst.type_id() == SemIR::TypeId::Error;
|
||||
|
||||
+11
-14
@@ -134,19 +134,6 @@ struct ConstantId : public IdBase, public Printable<ConstantId> {
|
||||
return index >= IndexOffset;
|
||||
}
|
||||
|
||||
// Returns the instruction that describes this constant value, or
|
||||
// InstId::Invalid for a runtime value. Requires is_valid.
|
||||
constexpr auto inst_id() const -> InstId {
|
||||
CARBON_CHECK(is_valid());
|
||||
return InstId(Abs(index) - IndexOffset);
|
||||
}
|
||||
|
||||
// Returns the instruction that describes this constant value, or
|
||||
// InstId::Invalid if this is invalid or a runtime value.
|
||||
constexpr auto inst_id_if_valid() const -> InstId {
|
||||
return is_valid() ? inst_id() : InstId::Invalid;
|
||||
}
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
if (!is_valid()) {
|
||||
IdBase::Print(out);
|
||||
@@ -160,17 +147,27 @@ struct ConstantId : public IdBase, public Printable<ConstantId> {
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ConstantValueStore;
|
||||
|
||||
// TODO: C++23 makes std::abs constexpr, but until then we mirror std::abs
|
||||
// logic here. LLVM should still optimize this.
|
||||
static constexpr auto Abs(int32_t i) -> int32_t { return i > 0 ? i : -i; }
|
||||
|
||||
// Returns the instruction that describes this constant value, or
|
||||
// InstId::Invalid for a runtime value. This is not part of the public
|
||||
// interface of `ConstantId`. Use `ConstantValueStore::GetInstId` to get the
|
||||
// instruction ID of a `ConstantId`.
|
||||
constexpr auto inst_id() const -> InstId {
|
||||
CARBON_CHECK(is_valid());
|
||||
return InstId(Abs(index) - IndexOffset);
|
||||
}
|
||||
|
||||
static constexpr int32_t NotConstantIndex = InvalidIndex - 1;
|
||||
// The offset of InstId indices to ConstantId indices.
|
||||
static constexpr int32_t IndexOffset = -NotConstantIndex + 1;
|
||||
};
|
||||
|
||||
constexpr ConstantId ConstantId::NotConstant = ConstantId(NotConstantIndex);
|
||||
static_assert(ConstantId::NotConstant.inst_id() == InstId::Invalid);
|
||||
constexpr ConstantId ConstantId::Error =
|
||||
ConstantId::ForTemplateConstant(InstId::BuiltinError);
|
||||
constexpr ConstantId ConstantId::Invalid = ConstantId(InvalidIndex);
|
||||
|
||||
@@ -457,9 +457,11 @@ auto InstNamer::CollectNamesInBlock(ScopeId scope_id,
|
||||
// a block. Constants that refer to them need to be separately
|
||||
// named.
|
||||
auto const_id = sem_ir_.constant_values().Get(inst_id);
|
||||
if (const_id.is_valid() && const_id.is_template() &&
|
||||
!insts[const_id.inst_id().index].second) {
|
||||
CollectNamesInBlock(ScopeId::ImportRef, const_id.inst_id());
|
||||
if (const_id.is_valid() && const_id.is_template()) {
|
||||
auto const_inst_id = sem_ir_.constant_values().GetInstId(const_id);
|
||||
if (!insts[const_inst_id.index].second) {
|
||||
CollectNamesInBlock(ScopeId::ImportRef, const_inst_id);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define CARBON_TOOLCHAIN_SEM_IR_TYPE_H_
|
||||
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/sem_ir/constant.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
#include "toolchain/sem_ir/type_info.h"
|
||||
@@ -15,7 +16,8 @@ namespace Carbon::SemIR {
|
||||
// Provides a ValueStore wrapper with an API specific to types.
|
||||
class TypeStore : public ValueStore<TypeId> {
|
||||
public:
|
||||
explicit TypeStore(InstStore* insts) : insts_(insts) {}
|
||||
explicit TypeStore(InstStore* insts, ConstantValueStore* constants)
|
||||
: insts_(insts), constants_(constants) {}
|
||||
|
||||
// Returns the ID of the constant used to define the specified type.
|
||||
auto GetConstantId(TypeId type_id) const -> ConstantId {
|
||||
@@ -33,7 +35,7 @@ class TypeStore : public ValueStore<TypeId> {
|
||||
|
||||
// Returns the ID of the instruction used to define the specified type.
|
||||
auto GetInstId(TypeId type_id) const -> InstId {
|
||||
return GetConstantId(type_id).inst_id();
|
||||
return constants_->GetInstId(GetConstantId(type_id));
|
||||
}
|
||||
|
||||
// Returns the instruction used to define the specified type.
|
||||
@@ -56,7 +58,8 @@ class TypeStore : public ValueStore<TypeId> {
|
||||
return GetAsInst(type_id).As<InstT>();
|
||||
} else {
|
||||
// The type is not a builtin, so no need to check for special values.
|
||||
return insts_->Get(Get(type_id).constant_id.inst_id()).As<InstT>();
|
||||
auto inst_id = constants_->GetInstId(Get(type_id).constant_id);
|
||||
return insts_->GetAs<InstT>(inst_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +98,7 @@ class TypeStore : public ValueStore<TypeId> {
|
||||
|
||||
private:
|
||||
InstStore* insts_;
|
||||
ConstantValueStore* constants_;
|
||||
};
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
Reference in New Issue
Block a user