]> granicus.if.org Git - clang/commitdiff
The 0.98 revision of the x86-64 ABI clarified a lot of things, some
authorJohn McCall <rjmccall@apple.com>
Thu, 21 Apr 2011 01:20:55 +0000 (01:20 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 21 Apr 2011 01:20:55 +0000 (01:20 +0000)
of which break strict compatibility with previous compilers.  Implement
one of them and then immediately opt out on Darwin.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129899 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/x86_64-arguments-darwin.c [new file with mode: 0644]
test/CodeGen/x86_64-arguments.c

index a98579e05d156cdf3059545e4e845216c5b1598a..fd43dca5e158a0039f9cb97e927bcefb18cd47f8 100644 (file)
@@ -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 (file)
index 0000000..2f804e6
--- /dev/null
@@ -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);
+}
index 51a234d993cade804ae245f106afbff6a83d97aa..ebde884d78d6c665f7baafcad80ab2f40eeddfa1 100644 (file)
@@ -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);
+}
+