aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-06-29 07:04:55 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-06-29 07:04:55 +0000
commitded137fcab19f0aace08a28b5c91574e6b23debc (patch)
tree3be48f9fa6bac39fd13585ce5b330b0ee1edd7ad
parent1df396d85d87b7d6e05cd7110d64ec8eeed74bef (diff)
We don't pass classes with a copy-constructor or destructor byval, so the address takes up an integer register (if one is available). Make sure the x86-64 ABI implementation takes that into account properly.
The fixed implementation is compatible with the implementation both gcc and llvm-gcc use. rdar://9686430 . (This is the issue that was reported in the thread "[LLVMdev] Segfault calling LLVM libs from a clang-compiled executable".) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134059 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/TargetInfo.cpp2
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp19
2 files changed, 21 insertions, 0 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 47a764bbc0..f65fc185ba 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -1765,6 +1765,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt,
// COMPLEX_X87, it is passed in memory.
case X87:
case ComplexX87:
+ if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+ ++neededInt;
return getIndirectResult(Ty);
case SSEUp:
diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp
index 01f1a445b1..6d3748ca7d 100644
--- a/test/CodeGenCXX/x86_64-arguments.cpp
+++ b/test/CodeGenCXX/x86_64-arguments.cpp
@@ -115,3 +115,22 @@ namespace test6 {
}
// CHECK: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1)
}
+
+namespace test7 {
+ struct StringRef {char* ptr; long len; };
+ class A { public: ~A(); };
+ A x(A, A, long, long, StringRef) { return A(); }
+ // Check that the StringRef is passed byval instead of expanded
+ // (which would split it between registers and memory).
+ // rdar://problem/9686430
+ // CHECK: define void @_ZN5test71xENS_1AES0_llNS_9StringRefE({{.*}} byval align 8)
+
+ // And a couple extra related tests:
+ A y(A, long double, long, long, StringRef) { return A(); }
+ // CHECK: define void @_ZN5test71yENS_1AEellNS_9StringRefE({{.*}} i8*
+ struct StringDouble {char * ptr; double d;};
+ A z(A, A, A, A, A, StringDouble) { return A(); }
+ A zz(A, A, A, A, StringDouble) { return A(); }
+ // CHECK: define void @_ZN5test71zENS_1AES0_S0_S0_S0_NS_12StringDoubleE({{.*}} byval align 8)
+ // CHECK: define void @_ZN5test72zzENS_1AES0_S0_S0_NS_12StringDoubleE({{.*}} i8*
+}