-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[cxx-interop] Add support for custom C++ destructors. #32291
Conversation
fcee2ad
to
2a6fc7e
Compare
lib/SIL/IR/TypeLowering.cpp
Outdated
@@ -1455,6 +1455,13 @@ namespace { | |||
properties.setAddressOnly(); | |||
} | |||
|
|||
// If a struct has a destructor, it's not trivial. Currently this is only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is redundant with the code right above -- if (D->isCxxNotTriviallyCopyable())
. However, you're raising a good point -- should we also set the non-trivial flag? Seems like trivial and address-only is an invalid combination of flags, and we are setting that combination now. If you agree, could you send that fix as a separate PR?
On the other hand, if we are building towards the future Swift feature of move-only structs then checking for the destructor makes sense. However, I'm not sure that Swift move-only structs would necessarily be non-trivial. They can be certainly trivial to move (imagine a Swift equivalent of std::unique_ptr
). So I'm reluctant to add code that checks for non-C++ destructors at this point, we know too little about the future Swift feature yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also set the non-trivial flag?
Yes. This is very important. Otherwise, the compiler won't create or will remove calls to destroy_addr
which will mean the destructor will not be invoked.
Seems like trivial and address-only is an invalid combination of flags
I don't think this is the case. I don't see any reason we couldn't have a trivial, address-only type.
So I'm reluctant to add code that checks for non-C++ destructors at this point, we know too little about the future Swift feature yet.
I see the concern but, I think the risk of omitting destroy_addr
calls is greater than the risk of uncertainty in the future. If and when Swift changes its mind about structs with custom destructors, there's no reason this code couldn't be updated.
That being said, it might just be easier to set the properties flag based on isCxxNotTriviallyCopyable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm reluctant to add code that checks for non-C++ destructors at this point, we know too little about the future Swift feature yet.
Thinking about this more, I think you're right. I'll update this to check isCxxNotTriviallyCopyable
and remove the llvm::any_of
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the case. I don't see any reason we couldn't have a trivial, address-only type.
Could you provide a sample use case? What would prevent a trivial type from being loadable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's an example:
struct Foo { unsigned x : 3; };
That type is trivial and also address-only. If you remove the bitfield you'll see the SIL gen produces a builtin "zeroInitializer"<Foo>() : $Foo
instruction whereas with the bitfield (as above) it is stored on the stack.
However, there are no destory_addr
s indicating that this type is trivial (and if you want, I suspect the compiler would confirm this if I add an assertion or something to double-check).
lib/SILGen/SILGenStmt.cpp
Outdated
tupleInit->SubInitializations.push_back(std::move(eltInit)); | ||
} | ||
// If this is an empty tuple, we don't want to decompose it. | ||
if (resultTupleType.getElementTypes().size()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you provide some information about why this change was needed? Was it necessary for destructors to work (if so, how does it come up?), or is it just a drive-by peephole optimization? From my reading of TupleInitialization
it seems like it should handle the empty tuple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this as actually causing issues (probably should have put that in the comment). When we have an empty tuple, we get the wrong return type later on. Because the value is returned with an indirect result, the return type should be @out Foo
but instead is ()
(because that's what's returned).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Now that the other PR is merged, could you rebase to eliminate this diff from this PR?
7ec0794
to
77463ea
Compare
77463ea
to
6aaf4a3
Compare
78b0ef5
to
4d81be9
Compare
lib/SIL/IR/TypeLowering.cpp
Outdated
@@ -1453,6 +1453,7 @@ namespace { | |||
|
|||
if (D->isCxxNotTriviallyCopyable()) { | |||
properties.setAddressOnly(); | |||
properties.setNonTrivial(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to factor out this fix into a separate PR and write a test for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#32402 done :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Now that PR is merged, would you mind rebasing to minimize the diff?
30fae47
to
8c4ea51
Compare
@@ -0,0 +1,61 @@ | |||
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop -Xcc -fno-rtti) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for repeating the comment. Each file will likely live its own life, and figuring out a couple of years from now why there is an -fno-rtti
in one of the files but not in others would be difficult if we didn't have local comments.
test/Interop/Cxx/value-witness-table/custom-virtual-destructors-irgen.swift
Outdated
Show resolved
Hide resolved
test/Interop/Cxx/value-witness-table/custom-virtual-destructors.swift
Outdated
Show resolved
Hide resolved
test/Interop/Cxx/value-witness-table/Inputs/custom-destructor.h
Outdated
Show resolved
Hide resolved
// we try to delete the base object. Until we can link against libc++, use | ||
// this dummy implementation. | ||
static void operator delete(void *p) { __builtin_unreachable(); } | ||
virtual ~HasVirtualDestructor(){}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
virtual ~HasVirtualDestructor(){}; | |
virtual ~HasVirtualDestructor() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. I agree that this is better, but I also like to use clang-format
on all my changes, and clang-format seems to disagree about this. I'm going to look into fixing our clang-format config so that this is formatted correctly.
test/Interop/Cxx/value-witness-table/Inputs/custom-destructor.h
Outdated
Show resolved
Hide resolved
test/Interop/Cxx/value-witness-table/non-trivial-implicit-destructor-irgen.swift
Outdated
Show resolved
Hide resolved
5f3d55a
to
4b6f93f
Compare
@swift-ci please smoke test. |
test/Interop/Cxx/class/non-trivial-implicit-destructor-irgen.swift
Outdated
Show resolved
Hide resolved
test/Interop/Cxx/value-witness-table/custom-virtual-destructors-irgen.swift
Outdated
Show resolved
Hide resolved
test/Interop/Cxx/value-witness-table/custom-virtual-destructors.swift
Outdated
Show resolved
Hide resolved
@@ -0,0 +1,41 @@ | |||
// RUN: %target-swift-frontend -enable-cxx-interop -I %S/Inputs %s -emit-ir | %FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming you rename the other test to custom-destructors-virtual-irgen.swift
, please rename this one to custom-destructors-non-virtual-irgen.swift
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to do the same thing with custom-destructors.swift
-> custom-destructors-non-virtual.swift
4b6f93f
to
2fff450
Compare
2fff450
to
a49aef2
Compare
@swift-ci please test. |
@swift-ci please test Windows. |
1 similar comment
@swift-ci please test Windows. |
Build failed |
@swift-ci please test Windows. |
@swift-ci please test Linux. |
1 similar comment
@swift-ci please test Linux. |
Build failed |
test/Interop/Cxx/value-witness-table/custom-destructors-non-virtual.swift
Outdated
Show resolved
Hide resolved
6454b74
to
36eb6c9
Compare
This patch adds support for custom C++ destructors. The most notable thing here, I think, is that this is the first place a struct type has a custom destructor. I suspect with more code we will expose a few places where optimization passes need to be fixed to account for this. One of many patches to fix SR-12797.
36eb6c9
to
ffa0d1c
Compare
@swift-ci please test Linux. |
Build failed |
@swift-ci please test Linux. |
@swift-ci please test macOS. |
@swift-ci please test Windows. |
1 similar comment
@swift-ci please test Windows. |
I'm going to land this as soon as the Windows bot finishes. |
Adds `CodeGen::getCXXDestructorImplicitParam`, to retrieve a C++ destructor's implicit parameter (after the "this" pointer) based on the ABI in the given CodeGenModule. This will allow other frontends (Swift, for example) to easily emit calls to object destructors with correct ABI semantics and calling convetions. This is needed for Swift C++ interop. Here's the corresponding Swift change: swiftlang/swift#32291 Differential Revision: https://reviews.llvm.org/D82392
This patch adds support for custom C++ destructors. The most notable thing here, I think, is that this is the first place a struct type has a custom destructor. I suspect with more code we will expose a few places where optimization passes need to be fixed to account for this.
One of many patches to fix SR-12797.