Skip to content

[interop][SwiftToC++] print C++ interface for top-level Swift functions #40995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 11, 2022

Conversation

hyp
Copy link
Contributor

@hyp hyp commented Jan 25, 2022

Emit C++ function thunks that correspond to Swift top-level functions, alongside their extern "C" function signatures, which are places in the _impl namespace in the module's namespace.

@hyp hyp added the c++ interop Feature: Interoperability with C++ label Jan 25, 2022
@hyp
Copy link
Contributor Author

hyp commented Jan 25, 2022

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - db66120a7a7968a2e9f79b0f62c2411c43f606d1

@@ -2012,7 +2147,8 @@ class DeclAndTypePrinter::Implementation
public:
void print(Type ty, Optional<OptionalTypeKind> optionalKind,
Identifier name = Identifier(),
IsFunctionParam_t isFuncParam = IsNotFunctionParam) {
IsFunctionParam_t isFuncParam = IsNotFunctionParam,
size_t *nameIndex = nullptr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense as an API. Please use optional, or maybe a signed type. But optional is probably best.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also thinking, maybe we could compute this in the caller and just pass it as name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought: this requires a bit of refactoring but name doesn't need to be an Identifier which might help. We could refactor it to be a std::string and in the caller just use std::to_string.

std::tie(objTy, kind) =
getObjectTypeAndOptionality(param, param->getInterfaceType());
print(objTy, kind, param->getName(), IsFunctionParam,
printEmptyParamNames ? &index : nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below comment.

os << "inline ";
printFunctionDeclAsCFunctionDecl(FD,
FD->getName().getBaseIdentifier().get(),
resultTy, /*printEmptyParamNames=*/true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only print empty param names some places? Seems like that should maybe be a global config. Then you also wouldn't have to launder an int down to print.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to print out empty parameters for the inline thunks specifically as we need to use them in the body.


namespace swift {

namespace cxx_synthesis {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's anything wrong with this, but usually, there'd be some object which we put all these functions in. Maybe Implementation?

Copy link
Contributor Author

@hyp hyp Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can pull it into an object class.

}
}

StringRef getSymbolName() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is returning a reference to a string owned by the object, which is a bug waiting to happen. I wonder if it wouldn't be better to allocate mangledName in the AST context and just hold one StringRef.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

}

void printAbstractFunctionAsCxxFunctionThunk(
FuncDecl *FD, const FuncionSwiftABIInformation &funcABI) {
Copy link
Contributor

@zoecarver zoecarver Jan 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
FuncDecl *FD, const FuncionSwiftABIInformation &funcABI) {
FuncDecl *FD, const FuncionSwiftABIInformation &funcABI) {
assert(outputLang == OutputLanguageMode::Cxx);

};

FuncionSwiftABIInformation
printSwiftABIFunctionSignatureAsCxxFunction(FuncDecl *FD) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment above this and printAbstractFunctionAsCxxFunctionThunk to explain roughly what they do and why you would use one vs the other.

auto params = FD->getParameters();
if (params->size()) {
size_t index = 1;
interleave(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: interleaveComma

// CHECK: extern "C" int cfuncPassTwo(int x, int y) noexcept;
// CHECK: }

@_cdecl("cfuncPassTwo")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's kind of interesting that this cdecl name is different from the declared fn, so maybe the name should be differentCDeclName or something like that. What do you think?

(Or maybe the test name?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that makes sense to me.

@@ -0,0 +1,19 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -typecheck -module-name CdeclFunctions -emit-cxx-header-path %t/empty.h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the mock sdk here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, removed.

Comment on lines +5 to +6
// RUN: %check-cxx-header-in-clang -std=c++14 %t/empty.h
// RUN: %check-cxx-header-in-clang -std=c++17 %t/empty.h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't automate this to run 5-10 configs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I can do that as a follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added support here: #41794

Copy link
Contributor

@zoecarver zoecarver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, looks really good. Excited to see the progress! I may have a couple more comments, but generally it looks good.

@zoecarver
Copy link
Contributor

@LebJe, @hooray I noticed both of you have been putting emojis on the interop patches. If you're just watching from the side lines, that's totally fine (and thanks for the encouragement). But if you want to get involved in the project, please reach out to me (either on the forums or my email) and I can help you get started :)

@plotfi
Copy link
Contributor

plotfi commented Feb 2, 2022

@zoecarver @hyp is this a better alternative to @_cdecl?

@zoecarver
Copy link
Contributor

@zoecarver @hyp is this a better alternative to @_cdecl?

I mean, "better" is really subjective. I think we may actually not take this path of "export everything," and instead require users to mark the functions they want exported. Maybe this can be one of the first working group discussions :)

@hyp hyp force-pushed the function-to-cxx-thunk branch from db66120 to fcdcb2a Compare March 9, 2022 22:54
@hyp
Copy link
Contributor Author

hyp commented Mar 9, 2022

@zoecarver please take another look. I will need to make some changes in a follow-up PR related to unified header, but I would like to land this one first.

@hyp
Copy link
Contributor Author

hyp commented Mar 9, 2022

@swift-ci please test

@zoecarver
Copy link
Contributor

So this is still exporting everything?

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

everything

For now yes, I will need to resolve that in the future follow-up PRs

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test linux platform

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test windows platform

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test linux platform

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test linux platform

2 similar comments
@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test linux platform

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please test linux platform

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please smoke test

1 similar comment
@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please smoke test

@hyp
Copy link
Contributor Author

hyp commented Mar 10, 2022

@swift-ci please smoke test linux platform

@hyp hyp merged commit 5fb34b4 into swiftlang:main Mar 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants