aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2012-02-09 18:49:26 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2012-02-09 18:49:26 +0000
commitda54ff306270e179f64d046369419724356d30d7 (patch)
treec3c4b16709934c7398ae67b15494283ec416c1d1 /lib/CodeGen/TargetInfo.cpp
parenta0c2b21e0d84ad289781e08e14148da6b8b8b76d (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.cpp41
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(),