Simplify code for returning a struct for Darwin x86-32 ABI. Use a better type for a function returning a struct containing only a pointer. Handle the edge case of a struct containing only a float or double plus some dead padding instead of asserting.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144960 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2011-11-18 01:25:50 +00:00
Родитель 87adb0bf93
Коммит bd4d3bcd2c
3 изменённых файлов: 23 добавлений и 44 удалений

Просмотреть файл

@ -252,6 +252,11 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
}
}
// We don't consider a struct a single-element struct if it has
// padding beyond the element type.
if (Found && Context.getTypeSize(Found) != Context.getTypeSize(T))
return 0;
return Found;
}
@ -561,51 +566,21 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
return ABIArgInfo::getIndirect(0);
// Classify "single element" structs as their element type.
if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) {
if (const BuiltinType *BT = SeltTy->getAs<BuiltinType>()) {
if (BT->isIntegerType()) {
// We need to use the size of the structure, padding
// bit-fields can adjust that to be larger than the single
// element type.
uint64_t Size = getContext().getTypeSize(RetTy);
return ABIArgInfo::getDirect(
llvm::IntegerType::get(getVMContext(), (unsigned)Size));
}
if (BT->getKind() == BuiltinType::Float) {
assert(getContext().getTypeSize(RetTy) ==
getContext().getTypeSize(SeltTy) &&
"Unexpect single element structure size!");
return ABIArgInfo::getDirect(llvm::Type::getFloatTy(getVMContext()));
}
if (BT->getKind() == BuiltinType::Double) {
assert(getContext().getTypeSize(RetTy) ==
getContext().getTypeSize(SeltTy) &&
"Unexpect single element structure size!");
return ABIArgInfo::getDirect(llvm::Type::getDoubleTy(getVMContext()));
}
} else if (SeltTy->isPointerType()) {
// FIXME: It would be really nice if this could come out as the proper
// pointer type.
llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(getVMContext());
return ABIArgInfo::getDirect(PtrTy);
} else if (SeltTy->isVectorType()) {
// 64- and 128-bit vectors are never returned in a
// register when inside a structure.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size == 64 || Size == 128)
return ABIArgInfo::getIndirect(0);
return classifyReturnType(QualType(SeltTy, 0));
}
}
// Small structures which are register sized are generally returned
// in a register.
if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) {
uint64_t Size = getContext().getTypeSize(RetTy);
// As a special-case, if the struct is a "single-element" struct, and
// the field is of type "float" or "double", return it in a
// floating-point register. We apply a similar transformation for
// pointer types to improve the quality of the generated IR.
if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))
if (SeltTy->isRealFloatingType() || SeltTy->hasPointerRepresentation())
return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
// FIXME: We should be able to narrow this integer in cases with dead
// padding.
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
}

Просмотреть файл

@ -173,7 +173,7 @@ struct s42 { enum e40 f0; } f42(void) { }
// CHECK: define i64 @f43()
struct s43 { enum e40 f0; int f1; } f43(void) { }
// CHECK: define i32 @f44()
// CHECK: define void ()* @f44()
struct s44 { vvbp f0; } f44(void) { }
// CHECK: define i64 @f45()
@ -281,6 +281,10 @@ void f56(char a0, struct s56_0 a1,
struct s57 { _Complex int x; };
void f57(struct s57 x) {} void f57a(void) { f57((struct s57){1}); }
// CHECK: define void @f58()
union u58 {};
void f58(union u58 x) {}
// CHECK: define void @f58()
// CHECK: define i64 @f59()
struct s59 { float x __attribute((aligned(8))); };
struct s59 f59() { while (1) {} }

Просмотреть файл

@ -84,7 +84,7 @@ struct s4_1 { float x; };
struct s4_2 : s4_0, s4_1 { };
s4_2 f4() { return s4_2(); }
// CHECK: define i32 @_Z2f5v()
// CHECK: define i32* @_Z2f5v()
struct s5 { s5(); int &x; };
s5 f5() { return s5(); }