forked from OSchip/llvm-project
Fix bugs in function MipsABIInfo::returnAggregateInRegs. Functions returning
class objects follow the same rules as those returning struct objects. llvm-svn: 150196
This commit is contained in:
parent
acdde195fb
commit
b6f7443c3c
|
@ -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;
|
||||
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
|
||||
unsigned FieldCnt = Layout.getFieldCount();
|
||||
|
||||
for (i = b; (i != e) && (std::distance(b, i) < 2); ++i) {
|
||||
const BuiltinType *BT = (*i)->getType()->getAs<BuiltinType>();
|
||||
// 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 (b == e)
|
||||
return llvm::StructType::get(getVMContext(), RTList,
|
||||
RD->hasAttr<PackedAttr>());
|
||||
|
||||
RTList.clear();
|
||||
}
|
||||
|
||||
if (i == e)
|
||||
return llvm::StructType::get(getVMContext(), RTList,
|
||||
RD->hasAttr<PackedAttr>());
|
||||
|
||||
RTList.clear();
|
||||
}
|
||||
|
||||
RTList.push_back(llvm::IntegerType::get(getVMContext(),
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// RUN: %clang -target mips64el-unknown-linux -ccc-clang-archs mips64el -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s
|
||||
|
||||
class B0 {
|
||||
double d;
|
||||
};
|
||||
|
||||
class D0 : public B0 {
|
||||
float f;
|
||||
};
|
||||
|
||||
class B1 {
|
||||
};
|
||||
|
||||
class D1 : public B1 {
|
||||
double d;
|
||||
float f;
|
||||
};
|
||||
|
||||
extern D0 gd0;
|
||||
extern D1 gd1;
|
||||
|
||||
// CHECK: define { i64, i64 } @_Z4foo1v()
|
||||
D0 foo1(void) {
|
||||
return gd0;
|
||||
}
|
||||
|
||||
// CHECK: define { double, float } @_Z4foo2v()
|
||||
D1 foo2(void) {
|
||||
return gd1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue