summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp132
1 files changed, 94 insertions, 38 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 4455f1a..82ee4fc 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/contrib/llvm/tools/clang/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());
@@ -443,32 +464,55 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
llvm::Function::arg_iterator AI) {
assert(LV.isSimple() &&
"Unexpected non-simple lvalue during struct expansion.");
- llvm::Value *Addr = LV.getAddress();
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
unsigned NumElts = AT->getSize().getZExtValue();
QualType EltTy = AT->getElementType();
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
- llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
+ llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, Elt);
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 SubLV = EmitLValueForField(LV, LargestFD);
+ AI = ExpandTypeFromArgs(LargestFD->getType(), SubLV, 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 SubLV = EmitLValueForField(LV, FD);
+ AI = ExpandTypeFromArgs(FT, SubLV, AI);
+ }
}
} else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
QualType EltTy = CT->getElementType();
- llvm::Value *RealAddr = Builder.CreateStructGEP(Addr, 0, "real");
+ llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(RealAddr, EltTy));
- llvm::Value *ImagAddr = Builder.CreateStructGEP(Addr, 1, "imag");
+ llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(ImagAddr, EltTy));
} else {
EmitStoreThroughLValue(RValue::get(AI), LV);
@@ -1760,26 +1804,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);
+ LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
+
+ 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(LV, 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(LV, FD);
+ ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
+ }
}
} else if (Ty->isAnyComplexType()) {
ComplexPairTy CV = RV.getComplexVal();
OpenPOWER on IntegriCloud