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:
Richard Smith
2024-06-14 00:40:53 +00:00
committed by GitHub
parent e3c15edb92
commit 9029cac727
21 changed files with 167 additions and 128 deletions
+9 -14
View File
@@ -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);
}
+2 -1
View File
@@ -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();
}
+6 -4
View File
@@ -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));
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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,
+3 -3
View File
@@ -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) {
+48 -46
View File
@@ -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});
+17 -15
View File
@@ -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))) {
+1 -1
View File
@@ -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)) {
+3 -3
View File
@@ -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;
}
}
+13 -8
View File
@@ -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);
}
}
+4 -2
View File
@@ -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);
}
+18
View File
@@ -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.
+5
View File
@@ -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);
}
+4 -1
View File
@@ -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_;
+3 -2
View File
@@ -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_;
+3 -3
View File
@@ -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
View File
@@ -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);
+5 -3
View File
@@ -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;
}
+7 -3
View File
@@ -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