From c7ecc2e3691e484cffcfec7fcefef18b2bd23e5f Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 4 Jan 2012 03:34:42 +0000 Subject: [PATCH] Have functions return structures smaller than 128-bit in registers if ABI is either N32 or N64. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147520 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/TargetInfo.cpp | 57 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 30dcaad591..0ce5957246 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -3041,6 +3041,7 @@ class MipsABIInfo : public ABIInfo { bool IsO32; unsigned MinABIStackAlignInBytes; llvm::Type* HandleStructTy(QualType Ty) const; + llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const; public: MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) : ABIInfo(CGT), IsO32(_IsO32), MinABIStackAlignInBytes(IsO32 ? 4 : 8) {} @@ -3157,14 +3158,64 @@ ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty) const { ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } +llvm::Type* +MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { + const RecordType *RT = RetTy->getAsStructureType(); + SmallVector RTList; + + if (RT) { + const RecordDecl *RD = RT->getDecl(); + RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end(), i; + + for (i = b; (i != e) && (std::distance(b, i) < 2); ++i) { + const BuiltinType *BT = (*i)->getType()->getAs(); + + if (!BT || !BT->isFloatingPoint()) + break; + + switch (BT->getKind()) { + case BuiltinType::Float: + RTList.push_back(llvm::Type::getFloatTy(getVMContext())); + break; + case BuiltinType::Double: + RTList.push_back(llvm::Type::getDoubleTy(getVMContext())); + break; + case BuiltinType::LongDouble: + RTList.push_back(llvm::Type::getFP128Ty(getVMContext())); + break; + default: + assert(false && "Unexpexted floating point type."); + } + } + + if (i == e) + return llvm::StructType::get(getVMContext(), RTList, + RD->hasAttr()); + + RTList.clear(); + } + + RTList.push_back(llvm::IntegerType::get(getVMContext(), + std::min(Size, (uint64_t)64))); + if (Size > 64) + RTList.push_back(llvm::IntegerType::get(getVMContext(), Size - 64)); + + return llvm::StructType::get(getVMContext(), RTList); +} + ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy)) { - if ((IsO32 && RetTy->isAnyComplexType()) || - (!IsO32 && (getContext().getTypeSize(RetTy) <= 128))) - return ABIArgInfo::getDirect(); + uint64_t Size = getContext().getTypeSize(RetTy); + if (Size <= 128) { + if (RetTy->isAnyComplexType()) + return ABIArgInfo::getDirect(); + + if (!IsO32) + return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); + } return ABIArgInfo::getIndirect(0); } -- 2.40.0