<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 10, 2015 at 10:33 AM, Chih-Hung Hsieh via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chh<br>
Date: Mon Aug 10 12:33:31 2015<br>
New Revision: 244468<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=244468&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=244468&view=rev</a><br>
Log:<br>
Correct x86_64 fp128 calling convention<br>
<br>
These changes are for Android x86_64 targets to be compatible<br>
with current Android g++ and conform to AMD64 ABI.<br>
<br>
<a href="https://llvm.org/bugs/show_bug.cgi?id=23897" rel="noreferrer" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=23897</a><br>
  * Return type of long double (fp128) should be fp128, not x86_fp80.<br>
  * Vararg of long double (fp128) could be in register and overflowed to memory.<br>
<br>
<a href="https://llvm.org/bugs/show_bug.cgi?id=24111" rel="noreferrer" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=24111</a><br>
  * Return value of long double (fp128) _Complex should be in memory like a structure of {fp128,fp128}.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D11437" rel="noreferrer" target="_blank">http://reviews.llvm.org/D11437</a><br>
<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/x86_64-fp128.c<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/TargetInfo.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=244468&r1=244467&r2=244468&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=244468&r1=244467&r2=244468&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Aug 10 12:33:31 2015<br>
@@ -1862,13 +1862,20 @@ void X86_64ABIInfo::classify(QualType Ty<br>
       Hi = Integer;<br>
     } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {<br>
       Current = Integer;<br>
-    } else if ((k == BuiltinType::Float || k == BuiltinType::Double) ||<br>
-               (k == BuiltinType::LongDouble &&<br>
-                getTarget().getTriple().isOSNaCl())) {<br>
+    } else if (k == BuiltinType::Float || k == BuiltinType::Double) {<br>
       Current = SSE;<br>
     } else if (k == BuiltinType::LongDouble) {<br>
-      Lo = X87;<br>
-      Hi = X87Up;<br>
+      const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();<br>
+      if (LDF == &llvm::APFloat::IEEEquad) {<br>
+        Lo = SSE;<br>
+        Hi = SSEUp;<br>
+      } else if (LDF == &llvm::APFloat::x87DoubleExtended) {<br>
+        Lo = X87;<br>
+        Hi = X87Up;<br>
+      } else if (LDF == &llvm::APFloat::IEEEdouble) {<br>
+        Current = SSE;<br>
+      } else<br>
+        llvm_unreachable("unexpected long double representation!");<br>
     }<br>
     // FIXME: _Decimal32 and _Decimal64 are SSE.<br>
     // FIXME: _float128 and _Decimal128 are (SSE, SSEUp).<br>
@@ -1973,14 +1980,21 @@ void X86_64ABIInfo::classify(QualType Ty<br>
         Current = Integer;<br>
       else if (Size <= 128)<br>
         Lo = Hi = Integer;<br>
-    } else if (ET == getContext().FloatTy)<br>
+    } else if (ET == getContext().FloatTy) {<br>
       Current = SSE;<br>
-    else if (ET == getContext().DoubleTy ||<br>
-             (ET == getContext().LongDoubleTy &&<br>
-              getTarget().getTriple().isOSNaCl()))<br>
+    } else if (ET == getContext().DoubleTy) {<br>
       Lo = Hi = SSE;<br>
-    else if (ET == getContext().LongDoubleTy)<br>
-      Current = ComplexX87;<br>
+    } else if (ET == getContext().LongDoubleTy) {<br>
+      const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();<br>
+      if (LDF == &llvm::APFloat::IEEEquad)<br>
+        Current = Memory;<br>
+      else if (LDF == &llvm::APFloat::x87DoubleExtended)<br>
+        Current = ComplexX87;<br>
+      else if (LDF == &llvm::APFloat::IEEEdouble)<br>
+        Lo = Hi = SSE;<br>
+      else<br>
+        llvm_unreachable("unexpected long double representation!");<br>
+    }<br>
<br>
     // If this complex type crosses an eightbyte boundary then it<br>
     // should be split.<br>
