diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 128 | ||||
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 74 |
2 files changed, 154 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."); diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f7bef11fe1..c07e048358 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -2379,6 +2379,73 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { } } +/// isHomogeneousAggregate - Return true if a type is an AAPCS-VFP homogeneous +/// aggregate. If HAMembers is non-null, the number of base elements +/// contained in the type is returned through it; this is used for the +/// recursive calls that check aggregate component types. +static bool isHomogeneousAggregate(QualType Ty, const Type *&Base, + ASTContext &Context, + uint64_t *HAMembers = 0) { + uint64_t Members; + 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()) + 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) { + const FieldDecl *FD = *i; + uint64_t FldMembers; + if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers)) + return false; + Members += FldMembers; + } + } else { + Members = 1; + if (const ComplexType *CT = Ty->getAs<ComplexType>()) { + Members = 2; + Ty = CT->getElementType(); + } + + // Homogeneous aggregates for AAPCS-VFP must have base types of float, + // double, or 64-bit or 128-bit vectors. + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { + if (BT->getKind() != BuiltinType::Float && + BT->getKind() != BuiltinType::Double) + return false; + } else if (const VectorType *VT = Ty->getAs<VectorType>()) { + unsigned VecSize = Context.getTypeSize(VT); + if (VecSize != 64 && VecSize != 128) + return false; + } else { + return false; + } + + // The base type must be the same for all members. Vector types of the + // same total size are treated as being equivalent here. + const Type *TyPtr = Ty.getTypePtr(); + if (!Base) + Base = TyPtr; + if (Base != TyPtr && + (!Base->isVectorType() || !TyPtr->isVectorType() || + Context.getTypeSize(Base) != Context.getTypeSize(TyPtr))) + return false; + } + + // Homogeneous Aggregates can have at most 4 members of the base type. + if (HAMembers) + *HAMembers = Members; + return (Members <= 4); +} + ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const { if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. @@ -2398,6 +2465,13 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const { if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) return ABIArgInfo::getIndirect(0, /*ByVal=*/false); + if (getABIKind() == ARMABIInfo::AAPCS_VFP) { + // Homogeneous Aggregates need to be expanded. + const Type *Base = 0; + if (isHomogeneousAggregate(Ty, Base, getContext())) + return ABIArgInfo::getExpand(); + } + // Otherwise, pass by coercing to a structure of the appropriate size. // // FIXME: This is kind of nasty... but there isn't much choice because the ARM |