diff options
| author | Akira Hatanaka <ahatanaka@mips.com> | 2012-01-04 03:34:42 +0000 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-01-04 03:34:42 +0000 |
| commit | f093f5be3e900bfb85070959be6b65f2f660d7d8 (patch) | |
| tree | e2fdd04ca03e91e776ec33b8043e24ee5ac31bce /clang/lib/CodeGen | |
| parent | 3b775b8cc34365fdf9ace8ab45dd0539ddf0771d (diff) | |
| download | bcm5719-llvm-f093f5be3e900bfb85070959be6b65f2f660d7d8.tar.gz bcm5719-llvm-f093f5be3e900bfb85070959be6b65f2f660d7d8.zip | |
Have functions return structures smaller than 128-bit in registers if ABI
is either N32 or N64.
llvm-svn: 147520
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 30dcaad591f..0ce5957246d 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/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<llvm::Type*, 2> 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<BuiltinType>(); + + 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<PackedAttr>()); + + 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); } |

