diff options
author | Bob Wilson <bob.wilson@apple.com> | 2011-08-03 05:58:22 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@apple.com> | 2011-08-03 05:58:22 +0000 |
commit | 194f06a476d299a7a70e5ff1d152f5895dc0a76c (patch) | |
tree | 2e30d8cdcd5fca7ffb191b53b96dd5f62cf77064 /lib/CodeGen/CGCall.cpp | |
parent | eb3058a114edd3a3bff1011554aafc95b529a975 (diff) |
Handle "homogeneous aggregates" as required by the ARM AAPCS-VFP ABI.
A homogeneous aggregate is an aggregate data structure where after flattening
any nesting there are 1 to 4 elements of the same base type that is either a
float, double, or Neon vector. All Neon vectors of the same size, either 64
or 128 bits, are treated as equivalent for this purpose. When using the
AAPCS-VFP ABI, check for homogeneous aggregates and pass them as arguments by
expanding them into a sequence of their base types. This requires extending
the existing support for expanded arguments to handle not only structs, but
also constant arrays and complex types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136767 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 128 |
1 files changed, 80 insertions, 48 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 3e5b431c2e..023dd2267c 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -313,49 +313,64 @@ CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention, void CodeGenTypes::GetExpandedTypes(QualType type, SmallVectorImpl<llvm::Type*> &expandedTypes) { - const RecordType *RT = type->getAsStructureType(); - assert(RT && "Can only expand structure types."); - 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(); + if (const ConstantArrayType *AT = Context.getAsConstantArrayType(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()) { + 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."); - - QualType fieldType = FD->getType(); - if (fieldType->isRecordType()) - GetExpandedTypes(fieldType, expandedTypes); - else - expandedTypes.push_back(ConvertType(fieldType)); - } + 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()); + expandedTypes.push_back(EltTy); + expandedTypes.push_back(EltTy); + } else + expandedTypes.push_back(ConvertType(type)); } llvm::Function::arg_iterator CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, llvm::Function::arg_iterator AI) { - const RecordType *RT = Ty->getAsStructureType(); - assert(RT && "Can only expand structure types."); - - RecordDecl *RD = RT->getDecl(); assert(LV.isSimple() && "Unexpected non-simple lvalue during struct expansion."); llvm::Value *Addr = LV.getAddress(); - for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + + 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); + LValue LV = MakeAddrLValue(EltAddr, EltTy); + AI = ExpandTypeFromArgs(EltTy, LV, AI); + } + } else if (const RecordType *RT = Ty->getAsStructureType()) { + 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(); + FieldDecl *FD = *i; + QualType FT = FD->getType(); - // FIXME: What are the right qualifiers here? - LValue LV = EmitLValueForField(Addr, FD, 0); - if (CodeGenFunction::hasAggregateLLVMType(FT)) { + // FIXME: What are the right qualifiers here? + LValue LV = EmitLValueForField(Addr, FD, 0); AI = ExpandTypeFromArgs(FT, LV, AI); - } else { - EmitStoreThroughLValue(RValue::get(AI), LV); - ++AI; } + } else if (const ComplexType *CT = Ty->getAs<ComplexType>()) { + QualType EltTy = CT->getElementType(); + llvm::Value *RealAddr = Builder.CreateStructGEP(Addr, 0, "real"); + EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(RealAddr, EltTy)); + llvm::Value *ImagAddr = Builder.CreateStructGEP(Addr, 0, "imag"); + EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(ImagAddr, EltTy)); + } else { + EmitStoreThroughLValue(RValue::get(AI), LV); + ++AI; } return AI; @@ -1462,26 +1477,43 @@ static void checkArgMatches(llvm::Value *Elt, unsigned &ArgNo, void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, SmallVector<llvm::Value*,16> &Args, llvm::FunctionType *IRFuncTy) { - const RecordType *RT = Ty->getAsStructureType(); - assert(RT && "Can only expand structure types."); - - 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); - if (CodeGenFunction::hasAggregateLLVMType(FT)) { - ExpandTypeToArgs(FT, RValue::getAggregate(LV.getAddress()), - Args, IRFuncTy); - continue; + if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { + unsigned NumElts = AT->getSize().getZExtValue(); + QualType EltTy = AT->getElementType(); + llvm::Value *Addr = RV.getAggregateAddr(); + for (unsigned Elt = 0; Elt < NumElts; ++Elt) { + llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt); + LValue LV = MakeAddrLValue(EltAddr, EltTy); + RValue EltRV; + if (CodeGenFunction::hasAggregateLLVMType(EltTy)) + EltRV = RValue::getAggregate(LV.getAddress()); + else + EltRV = EmitLoadOfLValue(LV); + ExpandTypeToArgs(EltTy, EltRV, Args, IRFuncTy); } + } else if (const RecordType *RT = Ty->getAsStructureType()) { + 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(); - RValue RV = EmitLoadOfLValue(LV); + // FIXME: What are the right qualifiers here? + LValue LV = EmitLValueForField(Addr, FD, 0); + RValue FldRV; + if (CodeGenFunction::hasAggregateLLVMType(FT)) + FldRV = RValue::getAggregate(LV.getAddress()); + else + FldRV = EmitLoadOfLValue(LV); + ExpandTypeToArgs(FT, FldRV, Args, IRFuncTy); + } + } else if (isa<ComplexType>(Ty)) { + ComplexPairTy CV = RV.getComplexVal(); + Args.push_back(CV.first); + Args.push_back(CV.second); + } else { assert(RV.isScalar() && "Unexpected non-scalar rvalue during struct expansion."); |