x86-32 Darwin ABI: Single element arrays can be part of "single
element structures", which have different ABI rules. - Current return-arguments-32 status is: 1 out of 1000 failures (-7) - Also, vectors inside "single element structs" require special handling. llvm-svn: 68196
This commit is contained in:
parent
8b0dba358a
commit
58e2971bb0
|
|
@ -167,7 +167,7 @@ static bool isEmptyRecord(QualType T) {
|
|||
///
|
||||
/// \return The field declaration for the single non-empty field, if
|
||||
/// it exists.
|
||||
static const FieldDecl *isSingleElementStruct(QualType T) {
|
||||
static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
|
||||
const RecordType *RT = T->getAsStructureType();
|
||||
if (!RT)
|
||||
return 0;
|
||||
|
|
@ -176,20 +176,25 @@ static const FieldDecl *isSingleElementStruct(QualType T) {
|
|||
if (RD->hasFlexibleArrayMember())
|
||||
return 0;
|
||||
|
||||
const FieldDecl *Found = 0;
|
||||
const Type *Found = 0;
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(),
|
||||
e = RD->field_end(); i != e; ++i) {
|
||||
const FieldDecl *FD = *i;
|
||||
QualType FT = FD->getType();
|
||||
|
||||
// Treat single element arrays as the element
|
||||
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT))
|
||||
if (AT->getSize().getZExtValue() == 1)
|
||||
FT = AT->getElementType();
|
||||
|
||||
if (isEmptyRecord(FT)) {
|
||||
// Ignore
|
||||
} else if (Found) {
|
||||
return 0;
|
||||
} else if (!CodeGenFunction::hasAggregateLLVMType(FT)) {
|
||||
Found = FD;
|
||||
Found = FT.getTypePtr();
|
||||
} else {
|
||||
Found = isSingleElementStruct(FT);
|
||||
Found = isSingleElementStruct(FT, Context);
|
||||
if (!Found)
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -253,6 +258,10 @@ class DefaultABIInfo : public ABIInfo {
|
|||
class X86_32ABIInfo : public ABIInfo {
|
||||
bool IsDarwin;
|
||||
|
||||
static bool isRegisterSize(unsigned Size) {
|
||||
return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
|
||||
}
|
||||
|
||||
public:
|
||||
ABIArgInfo classifyReturnType(QualType RetTy,
|
||||
ASTContext &Context) const;
|
||||
|
|
@ -305,9 +314,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
|||
if (!IsDarwin && !RetTy->isAnyComplexType())
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
// Classify "single element" structs as their element type.
|
||||
const FieldDecl *SeltFD = isSingleElementStruct(RetTy);
|
||||
if (SeltFD) {
|
||||
QualType SeltTy = SeltFD->getType()->getDesugaredType();
|
||||
if (const Type *SeltTy = isSingleElementStruct(RetTy, Context)) {
|
||||
if (const BuiltinType *BT = SeltTy->getAsBuiltinType()) {
|
||||
// FIXME: This is gross, it would be nice if we could just
|
||||
// pass back SeltTy and have clients deal with it. Is it worth
|
||||
|
|
@ -326,21 +333,22 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
|
|||
llvm::Type *PtrTy =
|
||||
llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
return ABIArgInfo::getCoerce(PtrTy);
|
||||
} else if (SeltTy->isVectorType()) {
|
||||
// 64- and 128-bit vectors are never returned in a
|
||||
// register when inside a structure.
|
||||
uint64_t Size = Context.getTypeSize(RetTy);
|
||||
if (Size == 64 || Size == 128)
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
|
||||
return classifyReturnType(QualType(SeltTy, 0), Context);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Size = Context.getTypeSize(RetTy);
|
||||
if (Size == 8) {
|
||||
return ABIArgInfo::getCoerce(llvm::Type::Int8Ty);
|
||||
} else if (Size == 16) {
|
||||
return ABIArgInfo::getCoerce(llvm::Type::Int16Ty);
|
||||
} else if (Size == 32) {
|
||||
return ABIArgInfo::getCoerce(llvm::Type::Int32Ty);
|
||||
} else if (Size == 64) {
|
||||
return ABIArgInfo::getCoerce(llvm::Type::Int64Ty);
|
||||
} else {
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
}
|
||||
if (isRegisterSize(Size))
|
||||
return ABIArgInfo::getCoerce(llvm::IntegerType::get(Size));
|
||||
|
||||
return ABIArgInfo::getIndirect(0);
|
||||
} else {
|
||||
return ABIArgInfo::getDirect();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct s9 f9_1(void) {
|
|||
void f9_2(struct s9 a0) {
|
||||
}
|
||||
|
||||
// Return of small structures and unions...
|
||||
// Return of small structures and unions
|
||||
|
||||
// RUN: grep 'float @f10()' %t &&
|
||||
struct s10 {
|
||||
|
|
@ -71,12 +71,14 @@ struct s10 {
|
|||
float f;
|
||||
} f10(void) {}
|
||||
|
||||
// Small vectors and 1 x {i64,double} are returned in registers...
|
||||
// Small vectors and 1 x {i64,double} are returned in registers
|
||||
|
||||
// RUN: grep 'i32 @f11()' %t &&
|
||||
// RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t &&
|
||||
// RUN: grep 'i64 @f13()' %t &&
|
||||
// RUN: grep 'i64 @f14()' %t &&
|
||||
// RUN: grep '<2 x i64> @f15()' %t &&
|
||||
// RUN: grep '<2 x i64> @f16()' %t &&
|
||||
typedef short T11 __attribute__ ((vector_size (4)));
|
||||
T11 f11(void) {}
|
||||
typedef int T12 __attribute__ ((vector_size (8)));
|
||||
|
|
@ -85,5 +87,34 @@ typedef long long T13 __attribute__ ((vector_size (8)));
|
|||
T13 f13(void) {}
|
||||
typedef double T14 __attribute__ ((vector_size (8)));
|
||||
T14 f14(void) {}
|
||||
typedef long long T15 __attribute__ ((vector_size (16)));
|
||||
T15 f15(void) {}
|
||||
typedef double T16 __attribute__ ((vector_size (16)));
|
||||
T16 f16(void) {}
|
||||
|
||||
// And when the single element in a struct (but not for 64 and
|
||||
// 128-bits).
|
||||
|
||||
// RUN: grep 'i32 @f17()' %t &&
|
||||
// RUN: grep -F 'void @f18(%0* noalias sret %agg.result)' %t &&
|
||||
// RUN: grep -F 'void @f19(%1* noalias sret %agg.result)' %t &&
|
||||
// RUN: grep -F 'void @f20(%2* noalias sret %agg.result)' %t &&
|
||||
// RUN: grep -F 'void @f21(%3* noalias sret %agg.result)' %t &&
|
||||
// RUN: grep -F 'void @f22(%4* noalias sret %agg.result)' %t &&
|
||||
struct { T11 a; } f17(void) {}
|
||||
struct { T12 a; } f18(void) {}
|
||||
struct { T13 a; } f19(void) {}
|
||||
struct { T14 a; } f20(void) {}
|
||||
struct { T15 a; } f21(void) {}
|
||||
struct { T16 a; } f22(void) {}
|
||||
|
||||
// Single element structures are handled specially
|
||||
|
||||
// RUN: grep -F 'float @f23()' %t &&
|
||||
// RUN: grep -F 'float @f24()' %t &&
|
||||
// RUN: grep -F 'float @f25()' %t &&
|
||||
struct { float a; } f23(void) {}
|
||||
struct { float a[1]; } f24(void) {}
|
||||
struct { struct {} a; struct { float a[1]; } b; } f25(void) {}
|
||||
|
||||
// RUN: true
|
||||
|
|
|
|||
Loading…
Reference in New Issue