Add a vtableDecl inst and use that in classes instead of VtablePtr (#5945)

This addresses/avoids the duplicate import of vtables.

I went through a few iterations/etc along the way and left them in the
commit
history for the PR in case any of them are useful to illustrate how I
got here,
or worth revisiting.

Essentially I ended up with a circularity in importing - importing the
class
imported the vtable_decl which imported the virtual functions - and then
pending
specifics of the virtual functions needed the self specific of the
enclosing
class which wasn't ready yet.

Adding ImportRef to the vtable_decl to break the cycle caused me trouble
when
naming the vtable_decl instructions - so I tried making the functions in
the
vtable unloaded ImportRefs instead. That worked, but meant that
importing a
class still was doing O(number of vtable entries) even if the vtable
wasn't
used.

So I revisited the lazy vtable_decl - figured out how to make the naming
work
(when building the vtable_ptr, even though the vtable_decl doesn't have
to be
loaded for the vtable_ptr, I force it to be loaded anyway, to load the
vtable so
it's usable by lowering, etc). And then I could go back to the old
non-lazy
loaded vtable entries (using some loaded ImportRefs in the cases where
we needed
them/had already adopted them).

Then thinking about the VtablePtr instruction, went back/forth on
exactly what
it needed - went from VtablePtr's member being a VtableDecl InstId, to a
ClassId, then back to a VtableId as it was before this patch.

Naming the instructions has one oddity, that the VtableDecl and
VtablePtr
instructions seem to need to add the pending name for the VtableId -
despite not
using the VtableId in their own name - should the inst namer be doing
this work
for parameters of instructions rather than requiring the inst to do it
deliberately? (or am I holding it wrong in some way?)

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
David Blaikie
2025-08-15 18:36:54 +00:00
committed by GitHub
co-authored by Richard Smith
parent 7727c62880
commit 3f9fc633fe
12 changed files with 292 additions and 313 deletions
+9 -16
View File
@@ -145,15 +145,15 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
// Get some base class/type/specific info.
if (base_class_type) {
auto& base_class_info = context.classes().Get(base_class_type->class_id);
auto base_vtable_ptr_inst_id = base_class_info.vtable_ptr_id;
if (base_vtable_ptr_inst_id.has_value()) {
LoadImportRef(context, base_vtable_ptr_inst_id);
auto base_vtable_decl_inst_id = base_class_info.vtable_decl_id;
if (base_vtable_decl_inst_id.has_value()) {
LoadImportRef(context, base_vtable_decl_inst_id);
auto canonical_base_vtable_inst_id =
context.constant_values().GetConstantInstId(base_vtable_ptr_inst_id);
const auto& base_vtable_ptr_inst =
context.insts().GetAs<SemIR::VtablePtr>(
context.constant_values().GetConstantInstId(base_vtable_decl_inst_id);
const auto& base_vtable_decl_inst =
context.insts().GetAs<SemIR::VtableDecl>(
canonical_base_vtable_inst_id);
base_vtable_id = base_vtable_ptr_inst.vtable_id;
base_vtable_id = base_vtable_decl_inst.vtable_id;
base_class_specific_id = base_class_type->specific_id;
}
}
@@ -187,7 +187,6 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,
// TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the
// elements of the top of `vtable_stack`.
for (auto base_vtable_entry_id : base_vtable_inst_block) {
LoadImportRef(context, base_vtable_entry_id);
auto [derived_vtable_entry_id, derived_vtable_entry_const_id, fn_id,
specific_id] =
DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,
@@ -303,15 +302,9 @@ static auto CheckCompleteClassType(
if (class_info.is_dynamic) {
auto vtable_id = BuildVtable(context, node_id, class_id, base_class_type,
vtable_contents);
auto vptr_type_id = GetPointerType(context, SemIR::VtableType::TypeInstId);
auto generic_id = class_info.generic_id;
auto self_specific_id = context.generics().GetSelfSpecific(generic_id);
class_info.vtable_ptr_id =
AddInst<SemIR::VtablePtr>(context, node_id,
{.type_id = vptr_type_id,
.vtable_id = vtable_id,
.specific_id = self_specific_id});
class_info.vtable_decl_id = AddInst<SemIR::VtableDecl>(
context, node_id, {.type_id = vptr_type_id, .vtable_id = vtable_id});
}
auto struct_type_id = GetStructType(