@@ -2249,7 +2263,8 @@ llvm::Type *X86_64ABIInfo::GetByteVector<br>
     Ty = QualType(InnerTy, 0);<br>
<br>
   llvm::Type *IRType = CGT.ConvertType(Ty);<br>
-  if(isa<llvm::VectorType>(IRType))<br>
+  if (isa<llvm::VectorType>(IRType) ||<br>
+      IRType->getTypeID() == llvm::Type::FP128TyID)<br>
     return IRType;<br>
<br>
   // We couldn't find the preferred IR vector type for 'Ty'.<br>
<br>
Added: cfe/trunk/test/CodeGen/x86_64-fp128.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86_64-fp128.c?rev=244468&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86_64-fp128.c?rev=244468&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGen/x86_64-fp128.c (added)<br>
+++ cfe/trunk/test/CodeGen/x86_64-fp128.c Mon Aug 10 12:33:31 2015<br>
@@ -0,0 +1,116 @@<br>
+// RUN: %clang_cc1 -triple x86_64-linux-android -emit-llvm -O -o - %s \<br>
+// RUN:    | FileCheck %s --check-prefix=ANDROID --check-prefix=CHECK<br>
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -O -o - %s \<br>
+// RUN:    | FileCheck %s --check-prefix=GNU --check-prefix=CHECK<br>
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm -O -o - %s \<br>
+// RUN:    | FileCheck %s --check-prefix=GNU --check-prefix=CHECK<br>
+<br>
+// Android uses fp128 for long double but other x86_64 targets use x86_fp80.<br>
+<br>
+long double dataLD = 1.0L;<br>
+// ANDROID: @dataLD = global fp128 0xL00000000000000003FFF000000000000, align 16<br>
+// GNU: @dataLD = global x86_fp80 0xK3FFF8000000000000000, align 16<br>
+<br>
+long double _Complex dataLDC = {1.0L, 1.0L};<br>
+// ANDROID: @dataLDC = global { fp128, fp128 } { fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000003FFF000000000000 }, align 16<br>
+// GNU: @dataLDC = global { x86_fp80, x86_fp80 } { x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK3FFF8000000000000000 }, align 16<br>
+<br>
+long double TestLD(long double x) {<br>
+  return x * x;<br>
+// ANDROID: define fp128 @TestLD(fp128 %x)<br>
+// GNU: define x86_fp80 @TestLD(x86_fp80 %x)<br>
+}<br>
+<br>
+long double _Complex TestLDC(long double _Complex x) {<br>
+  return x * x;<br>
+// ANDROID: define void @TestLDC({ fp128, fp128 }* {{.*}}, { fp128, fp128 }* {{.*}} %x)<br>
+// GNU: define { x86_fp80, x86_fp80 } @TestLDC({ x86_fp80, x86_fp80 }* {{.*}} %x)<br>
+}<br>
+<br>
+typedef __builtin_va_list va_list;<br>
+<br>
+int TestGetVarInt(va_list ap) {<br>
+  return __builtin_va_arg(ap, int);<br>
+// Since int can be passed in memory or in register there is a branch and a phi.<br>
+// CHECK:   define i32 @TestGetVarInt(<br>
+// CHECK:   br<br>
+// CHECK:   load {{.*}} %overflow_arg_area_p<br></blockquote><div><br>Checks like this are not resilient to -Asserts builds. When Clang is built without assertions, it does not create names for IR values (so that %overflow_arg_area_p will be %47 instead). Please update the test to be usable on a -Asserts build. <br><br>- David<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+// CHECK:   = phi<br>
+// CHECK:   ret i32<br>
+}<br>
+<br>
+double TestGetVarDouble(va_list ap) {<br>
+  return __builtin_va_arg(ap, double);<br>
+// Since double can be passed in memory or in register there is a branch and a phi.<br>
+// CHECK:   define double @TestGetVarDouble(<br>
+// CHECK:   br<br>
+// CHECK:   load {{.*}} %overflow_arg_area_p<br>
+// CHECK:   = phi<br>
+// CHECK:   ret double<br>
+}<br>
+<br>
+long double TestGetVarLD(va_list ap) {<br>
+  return __builtin_va_arg(ap, long double);<br>
+// fp128 can be passed in memory or in register, but x86_fp80 is in memory.<br>
+// ANDROID: define fp128 @TestGetVarLD(<br>
+// GNU:     define x86_fp80 @TestGetVarLD(<br>
+// ANDROID: br<br>
+// GNU-NOT: br<br>
+// CHECK:   load {{.*}} %overflow_arg_area_p<br>
+// ANDROID: = phi<br>
+// GNU-NOT: = phi<br>
+// ANDROID: ret fp128<br>
+// GNU:     ret x86_fp80<br>
+}<br>
+<br>
+long double _Complex TestGetVarLDC(va_list ap) {<br>
+  return __builtin_va_arg(ap, long double _Complex);<br>
+// Pair of fp128 or x86_fp80 are passed as struct in memory.<br>
+// ANDROID:   define void @TestGetVarLDC({ fp128, fp128 }* {{.*}}, %struct.__va_list_tag*<br>
+// GNU:       define { x86_fp80, x86_fp80 } @TestGetVarLDC(<br>
+// CHECK-NOT: br<br>
+// CHECK:     load {{.*}} %overflow_arg_area_p<br>
+// CHECK-NOT: phi<br>
+// ANDROID:   ret void<br>
+// GNU:       ret { x86_fp80, x86_fp80 }<br>
+}<br>
+<br>
+void TestVarArg(const char *s, ...);<br>
+<br>
+void TestPassVarInt(int x) {<br>
+  TestVarArg("A", x);<br>
+// CHECK: define void @TestPassVarInt(i32 %x)<br>
+// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, i32 %x)<br>
+}<br>
+<br>
+void TestPassVarFloat(float x) {<br>
+  TestVarArg("A", x);<br>
+// CHECK: define void @TestPassVarFloat(float %x)<br>
+// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double %<br>
+}<br>
+<br>
+void TestPassVarDouble(double x) {<br>
+  TestVarArg("A", x);<br>
+// CHECK: define void @TestPassVarDouble(double %x)<br>
+// CHECK: call {{.*}} @TestVarArg(i8* {{.*}}, double %x<br>
+}<br>
+<br>
+void TestPassVarLD(long double x) {<br>
+  TestVarArg("A", x);<br>
+// ANDROID: define void @TestPassVarLD(fp128 %x)<br>
+// ANDROID: call {{.*}} @TestVarArg(i8* {{.*}}, fp128 %x<br>
+// GNU: define void @TestPassVarLD(x86_fp80 %x)<br>
+// GNU: call {{.*}} @TestVarArg(i8* {{.*}}, x86_fp80 %x<br>
+}<br>
+<br>
+void TestPassVarLDC(long double _Complex x) {<br>
+  TestVarArg("A", x);<br>
+// ANDROID:      define void @TestPassVarLDC({ fp128, fp128 }* {{.*}} %x)<br>
+// ANDROID:      store fp128 %x.{{.*}}, fp128* %<br>
+// ANDROID-NEXT: store fp128 %x.{{.*}}, fp128* %<br>
+// ANDROID-NEXT: call {{.*}} @TestVarArg(i8* {{.*}}, { fp128, fp128 }* {{.*}} %<br>
+// GNU:          define void @TestPassVarLDC({ x86_fp80, x86_fp80 }* {{.*}} %x)<br>
+// GNU:          store x86_fp80 %x.{{.*}}, x86_fp80* %<br>
+// GNU-NEXT:     store x86_fp80 %x.{{.*}}, x86_fp80* %<br>
+// GNGNU-NEXT:   call {{.*}} @TestVarArg(i8* {{.*}}, { x86_fp80, x86_fp80 }* {{.*}} %<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>