diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-11-18 01:25:50 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-11-18 01:25:50 +0000 |
commit | bd4d3bcd2cd64d1bba29b2a52705b97d68ebccd5 (patch) | |
tree | b52152f814ae08ec26d62cbdb24b73255c86bb52 /lib/CodeGen/TargetInfo.cpp | |
parent | 87adb0bf9375390de4c66d9e2ad110cc492cd655 (diff) |
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
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 57 |
1 files changed, 16 insertions, 41 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index b23ae304a8..7ad351050d 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -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)); } |