Implement virtual call dispatch (#5308)

Adds a `virtual_index` to `SemIR::Function` used to determine which
vtable slot
to use when calling the given function.

Then use that to lower the function call to use the vtable and
specifically the
relative vtable ABI to match the vtable entries.
This commit is contained in:
David Blaikie
2025-04-17 14:42:30 +00:00
committed by GitHub
parent 48dc411776
commit f45a632d77
6 changed files with 95 additions and 7 deletions
+4 -2
View File
@@ -151,7 +151,7 @@ static auto BuildVtable(Context& context, Parse::NodeId node_id,
// elements of the top of `vtable_stack`.
for (auto fn_decl_id : base_vtable_inst_block) {
auto fn_decl = GetCalleeFunction(context.sem_ir(), fn_decl_id);
const auto& fn = context.functions().Get(fn_decl.function_id);
auto& fn = context.functions().Get(fn_decl.function_id);
for (auto override_fn_decl_id : vtable_contents) {
auto override_fn_decl =
context.insts().GetAs<SemIR::FunctionDecl>(override_fn_decl_id);
@@ -169,14 +169,16 @@ static auto BuildVtable(Context& context, Parse::NodeId node_id,
fn_decl_id = override_fn_decl_id;
}
}
fn.virtual_index = vtable.size();
vtable.push_back(fn_decl_id);
}
}
for (auto inst_id : vtable_contents) {
auto fn_decl = context.insts().GetAs<SemIR::FunctionDecl>(inst_id);
const auto& fn = context.functions().Get(fn_decl.function_id);
auto& fn = context.functions().Get(fn_decl.function_id);
if (fn.virtual_modifier != SemIR::FunctionFields::VirtualModifier::Impl) {
fn.virtual_index = vtable.size();
vtable.push_back(inst_id);
}
}