forked from OSchip/llvm-project
Fix AAPCS compliance for HFAs containing doubles and long doubles
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). llvm-svn: 200971
This commit is contained in:
parent
1dc1034218
commit
5e8558fce0
|
@ -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.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue