From a486c12bd69478bcfedcf73a3bb6b67a9b5f7ca8 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 15 Oct 2025 11:09:29 -0700 Subject: [PATCH] Add unit tagging to SpecificInterfaceId (#6215) --- scripts/lldbinit.py | 2 +- toolchain/base/canonical_value_store.h | 5 ++++ .../basics/raw_sem_ir/one_file.carbon | 24 +++++++++---------- toolchain/sem_ir/file.cpp | 1 + toolchain/sem_ir/ids.cpp | 4 ++++ toolchain/sem_ir/ids.h | 2 ++ toolchain/sem_ir/inst_namer.h | 2 ++ 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/scripts/lldbinit.py b/scripts/lldbinit.py index b12dd974d8f6..a1c66dbc9e20 100644 --- a/scripts/lldbinit.py +++ b/scripts/lldbinit.py @@ -96,7 +96,7 @@ Example usage: "name_scope": ("SemIR::MakeNameScopeId", DECIMAL), "identified_facet_type": ("SemIR::MakeIdentifiedFacetTypeId", DECIMAL), "specific": ("SemIR::MakeSpecificId", DECIMAL), - "specific_interface": ("SemIR::MakeSpecificInterfaceId", DECIMAL), + "specific_interface": ("SemIR::MakeSpecificInterfaceId", HEX), "struct_type_fields": ("SemIR::MakeStructTypeFieldsId", DECIMAL), "type": ("SemIR::MakeTypeId", DECIMAL), } diff --git a/toolchain/base/canonical_value_store.h b/toolchain/base/canonical_value_store.h index 264c4fbe579c..de371e4c7ff3 100644 --- a/toolchain/base/canonical_value_store.h +++ b/toolchain/base/canonical_value_store.h @@ -30,6 +30,9 @@ class CanonicalValueStore { using RefType = ValueStoreTypes::RefType; using ConstRefType = ValueStoreTypes::ConstRefType; + CanonicalValueStore() = default; + explicit CanonicalValueStore(IdTag tag) : values_(tag) {} + // Stores a canonical copy of the value and returns an ID to reference it. If // the value is already in the store, returns the ID of the existing value. auto Add(ValueType value) -> IdT; @@ -63,6 +66,8 @@ class CanonicalValueStore { mem_usage.Add(MemUsage::ConcatLabel(label, "set_"), bytes, bytes); } + auto GetRawIndex(IdT id) const -> int32_t { return values_.GetRawIndex(id); } + private: class KeyContext; diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon index 27f8e5b161ee..2d67179d9e1f 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon @@ -458,7 +458,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: inst60000059: {kind: BindSymbolicName, arg0: entity_name4, arg1: inst, type: type(inst60000047)} // CHECK:STDOUT: inst6000005A: {kind: SymbolicBindingType, arg0: entity_name4, arg1: inst60000059, type: type(TypeType)} // CHECK:STDOUT: inst6000005B: {kind: PatternType, arg0: inst6000005A, type: type(TypeType)} -// CHECK:STDOUT: inst6000005C: {kind: LookupImplWitness, arg0: inst6000001B, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst6000005C: {kind: LookupImplWitness, arg0: inst6000001B, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst6000005D: {kind: ImportRefUnloaded, arg0: import_ir_inst15, arg1: entity_name} // CHECK:STDOUT: inst6000005E: {kind: ImplDecl, arg0: impl60000000, arg1: inst_block_empty} // CHECK:STDOUT: inst6000005F: {kind: BindSymbolicName, arg0: entity_name1, arg1: inst, type: type(inst60000047)} @@ -493,13 +493,13 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: inst6000007C: {kind: PatternType, arg0: inst6000007B, type: type(TypeType)} // CHECK:STDOUT: inst6000007D: {kind: RequireCompleteType, arg0: inst60000061, type: type(inst(WitnessType))} // CHECK:STDOUT: inst6000007E: {kind: RequireCompleteType, arg0: inst60000060, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst6000007F: {kind: LookupImplWitness, arg0: inst6000005F, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst6000007F: {kind: LookupImplWitness, arg0: inst6000005F, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000080: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst6000005F, type: type(TypeType)} // CHECK:STDOUT: inst60000081: {kind: ImplWitnessAccess, arg0: inst6000007F, arg1: element0, type: type(symbolic_constant60)} // CHECK:STDOUT: inst60000082: {kind: SpecificImplFunction, arg0: inst60000081, arg1: specific5, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst60000083: {kind: RequireCompleteType, arg0: inst6000007B, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000084: {kind: RequireCompleteType, arg0: inst6000007A, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst60000085: {kind: LookupImplWitness, arg0: inst60000079, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000085: {kind: LookupImplWitness, arg0: inst60000079, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000086: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst60000079, type: type(TypeType)} // CHECK:STDOUT: inst60000087: {kind: ImplWitnessAccess, arg0: inst60000085, arg1: element0, type: type(symbolic_constant69)} // CHECK:STDOUT: inst60000088: {kind: SpecificImplFunction, arg0: inst60000087, arg1: specific6, type: type(inst(SpecificFunctionType))} @@ -594,18 +594,18 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: inst600000E1: {kind: PatternType, arg0: inst600000E0, type: type(TypeType)} // CHECK:STDOUT: inst600000E2: {kind: RequireCompleteType, arg0: inst600000C0, type: type(inst(WitnessType))} // CHECK:STDOUT: inst600000E3: {kind: RequireCompleteType, arg0: inst600000BF, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst600000E4: {kind: LookupImplWitness, arg0: inst600000BE, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst600000E4: {kind: LookupImplWitness, arg0: inst600000BE, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst600000E5: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst600000BE, type: type(TypeType)} // CHECK:STDOUT: inst600000E6: {kind: ImplWitnessAccess, arg0: inst600000E4, arg1: element0, type: type(symbolic_constant145)} // CHECK:STDOUT: inst600000E7: {kind: SpecificImplFunction, arg0: inst600000E6, arg1: specific13, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst600000E8: {kind: RequireCompleteType, arg0: inst600000E0, type: type(inst(WitnessType))} // CHECK:STDOUT: inst600000E9: {kind: RequireCompleteType, arg0: inst600000DD, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst600000EA: {kind: LookupImplWitness, arg0: inst600000DC, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst600000EA: {kind: LookupImplWitness, arg0: inst600000DC, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst600000EB: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst600000DC, type: type(TypeType)} // CHECK:STDOUT: inst600000EC: {kind: ImplWitnessAccess, arg0: inst600000EA, arg1: element0, type: type(symbolic_constant154)} // CHECK:STDOUT: inst600000ED: {kind: SpecificImplFunction, arg0: inst600000EC, arg1: specific14, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst600000EE: {kind: RequireCompleteType, arg0: inst600000DF, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst600000EF: {kind: LookupImplWitness, arg0: inst600000DE, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst600000EF: {kind: LookupImplWitness, arg0: inst600000DE, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst600000F0: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst600000DE, type: type(TypeType)} // CHECK:STDOUT: inst600000F1: {kind: ImplWitnessAccess, arg0: inst600000EF, arg1: element0, type: type(symbolic_constant159)} // CHECK:STDOUT: inst600000F2: {kind: SpecificImplFunction, arg0: inst600000F1, arg1: specific15, type: type(inst(SpecificFunctionType))} @@ -657,29 +657,29 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: inst60000120: {kind: PatternType, arg0: inst6000011F, type: type(TypeType)} // CHECK:STDOUT: inst60000121: {kind: RequireCompleteType, arg0: inst600000F8, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000122: {kind: RequireCompleteType, arg0: inst600000F7, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst60000123: {kind: LookupImplWitness, arg0: inst600000F6, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000123: {kind: LookupImplWitness, arg0: inst600000F6, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000124: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst600000F6, type: type(TypeType)} // CHECK:STDOUT: inst60000125: {kind: ImplWitnessAccess, arg0: inst60000123, arg1: element0, type: type(symbolic_constant226)} // CHECK:STDOUT: inst60000126: {kind: SpecificImplFunction, arg0: inst60000125, arg1: specific19, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst60000127: {kind: RequireCompleteType, arg0: inst6000011F, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000128: {kind: RequireCompleteType, arg0: inst6000011A, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst60000129: {kind: LookupImplWitness, arg0: inst60000119, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000129: {kind: LookupImplWitness, arg0: inst60000119, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst6000012A: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst60000119, type: type(TypeType)} // CHECK:STDOUT: inst6000012B: {kind: ImplWitnessAccess, arg0: inst60000129, arg1: element0, type: type(symbolic_constant235)} // CHECK:STDOUT: inst6000012C: {kind: SpecificImplFunction, arg0: inst6000012B, arg1: specific20, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst6000012D: {kind: RequireCompleteType, arg0: inst6000011C, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst6000012E: {kind: LookupImplWitness, arg0: inst6000011B, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst6000012E: {kind: LookupImplWitness, arg0: inst6000011B, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst6000012F: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst6000011B, type: type(TypeType)} // CHECK:STDOUT: inst60000130: {kind: ImplWitnessAccess, arg0: inst6000012E, arg1: element0, type: type(symbolic_constant240)} // CHECK:STDOUT: inst60000131: {kind: SpecificImplFunction, arg0: inst60000130, arg1: specific21, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst60000132: {kind: RequireCompleteType, arg0: inst6000011E, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst60000133: {kind: LookupImplWitness, arg0: inst6000011D, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000133: {kind: LookupImplWitness, arg0: inst6000011D, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000134: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst6000011D, type: type(TypeType)} // CHECK:STDOUT: inst60000135: {kind: ImplWitnessAccess, arg0: inst60000133, arg1: element0, type: type(symbolic_constant245)} // CHECK:STDOUT: inst60000136: {kind: SpecificImplFunction, arg0: inst60000135, arg1: specific22, type: type(inst(SpecificFunctionType))} // CHECK:STDOUT: inst60000137: {kind: PatternType, arg0: inst600000F7, type: type(TypeType)} -// CHECK:STDOUT: inst60000138: {kind: LookupImplWitness, arg0: inst6000001B, arg1: specific_interface0, type: type(inst(WitnessType))} -// CHECK:STDOUT: inst60000139: {kind: LookupImplWitness, arg0: inst6000001C, arg1: specific_interface0, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000138: {kind: LookupImplWitness, arg0: inst6000001B, arg1: specific_interface60000000, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst60000139: {kind: LookupImplWitness, arg0: inst6000001C, arg1: specific_interface60000000, type: type(inst(WitnessType))} // CHECK:STDOUT: inst6000013A: {kind: FacetValue, arg0: inst6000001B, arg1: inst_block103, type: type(inst60000047)} // CHECK:STDOUT: inst6000013B: {kind: FunctionTypeWithSelfType, arg0: inst60000050, arg1: inst6000013A, type: type(TypeType)} // CHECK:STDOUT: inst6000013C: {kind: ImplWitnessAccess, arg0: inst60000138, arg1: element0, type: type(symbolic_constant256)} diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index a13cfa3237f1..5524de345e31 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -40,6 +40,7 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id, classes_(IdTag(check_ir_id.index, 0)), associated_constants_(IdTag(check_ir_id.index, 0)), impls_(*this), + specific_interfaces_(IdTag(check_ir_id.index, 0)), // The `+1` prevents adding a tag to the global `NameSpace::PackageInstId` // instruction. It's not a "singleton" instruction, but it's a unique // instruction id that comes right after the singletons. diff --git a/toolchain/sem_ir/ids.cpp b/toolchain/sem_ir/ids.cpp index 806fa73a5313..82581974642d 100644 --- a/toolchain/sem_ir/ids.cpp +++ b/toolchain/sem_ir/ids.cpp @@ -70,6 +70,10 @@ auto ImplId::Print(llvm::raw_ostream& out) const -> void { IdBase::PrintHex(out); } +auto SpecificInterfaceId::Print(llvm::raw_ostream& out) const -> void { + IdBase::PrintHex(out); +} + auto GenericInstIndex::Print(llvm::raw_ostream& out) const -> void { out << "generic_inst"; if (has_value()) { diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 786ae413424e..810eabd344b6 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -391,6 +391,8 @@ struct SpecificInterfaceId : public IdBase { static constexpr llvm::StringLiteral Label = "specific_interface"; using IdBase::IdBase; + + auto Print(llvm::raw_ostream& out) const -> void; }; // The index of an instruction that depends on generic parameters within a diff --git a/toolchain/sem_ir/inst_namer.h b/toolchain/sem_ir/inst_namer.h index 77500bea345a..b9d196d7882d 100644 --- a/toolchain/sem_ir/inst_namer.h +++ b/toolchain/sem_ir/inst_namer.h @@ -61,6 +61,8 @@ class InstNamer { index = sem_ir_->functions().GetRawIndex(id); } else if constexpr (std::is_same_v) { index = sem_ir_->impls().GetRawIndex(id); + } else if constexpr (std::is_same_v) { + index = sem_ir_->specific_interfaces().GetRawIndex(id); } return static_cast(GetScopeIdOffset(ScopeIdTypeEnum::For) + index);