Skip to content

Commit 545354a

Browse files
authored
Import symbolic vtable entries as attached constants (#5871)
Similar to 26ec78e - vtable entries can't be unattached symbolic constants, because if they are they can't be `GetValueInSpecific`d because they lack the context for their generic/specific. Importing mostly wants to make/import things as unattached constants - but `ImportRef` supports attached constants, so use those - but we don't need the laziness, so use `LoadedImportRef`.
1 parent 139bdf2 commit 545354a

File tree

3 files changed

+50
-19
lines changed

3 files changed

+50
-19
lines changed

toolchain/check/class.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
187187
// TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the
188188
// elements of the top of `vtable_stack`.
189189
for (auto base_vtable_entry_id : base_vtable_inst_block) {
190+
LoadImportRef(context, base_vtable_entry_id);
190191
auto [derived_vtable_entry_id, derived_vtable_entry_const_id, fn_id,
191192
specific_id] =
192193
DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,

toolchain/check/import_ref.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,20 +1977,46 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
19771977
.Get(import_vtable.class_id)
19781978
.first_owning_decl_id);
19791979

1980+
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
1981+
1982+
auto class_const_inst = resolver.local_insts().Get(
1983+
resolver.local_constant_values().GetInstId(class_const_id));
1984+
19801985
// TODO: Ensure the vtable is only imported once, in eg: if there's distinct
19811986
// vtable constants (imported from multiple libraries using the vtable) that
19821987
// refer to the same vtable, the vtable should still be singular.
19831988
auto virtual_functions =
1984-
GetLocalInstBlockContents(resolver, import_vtable.virtual_functions_id);
1989+
resolver.import_inst_blocks().Get(import_vtable.virtual_functions_id);
19851990

1986-
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
1991+
llvm::SmallVector<SemIR::InstId> lazy_virtual_functions;
1992+
lazy_virtual_functions.reserve(virtual_functions.size());
1993+
for (auto vtable_entry_id : virtual_functions) {
1994+
auto local_attached_constant_id = GetLocalConstantId(
1995+
resolver,
1996+
resolver.import_constant_values().GetAttached(vtable_entry_id));
1997+
lazy_virtual_functions.push_back(
1998+
resolver.local_constant_values().GetInstIdIfValid(
1999+
local_attached_constant_id));
2000+
}
19872001

19882002
if (resolver.HasNewWork()) {
19892003
return ResolveResult::Retry();
19902004
}
19912005

1992-
auto class_const_inst = resolver.local_insts().Get(
1993-
resolver.local_constant_values().GetInstId(class_const_id));
2006+
for (auto& vtable_entry_id : lazy_virtual_functions) {
2007+
// Use LoadedImportRef for imported symbolic constant vtable entries so they
2008+
// can carry attached constants necessary for applying specifics to these
2009+
// constants when they are used.
2010+
auto local_attached_constant_id =
2011+
resolver.local_constant_values().Get(vtable_entry_id);
2012+
if (local_attached_constant_id.is_symbolic()) {
2013+
vtable_entry_id = AddLoadedImportRef(
2014+
resolver,
2015+
GetSingletonType(resolver.local_context(),
2016+
SemIR::SpecificFunctionType::TypeInstId),
2017+
vtable_entry_id, local_attached_constant_id);
2018+
}
2019+
}
19942020

19952021
auto class_id = SemIR::ClassId::None;
19962022
if (class_const_inst.Is<SemIR::ClassType>()) {
@@ -2001,10 +2027,11 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
20012027
class_const_inst.type_id());
20022028
class_id = generic_class_type.class_id;
20032029
}
2030+
20042031
auto new_vtable_id = resolver.local_vtables().Add(
20052032
{{.class_id = class_id,
2006-
.virtual_functions_id = GetLocalCanonicalInstBlockId(
2007-
resolver, import_vtable.virtual_functions_id, virtual_functions)}});
2033+
.virtual_functions_id =
2034+
resolver.local_inst_blocks().Add(lazy_virtual_functions)}});
20082035

