зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
87adb0bf93
Коммит
bd4d3bcd2c
|
@ -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(); }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче