summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp27
-rw-r--r--clang/test/CodeGen/aarch64-arguments.c7
-rw-r--r--clang/test/CodeGen/arm-homogenous.c11
3 files changed, 40 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 53747e3fcd1..6fde4be16a4 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -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.
diff --git a/clang/test/CodeGen/aarch64-arguments.c b/clang/test/CodeGen/aarch64-arguments.c
index a70dfb1e3d4..f8758866da7 100644
--- a/clang/test/CodeGen/aarch64-arguments.c
+++ b/clang/test/CodeGen/aarch64-arguments.c
@@ -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() {}
diff --git a/clang/test/CodeGen/arm-homogenous.c b/clang/test/CodeGen/arm-homogenous.c
index 0b6f9a50940..7737399f930 100644
--- a/clang/test/CodeGen/arm-homogenous.c
+++ b/clang/test/CodeGen/arm-homogenous.c
@@ -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
OpenPOWER on IntegriCloud