forked from OSchip/llvm-project
Fix a major swiftcall ABI bug with trivial C++ class types.
The problem with the previous logic was that there might not be any explicit copy/move constructor declarations, e.g. if the type is trivial and we've never type-checked a copy of it. Relying on Sema's computation seems much more reliable. Also, I believe Richard's recommendation is exactly the rule we use now on the Itanium ABI, modulo the trivial_abi attribute (which this change of course fixes our handling of in Swift). This does mean that we have a less portable rule for deciding indirectness for swiftcall. I would prefer it if we just applied the Itanium rule universally under swiftcall, but in the meantime, I need to fix this bug. This only arises when defining functions with class-type arguments in C++, as we do in the Swift runtime. It doesn't affect normal Swift operation because we don't import code as C++. llvm-svn: 328942
This commit is contained in:
parent
ba8033be4d
commit
4fcd9ef673
|
@ -742,22 +742,10 @@ void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize,
|
||||||
|
|
||||||
bool swiftcall::shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
|
bool swiftcall::shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
|
||||||
const CXXRecordDecl *record) {
|
const CXXRecordDecl *record) {
|
||||||
// Following a recommendation from Richard Smith, pass a C++ type
|
// FIXME: should we not rely on the standard computation in Sema, just in
|
||||||
// indirectly only if the destructor is non-trivial or *all* of the
|
// case we want to diverge from the platform ABI (e.g. on targets where
|
||||||
// copy/move constructors are deleted or non-trivial.
|
// that uses the MSVC rule)?
|
||||||
|
return !record->canPassInRegisters();
|
||||||
if (record->hasNonTrivialDestructor())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// It would be nice if this were summarized on the CXXRecordDecl.
|
|
||||||
for (auto ctor : record->ctors()) {
|
|
||||||
if (ctor->isCopyOrMoveConstructor() && !ctor->isDeleted() &&
|
|
||||||
ctor->isTrivial()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering,
|
static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering,
|
||||||
|
|
|
@ -113,3 +113,13 @@ TEST(struct_indirect_1)
|
||||||
|
|
||||||
// Should not be byval.
|
// Should not be byval.
|
||||||
// CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}})
|
// CHECK-LABEL: define {{.*}} void @take_struct_indirect_1({{.*}}*{{( %.*)?}})
|
||||||
|
|
||||||
|
// Do a simple standalone test here of a function definition to ensure that
|
||||||
|
// we don't have problems due to failure to eagerly synthesize a copy
|
||||||
|
// constructor declaration.
|
||||||
|
class struct_trivial {
|
||||||
|
int x;
|
||||||
|
};
|
||||||
|
// CHECK-LABEL define void @test_struct_trivial(i32{{( %.*)?}})
|
||||||
|
extern "C" SWIFTCALL
|
||||||
|
void test_struct_trivial(struct_trivial triv) {}
|
||||||
|
|
Loading…
Reference in New Issue