Calling C++ constructors -- looking for feedback on my approach

I have a tentative PR here that adds support for calling C++ constructors in ClangImporter:

I've marked the PR as "do not merge" as I'd like some feedback on my general approach first.

Specifically, because C++ constructors always return their result indirectly (i.e. they take a this parameter pointing to the object to be initialized, even if the class is "loadable" in the Swift sense), I'm mapping C++ constructors to Swift initializers that have their return type marked with the @out attribute.

This makes things pretty easy on the IRGen side because all of the infrastructure already knows that the result will be returned indirectly, and it's guaranteed that memory will be allocated for the result.

I'm a bit concerned though that I may be misusing the @out attribute. In Swift code, I think it's only used if the return value is an address-only type, whereas in the C++ interop I would be using it for all C++ constructor calls. I'm wondering if this could lead to missed optimization opportunities; more generally, I don't want to use @out for purposes it wasn't intended for.

An alternative approach would be to add checks in various places in IRGen to see if I'm calling a C++ constructor and force an indirect return in this case. I think this would be done everywhere we're checking FI.getReturnInfo().isIndirect() today.

I'd appreciate some feedback on whether I'm going about this the right way!

1 Like

@Slava_Pestov I'm told by @gribozavr that you may have some good insights here.

@out can absolutely be used with non-address-only types, so no worries there. And it happens quite a lot when functions as “reabstracted” to be passed to generic code.

Constructor calls are complicated across the various C++ ABIs, and you may need to expose some APIs in Clang in order to handle them correctly.

Constructor calls are complicated across the various C++ ABIs, and you may need to expose some APIs in Clang in order to handle them correctly.

So you're saying I need to use something like clang::CodeGenTypes::arrangeCXXConstructorCall() instead of just naively passing the this pointer as the first argument (which may not be correct for all ABIs)? That makes sense.

Along the same lines, it looks wrong to me that SignatureExpansion::expandExternalSignatureTypes currently uses clang::CodeGen::arrangeFreeFunctionCall() to call C++ member functions. I think this should be using clang::CodeGenTypes::arrangeCXXMethodCall() to handle all ABIs correctly. Do you agree?

I'll explore this some more and work out how to handle this in IRGen. I'll loop back when I have something concrete to discuss.

I agree on both counts.

Terms of Service

Privacy Policy

Cookie Policy