diff options
author | Akira Hatanaka <ahatanaka@mips.com> | 2012-02-09 18:49:26 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-02-09 18:49:26 +0000 |
commit | da54ff306270e179f64d046369419724356d30d7 (patch) | |
tree | c3c4b16709934c7398ae67b15494283ec416c1d1 /lib/CodeGen/TargetInfo.cpp | |
parent | a0c2b21e0d84ad289781e08e14148da6b8b8b76d (diff) |
Fix bugs in function MipsABIInfo::returnAggregateInRegs. Functions returning
class objects follow the same rules as those returning struct objects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150196 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 97b49a0c6b..b48bff8a1e 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -3173,27 +3173,40 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { llvm::Type* MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { - const RecordType *RT = RetTy->getAsStructureType(); + const RecordType *RT = RetTy->getAs<RecordType>(); SmallVector<llvm::Type*, 2> RTList; - if (RT) { + if (RT && RT->isStructureOrClassType()) { 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>(); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + unsigned FieldCnt = Layout.getFieldCount(); + + // N32/64 returns struct/classes in floating point registers if the + // following conditions are met: + // 1. The size of the struct/class is no larger than 128-bit. + // 2. The struct/class has one or two fields all of which are floating + // point types. + // 3. The offset of the first field is zero (this follows what gcc does). + // + // Any other composite results are returned in integer registers. + // + if (FieldCnt && (FieldCnt <= 2) && !Layout.getFieldOffset(0)) { + RecordDecl::field_iterator b = RD->field_begin(), e = RD->field_end(); + for (; b != e; ++b) { + const BuiltinType *BT = (*b)->getType()->getAs<BuiltinType>(); - if (!BT || !BT->isFloatingPoint()) - break; + if (!BT || !BT->isFloatingPoint()) + break; - RTList.push_back(CGT.ConvertType((*i)->getType())); - } + RTList.push_back(CGT.ConvertType((*b)->getType())); + } - if (i == e) - return llvm::StructType::get(getVMContext(), RTList, - RD->hasAttr<PackedAttr>()); + if (b == e) + return llvm::StructType::get(getVMContext(), RTList, + RD->hasAttr<PackedAttr>()); - RTList.clear(); + RTList.clear(); + } } RTList.push_back(llvm::IntegerType::get(getVMContext(), |