}
}
+ // 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;
}
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));
}
// 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()
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) {} }