diff options
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 30 | ||||
-rw-r--r-- | test/CodeGen/x86_64-arguments-darwin.c | 17 | ||||
-rw-r--r-- | test/CodeGen/x86_64-arguments.c | 22 |
3 files changed, 59 insertions, 10 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index a98579e05d..fd43dca5e1 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -865,6 +865,15 @@ class X86_64ABIInfo : public ABIInfo { unsigned &neededInt, unsigned &neededSSE) const; + /// The 0.98 ABI revision clarified a lot of ambiguities, + /// unfortunately in ways that were not always consistent with + /// certain previous compilers. In particular, platforms which + /// required strict binary compatibility with older versions of GCC + /// may need to exempt themselves. + bool honorsRevision0_98() const { + return !getContext().Target.getTriple().isOSDarwin(); + } + public: X86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {} @@ -1253,15 +1262,24 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, // (a) If one of the classes is MEMORY, the whole argument is // passed in memory. // - // (b) If SSEUP is not preceded by SSE, it is converted to SSE. - - // The first of these conditions is guaranteed by how we implement - // the merge (just bail). + // (b) If X87UP is not preceded by X87, the whole argument is + // passed in memory. + // + // (c) If the size of the aggregate exceeds two eightbytes and the first + // eight-byte isn’t SSE or any other eightbyte isn’t SSEUP, the whole + // argument is passed in memory. + // + // (d) If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE. + // + // Some of these are enforced by the merging logic. Others can arise + // only with unions; for example: + // union { _Complex double; unsigned; } // - // The second condition occurs in the case of unions; for example - // union { _Complex double; unsigned; }. + // Note that clauses (b) and (c) were added in 0.98. if (Hi == Memory) Lo = Memory; + if (Hi == X87Up && Lo != X87 && honorsRevision0_98()) + Lo = Memory; if (Hi == SSEUp && Lo != SSE) Hi = SSE; } diff --git a/test/CodeGen/x86_64-arguments-darwin.c b/test/CodeGen/x86_64-arguments-darwin.c new file mode 100644 index 0000000000..2f804e6efc --- /dev/null +++ b/test/CodeGen/x86_64-arguments-darwin.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s| FileCheck %s + +// rdar://9122143 +// CHECK: declare void @func(i64, double) +typedef struct _str { + union { + long double a; + long c; + }; +} str; + +void func(str s); +str ss; +void f9122143() +{ + func(ss); +} diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index 51a234d993..ebde884d78 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -1,8 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s| FileCheck %s #include <stdarg.h> -// CHECK: %0 = type { i64, double } - // CHECK: define signext i8 @f0() char f0(void) { return 0; @@ -44,8 +42,8 @@ void f7(e7 a0) { // Test merging/passing of upper eightbyte with X87 class. // -// CHECK: define %0 @f8_1() -// CHECK: define void @f8_2(i64 %a0.coerce0, double %a0.coerce1) +// CHECK: define void @f8_1(%struct.s19* sret %agg.result) +// CHECK: define void @f8_2(%struct.s19* byval align 16 %a0) union u8 { long double a; int b; @@ -245,3 +243,19 @@ v1i64 f34(v1i64 arg) { return arg; } typedef unsigned long v1i64_2 __attribute__((__vector_size__(8))); v1i64_2 f35(v1i64_2 arg) { return arg+arg; } +// rdar://9122143 +// CHECK: declare void @func(%struct._str* byval align 16) +typedef struct _str { + union { + long double a; + long c; + }; +} str; + +void func(str s); +str ss; +void f9122143() +{ + func(ss); +} + |