20092036
return ResolveAsDeduplicated<SemIR::VtablePtr>(
20102037
resolver, {.type_id = GetPointerType(resolver.local_context(),

toolchain/check/testdata/class/virtual_modifiers.carbon

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6784,19 +6784,19 @@ class T2(G2:! type) {
67846784
// CHECK:STDOUT: %Base.F.e26: %Base.F.type.f17 = struct_value () [symbolic]
67856785
// CHECK:STDOUT: %pattern_type.9f7: type = pattern_type %Base.370 [symbolic]
67866786
// CHECK:STDOUT: %Base.F.specific_fn.892: <specific function> = specific_function %Base.F.e26, @Base.F(%T) [symbolic]
6787-
// CHECK:STDOUT: %Base.vtable_ptr.f4433b.1: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T) [symbolic]
6787+
// CHECK:STDOUT: %Base.vtable_ptr.f15b84.1: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T) [symbolic]
67886788
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %Base.370 [symbolic]
6789-
// CHECK:STDOUT: %Base.vtable_ptr.f4433b.2: ref %ptr.454 = vtable_ptr @Base.vtable.2, @Base(%T) [symbolic]
6789+
// CHECK:STDOUT: %Base.vtable_ptr.f15b84.2: ref %ptr.454 = vtable_ptr @Base.vtable.2, @Base(%T) [symbolic]
67906790
// CHECK:STDOUT: %Base.ea5: type = class_type @Base, @Base(%T1) [concrete]
67916791
// CHECK:STDOUT: %Base.F.type.d82: type = fn_type @Base.F, @Base(%T1) [concrete]
67926792
// CHECK:STDOUT: %Base.F.d25: %Base.F.type.d82 = struct_value () [concrete]
67936793
// CHECK:STDOUT: %pattern_type.3bf: type = pattern_type %Base.ea5 [concrete]
67946794
// CHECK:STDOUT: %Base.F.specific_fn.210: <specific function> = specific_function %Base.F.d25, @Base.F(%T1) [concrete]
6795-
// CHECK:STDOUT: %Base.vtable_ptr.5be: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T1) [concrete]
6795+
// CHECK:STDOUT: %Base.vtable_ptr.88e: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T1) [concrete]
67966796
// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete]
6797-
// CHECK:STDOUT: %Base.vtable_ptr.f4433b.3: ref %ptr.454 = vtable_ptr @Base.vtable.3, @Base(%T) [symbolic]
6797+
// CHECK:STDOUT: %Base.vtable_ptr.f15b84.3: ref %ptr.454 = vtable_ptr @Base.vtable.3, @Base(%T) [symbolic]
67986798
// CHECK:STDOUT: %.b74: ref %ptr.454 = class_element_access file.%v.var, element0 [concrete]
6799-
// CHECK:STDOUT: %Base.val: %Base.ea5 = struct_value (%Base.vtable_ptr.5be) [concrete]
6799+
// CHECK:STDOUT: %Base.val: %Base.ea5 = struct_value (%Base.vtable_ptr.88e) [concrete]
68006800
// CHECK:STDOUT: }
68016801
// CHECK:STDOUT:
68026802
// CHECK:STDOUT: imports {
@@ -6805,12 +6805,15 @@ class T2(G2:! type) {
68056805
// CHECK:STDOUT: import Core//prelude
68066806
// CHECK:STDOUT: import Core//prelude/...
68076807
// CHECK:STDOUT: }
6808-
// CHECK:STDOUT: %Main.import_ref.03f: ref %ptr.454 = import_ref Main//generic_lib, loc6_1, loaded [symbolic = @Base.%vtable_ptr (constants.%Base.vtable_ptr.f4433b.3)]
6808+
// CHECK:STDOUT: %Main.import_ref.03f: ref %ptr.454 = import_ref Main//generic_lib, loc6_1, loaded [symbolic = @Base.%vtable_ptr (constants.%Base.vtable_ptr.f15b84.3)]
68096809
// CHECK:STDOUT: %Main.import_ref.5ab3ec.1: type = import_ref Main//generic_lib, loc4_17, loaded [symbolic = @Base.%T (constants.%T)]
68106810
// CHECK:STDOUT: %Main.import_ref.05e: <witness> = import_ref Main//generic_lib, loc6_1, loaded [concrete = constants.%complete_type]
68116811
// CHECK:STDOUT: %Main.import_ref.8e0 = import_ref Main//generic_lib, inst26 [no loc], unloaded
68126812
// CHECK:STDOUT: %Main.import_ref.e54 = import_ref Main//generic_lib, loc5_30, unloaded
68136813
// CHECK:STDOUT: %Main.import_ref.5ab3ec.2: type = import_ref Main//generic_lib, loc4_17, loaded [symbolic = @Base.%T (constants.%T)]
6814+
// CHECK:STDOUT: %Main.import_ref.4f4e13.1: <specific function> = import_ref Main//generic_lib, inst46 [no loc], loaded [symbolic = constants.%Base.F.specific_fn.892]
6815+
// CHECK:STDOUT: %Main.import_ref.4f4e13.2: <specific function> = import_ref Main//generic_lib, inst46 [no loc], loaded [symbolic = constants.%Base.F.specific_fn.892]
6816+
// CHECK:STDOUT: %Main.import_ref.4f4e13.3: <specific function> = import_ref Main//generic_lib, inst46 [no loc], loaded [symbolic = constants.%Base.F.specific_fn.892]
68146817
// CHECK:STDOUT: }
68156818
// CHECK:STDOUT:
68166819
// CHECK:STDOUT: file {
@@ -6845,7 +6848,7 @@ class T2(G2:! type) {
68456848
// CHECK:STDOUT: %Base.F.type: type = fn_type @Base.F, @Base(%T) [symbolic = %Base.F.type (constants.%Base.F.type.f17)]
68466849
// CHECK:STDOUT: %Base.F: @Base.%Base.F.type (%Base.F.type.f17) = struct_value () [symbolic = %Base.F (constants.%Base.F.e26)]
68476850
// CHECK:STDOUT: %Base.F.specific_fn: <specific function> = specific_function %Base.F, @Base.F(%T) [symbolic = %Base.F.specific_fn (constants.%Base.F.specific_fn.892)]
6848-
// CHECK:STDOUT: %vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T) [symbolic = %vtable_ptr (constants.%Base.vtable_ptr.f4433b.1)]
6851+
// CHECK:STDOUT: %vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable.1, @Base(%T) [symbolic = %vtable_ptr (constants.%Base.vtable_ptr.f15b84.1)]
68496852
// CHECK:STDOUT:
68506853
// CHECK:STDOUT: class {
68516854
// CHECK:STDOUT: complete_type_witness = imports.%Main.import_ref.05e
@@ -6858,15 +6861,15 @@ class T2(G2:! type) {
68586861
// CHECK:STDOUT: }
68596862
// CHECK:STDOUT:
68606863
// CHECK:STDOUT: vtable @Base.vtable.1 {
6861-
// CHECK:STDOUT: constants.%Base.F.specific_fn.892
6864+
// CHECK:STDOUT: imports.%Main.import_ref.4f4e13.1
68626865
// CHECK:STDOUT: }
68636866
// CHECK:STDOUT:
68646867
// CHECK:STDOUT: vtable @Base.vtable.2 {
6865-
// CHECK:STDOUT: constants.%Base.F.specific_fn.892
6868+
// CHECK:STDOUT: imports.%Main.import_ref.4f4e13.2
68666869
// CHECK:STDOUT: }
68676870
// CHECK:STDOUT:
68686871
// CHECK:STDOUT: vtable @Base.vtable.3 {
6869-
// CHECK:STDOUT: constants.%Base.F.specific_fn.892
6872+
// CHECK:STDOUT: imports.%Main.import_ref.4f4e13.3
68706873
// CHECK:STDOUT: }
68716874
// CHECK:STDOUT:
68726875
// CHECK:STDOUT: generic virtual fn @Base.F(imports.%Main.import_ref.5ab3ec.2: type) [from "generic_lib.carbon"] {
@@ -6884,7 +6887,7 @@ class T2(G2:! type) {
68846887
// CHECK:STDOUT: !entry:
68856888
// CHECK:STDOUT: %.loc7_20.1: %empty_struct_type = struct_literal ()
68866889
// CHECK:STDOUT: %.loc7_20.2: ref %ptr.454 = class_element_access file.%v.var, element0 [concrete = constants.%.b74]
6887-
// CHECK:STDOUT: %.loc7_20.3: init %ptr.454 = initialize_from constants.%Base.vtable_ptr.5be to %.loc7_20.2 [concrete = constants.%Base.vtable_ptr.5be]
6890+
// CHECK:STDOUT: %.loc7_20.3: init %ptr.454 = initialize_from constants.%Base.vtable_ptr.88e to %.loc7_20.2 [concrete = constants.%Base.vtable_ptr.88e]
68886891
// CHECK:STDOUT: %.loc7_20.4: init %Base.ea5 = class_init (%.loc7_20.3), file.%v.var [concrete = constants.%Base.val]
68896892
// CHECK:STDOUT: %.loc7_1: init %Base.ea5 = converted %.loc7_20.1, %.loc7_20.4 [concrete = constants.%Base.val]
68906893
// CHECK:STDOUT: assign file.%v.var, %.loc7_1
@@ -6898,7 +6901,7 @@ class T2(G2:! type) {
68986901
// CHECK:STDOUT: %Base.F.type => constants.%Base.F.type.f17
68996902
// CHECK:STDOUT: %Base.F => constants.%Base.F.e26
69006903
// CHECK:STDOUT: %Base.F.specific_fn => constants.%Base.F.specific_fn.892
6901-
// CHECK:STDOUT: %vtable_ptr => constants.%Base.vtable_ptr.f4433b.2
6904+
// CHECK:STDOUT: %vtable_ptr => constants.%Base.vtable_ptr.f15b84.2
69026905
// CHECK:STDOUT: }
69036906
// CHECK:STDOUT:
69046907
// CHECK:STDOUT: specific @Base.F(constants.%T) {
@@ -6917,7 +6920,7 @@ class T2(G2:! type) {
69176920
// CHECK:STDOUT: %Base.F.type => constants.%Base.F.type.d82
69186921
// CHECK:STDOUT: %Base.F => constants.%Base.F.d25
69196922
// CHECK:STDOUT: %Base.F.specific_fn => constants.%Base.F.specific_fn.210
6920-
// CHECK:STDOUT: %vtable_ptr => constants.%Base.vtable_ptr.5be
6923+
// CHECK:STDOUT: %vtable_ptr => constants.%Base.vtable_ptr.88e
69216924
// CHECK:STDOUT: }
69226925
// CHECK:STDOUT:
69236926
// CHECK:STDOUT: specific @Base.F(constants.%T1) {

0 commit comments

Comments
 (0)