summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2012-04-13 11:22:00 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2012-04-13 11:22:00 +0000
commiteaf856db5d1a272dc7188937206ef4572836f82a (patch)
treeea360d29807f197c529a7105dad5ece443fca2ae
parent51b92401c9f95023a2ef27064fd5a60fd99175f5 (diff)
Step forward with supporting of ARM homogenous aggregates:
- Handle unions - Handle C++ classes git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154664 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGCall.cpp123
-rw-r--r--lib/CodeGen/CGExpr.cpp13
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
-rw-r--r--lib/CodeGen/TargetInfo.cpp24
4 files changed, 119 insertions, 43 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 4455f1a086..90b6bee2f7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -419,16 +419,37 @@ void CodeGenTypes::GetExpandedTypes(QualType type,
uint64_t NumElts = AT->getSize().getZExtValue();
for (uint64_t Elt = 0; Elt < NumElts; ++Elt)
GetExpandedTypes(AT->getElementType(), expandedTypes);
- } else if (const RecordType *RT = type->getAsStructureType()) {
+ } else if (const RecordType *RT = type->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
assert(!RD->hasFlexibleArrayMember() &&
"Cannot expand structure with flexible array.");
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- const FieldDecl *FD = *i;
- assert(!FD->isBitField() &&
- "Cannot expand structure with bit-field members.");
- GetExpandedTypes(FD->getType(), expandedTypes);
+ if (RD->isUnion()) {
+ // Unions can be here only in degenerative cases - all the fields are same
+ // after flattening. Thus we have to use the "largest" field.
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD)
+ GetExpandedTypes(LargestFD->getType(), expandedTypes);
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ GetExpandedTypes(FD->getType(), expandedTypes);
+ }
}
} else if (const ComplexType *CT = type->getAs<ComplexType>()) {
llvm::Type *EltTy = ConvertType(CT->getElementType());
@@ -453,16 +474,40 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
LValue LV = MakeAddrLValue(EltAddr, EltTy);
AI = ExpandTypeFromArgs(EltTy, LV, AI);
}
- } else if (const RecordType *RT = Ty->getAsStructureType()) {
+ } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- FieldDecl *FD = *i;
- QualType FT = FD->getType();
-
- // FIXME: What are the right qualifiers here?
- LValue LV = EmitLValueForField(Addr, FD, 0);
- AI = ExpandTypeFromArgs(FT, LV, AI);
+ if (RD->isUnion()) {
+ // Unions can be here only in degenerative cases - all the fields are same
+ // after flattening. Thus we have to use the "largest" field.
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD) {
+ // FIXME: What are the right qualifiers here?
+ LValue LV = EmitLValueForField(Addr, LargestFD, 0);
+ AI = ExpandTypeFromArgs(LargestFD->getType(), LV, AI);
+ }
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+ QualType FT = FD->getType();
+
+ // FIXME: What are the right qualifiers here?
+ LValue LV = EmitLValueForField(Addr, FD, 0);
+ AI = ExpandTypeFromArgs(FT, LV, AI);
+ }
}
} else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
QualType EltTy = CT->getElementType();
@@ -1760,26 +1805,38 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
EltRV = EmitLoadOfLValue(LV);
ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy);
}
- } else if (const RecordType *RT = Ty->getAsStructureType()) {
+ } else if (const RecordType *RT = Ty->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
llvm::Value *Addr = RV.getAggregateAddr();
- for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- i != e; ++i) {
- FieldDecl *FD = *i;
- QualType FT = FD->getType();
-
- // FIXME: What are the right qualifiers here?
- LValue LV = EmitLValueForField(Addr, FD, 0);
- RValue FldRV;
- if (FT->isAnyComplexType())
- // FIXME: Volatile?
- FldRV = RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
- else if (CodeGenFunction::hasAggregateLLVMType(FT))
- FldRV = LV.asAggregateRValue();
- else
- FldRV = EmitLoadOfLValue(LV);
- ExpandTypeToArgs(FT, FldRV, Args, IRFuncTy);
+
+ if (RD->isUnion()) {
+ const FieldDecl *LargestFD = 0;
+ CharUnits UnionSize = CharUnits::Zero();
+
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ const FieldDecl *FD = *i;
+ assert(!FD->isBitField() &&
+ "Cannot expand structure with bit-field members.");
+ CharUnits FieldSize = getContext().getTypeSizeInChars(FD->getType());
+ if (UnionSize < FieldSize) {
+ UnionSize = FieldSize;
+ LargestFD = FD;
+ }
+ }
+ if (LargestFD) {
+ RValue FldRV = EmitRValueForField(Addr, LargestFD);
+ ExpandTypeToArgs(LargestFD->getType(), FldRV, Args, IRFuncTy);
+ }
+ } else {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
+ FieldDecl *FD = *i;
+
+ RValue FldRV = EmitRValueForField(Addr, FD);
+ ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
+ }
}
} else if (Ty->isAnyComplexType()) {
ComplexPairTy CV = RV.getComplexVal();
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 08970fd738..a7f5c47bbc 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -2378,6 +2378,19 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
+RValue CodeGenFunction::EmitRValueForField(llvm::Value *Addr,
+ const FieldDecl *FD) {
+ QualType FT = FD->getType();
+ // FIXME: What are the right qualifiers here?
+ LValue LV = EmitLValueForField(Addr, FD, 0);
+ if (FT->isAnyComplexType())
+ // FIXME: Volatile?
+ return RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
+ else if (CodeGenFunction::hasAggregateLLVMType(FT))
+ return LV.asAggregateRValue();
+
+ return EmitLoadOfLValue(LV);
+}
//===--------------------------------------------------------------------===//
// Expression Emission
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 3e0cd14625..f57dd5f587 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2104,6 +2104,8 @@ public:
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
+ RValue EmitRValueForField(llvm::Value *Addr, const FieldDecl *FD);
+
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
ConstantEmission(llvm::Constant *C, bool isReference)
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 3ed1778cc9..2b71fdd504 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -2527,19 +2527,16 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
ASTContext &Context,
uint64_t *HAMembers = 0) {
- uint64_t Members;
+ uint64_t Members = 0;
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
if (!isHomogeneousAggregate(AT->getElementType(), Base, Context, &Members))
return false;
Members *= AT->getSize().getZExtValue();
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
- if (RD->isUnion() || RD->hasFlexibleArrayMember())
+ if (RD->hasFlexibleArrayMember())
return false;
- if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CXXRD->isAggregate())
- return false;
- }
+
Members = 0;
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i) {
@@ -2547,7 +2544,9 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t FldMembers;
if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers))
return false;
- Members += FldMembers;
+
+ Members = (RD->isUnion() ?
+ std::max(Members, FldMembers) : Members + FldMembers);
}
} else {
Members = 1;
@@ -2584,7 +2583,8 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
// Homogeneous Aggregates can have at most 4 members of the base type.
if (HAMembers)
*HAMembers = Members;
- return (Members <= 4);
+
+ return (Members > 0 && Members <= 4);
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
@@ -2609,8 +2609,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
// Homogeneous Aggregates need to be expanded.
const Type *Base = 0;
- if (isHomogeneousAggregate(Ty, Base, getContext()))
+ if (isHomogeneousAggregate(Ty, Base, getContext())) {
+ assert(Base && "Base class should be set for homogeneous aggregate");
return ABIArgInfo::getExpand();
+ }
}
// Otherwise, pass by coercing to a structure of the appropriate size.
@@ -2776,9 +2778,11 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
// Check for homogeneous aggregates with AAPCS-VFP.
if (getABIKind() == AAPCS_VFP) {
const Type *Base = 0;
- if (isHomogeneousAggregate(RetTy, Base, getContext()))
+ if (isHomogeneousAggregate(RetTy, Base, getContext())) {
+ assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
return ABIArgInfo::getDirect();
+ }
}
// Aggregates <= 4 bytes are returned in r0; other aggregates