]> granicus.if.org Git - clang/commitdiff
Fix AAPCS compliance for HFAs containing doubles and long doubles
authorOliver Stannard <oliver.stannard@arm.com>
Fri, 7 Feb 2014 11:25:57 +0000 (11:25 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Fri, 7 Feb 2014 11:25:57 +0000 (11:25 +0000)
An HFA is defined as a struct containing floating point values of the
same machine type. In the 32-bit ABI, double and long double have the
same machine type, so a struct with a mixture of these types must be an
HFA (assuming it meets the other criteria).

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

lib/CodeGen/TargetInfo.cpp
test/CodeGen/aarch64-arguments.c
test/CodeGen/arm-homogenous.c

index 53747e3fcd1a3dc1dce9b26d54984fbcea817e76..6fde4be16a4f12b07eb30dfbc0892f65c52bb43b 100644 (file)
@@ -3415,10 +3415,29 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
     const Type *TyPtr = Ty.getTypePtr();
     if (!Base)
       Base = TyPtr;
-    if (Base != TyPtr &&
-        (!Base->isVectorType() || !TyPtr->isVectorType() ||
-         Context.getTypeSize(Base) != Context.getTypeSize(TyPtr)))
-      return false;
+
+    if (Base != TyPtr) {
+      // Homogeneous aggregates are defined as containing members with the
+      // same machine type. There are two cases in which two members have
+      // different TypePtrs but the same machine type:
+
+      // 1) Vectors of the same length, regardless of the type and number
+      //    of their members.
+      const bool SameLengthVectors = Base->isVectorType() && TyPtr->isVectorType()
+        && (Context.getTypeSize(Base) == Context.getTypeSize(TyPtr));
+
+      // 2) In the 32-bit AAPCS, `double' and `long double' have the same
+      //    machine type. This is not the case for the 64-bit AAPCS.
+      const bool SameSizeDoubles =
+           (   (   Base->isSpecificBuiltinType(BuiltinType::Double)
+                && TyPtr->isSpecificBuiltinType(BuiltinType::LongDouble))
+            || (   Base->isSpecificBuiltinType(BuiltinType::LongDouble)
+                && TyPtr->isSpecificBuiltinType(BuiltinType::Double)))
+        && (Context.getTypeSize(Base) == Context.getTypeSize(TyPtr));
+
+      if (!SameLengthVectors && !SameSizeDoubles)
+        return false;
+    }
   }
 
   // Homogeneous Aggregates can have at most 4 members of the base type.
index a70dfb1e3d4d81ba3715cc45a579acc238d8eacb..f8758866da7b416ead5f889fcaed632e80ce1220 100644 (file)
@@ -190,5 +190,10 @@ void f42(int x0, int x1, int x2, int x3, int x4, __int128 x6_7, __int128 stacked
 void variadic(int a, ...);
 void f43(__fp16 *in) {
   variadic(42, *in);
-// CHECK: call void @variadic(i32 42, double
+// PCS: call void (i32, ...)* @variadic(i32 42, double
 }
+
+// Checking: `double' and `long double' have different machine types, so cannot both be in an HFA
+struct s44 { long double a; double b; };
+// PCS: define void @f44(%struct.s44*
+struct s44 f44() {}
index 0b6f9a50940cccd080828aaca20ec374b14a1f47..7737399f930ddf65fe0f3f5df1ed683c9a750c29 100644 (file)
@@ -205,6 +205,17 @@ void test_struct_of_vecs(void) {
   takes_struct_of_vecs(3.0, g_vec, g_vec, 4.0);
 }
 
+typedef struct {
+  double a;
+  long double b;
+} struct_of_double_and_long_double;
+struct_of_double_and_long_double g_dld;
+
+struct_of_double_and_long_double test_struct_of_double_and_long_double(void) {
+  return g_dld;
+}
+// CHECK: define arm_aapcs_vfpcc %struct.struct_of_double_and_long_double @test_struct_of_double_and_long_double()
+
 // FIXME: Tests necessary:
 //         - Vectors
 //         - C++ stuff