diff options
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 27 | ||||
-rw-r--r-- | clang/test/CodeGen/aarch64-arguments.c | 7 | ||||
-rw-r--r-- | clang/test/CodeGen/arm-homogenous.c | 11 |
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 |