[C++ Interop] Virtual function calls

If I have a pure virtual function call, that will currently show up in the sil as:

  %0 = ...
  %1 = function_ref @_ZN5Class2fnEv : $@convention(c) (@inout Class) -> ()
  %2 = apply %1(%0) : $@convention(c) (@inout Class) -> ()

Which is a direct reference to Class::fn() which does not exist resulting in a linker error.

Three possible ideas for resolving this:

  • Something like class_method that ideally adjusts the this ptr and returns the computed vtable pointer.
  • Detect in IRGen that the original function_ref is virtual and go through a different path.
  • Somehow generate an inline thunk (manually construct an inline clang AST and send that through codegen) that takes Class* in ClangImporter.

@John_McCall ?

Virtual function calls should not in general be compiled to function_ref. They need to use an instruction that represents resolving the virtual function, probably a new cxx_virtual_method instruction.

This is complicated somewhat by multiple inheritance and the need for base-object adjustments.

Sounds reasonable. The this pointer adjustment is tricky.
I see the following ways that could work:

  • cxx_virtual_method just holds the decl. Special logic in the apply detects that and does virtual dispatch instead.
  • cxx_virtual_method takes a this pointer and returns an adjusted this pointer and the llvm function pointer. Apply then handles it accordingly either as a curried function or as two sil values for each the function pointer and the adjusted this.
  • cxx_virtual_method somehow does the apply all in one go.
  • Somehow we robustly disallow this pointer adjustment? Maybe just disallow importing funcs defined by multiple-inheritance? cxx_virtual_method just looks up the method in this case.

Doing the apply all in one go is annoying if we ever want cxx_virtual_method to be usable with different kinds of apply. Currently we don't, but if we want to support C++ exceptions or something similar someday, or allow C++ code to implement a coroutine or something, then we'd want this separation. It's also just nice to separate the concerns as much as we can.

Having cxx_virtual_method simultaneously adjust this is probably reasonable and would let us both (1) lower the instruction operationally and independently of the application and (2) robustly devirtualize in SIL if we wanted to.

3 Likes