diff options
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index c27e2cf42fe..fb3b931ce95 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -3544,8 +3544,9 @@ public: }; } -static bool isHomogeneousAggregate(QualType Ty, const Type *&Base, +static bool isARMHomogeneousAggregate(QualType Ty, const Type *&Base, ASTContext &Context, + bool isAArch64, uint64_t *HAMembers = nullptr); ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, @@ -3627,7 +3628,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, // Homogeneous Floating-point Aggregates (HFAs) need to be expanded. const Type *Base = nullptr; uint64_t Members = 0; - if (isHomogeneousAggregate(Ty, Base, getContext(), &Members)) { + if (isARMHomogeneousAggregate(Ty, Base, getContext(), true, &Members)) { IsHA = true; if (!IsNamedArg && isDarwinPCS()) { // With the Darwin ABI, variadic arguments are always passed on the stack @@ -3685,7 +3686,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); const Type *Base = nullptr; - if (isHomogeneousAggregate(RetTy, Base, getContext())) + if (isARMHomogeneousAggregate(RetTy, Base, getContext(), true)) // Homogeneous Floating-point Aggregates (HFAs) are returned directly. return ABIArgInfo::getDirect(); @@ -3822,7 +3823,7 @@ static llvm::Value *EmitAArch64VAArg(llvm::Value *VAListAddr, QualType Ty, const Type *Base = nullptr; uint64_t NumMembers; - bool IsHFA = isHomogeneousAggregate(Ty, Base, Ctx, &NumMembers); + bool IsHFA = isARMHomogeneousAggregate(Ty, Base, Ctx, true, &NumMembers); if (IsHFA && NumMembers > 1) { // Homogeneous aggregates passed in registers will have their elements split // and stored 16-bytes apart regardless of size (they're notionally in qN, @@ -3965,7 +3966,7 @@ llvm::Value *AArch64ABIInfo::EmitDarwinVAArg(llvm::Value *VAListAddr, QualType T uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8; const Type *Base = nullptr; - bool isHA = isHomogeneousAggregate(Ty, Base, getContext()); + bool isHA = isARMHomogeneousAggregate(Ty, Base, getContext(), true); bool isIndirect = false; // Arguments bigger than 16 bytes which aren't homogeneous aggregates should @@ -4251,15 +4252,16 @@ void ARMABIInfo::setRuntimeCC() { RuntimeCC = abiCC; } -/// isHomogeneousAggregate - Return true if a type is an AAPCS-VFP homogeneous +/// isARMHomogeneousAggregate - 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) { +static bool isARMHomogeneousAggregate(QualType Ty, const Type *&Base, + ASTContext &Context, bool isAArch64, + uint64_t *HAMembers) { uint64_t Members = 0; if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - if (!isHomogeneousAggregate(AT->getElementType(), Base, Context, &Members)) + if (!isARMHomogeneousAggregate(AT->getElementType(), Base, Context, isAArch64, &Members)) return false; Members *= AT->getSize().getZExtValue(); } else if (const RecordType *RT = Ty->getAs<RecordType>()) { @@ -4270,7 +4272,7 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base, Members = 0; for (const auto *FD : RD->fields()) { uint64_t FldMembers; - if (!isHomogeneousAggregate(FD->getType(), Base, Context, &FldMembers)) + if (!isARMHomogeneousAggregate(FD->getType(), Base, Context, isAArch64, &FldMembers)) return false; Members = (RD->isUnion() ? @@ -4284,12 +4286,22 @@ static bool isHomogeneousAggregate(QualType Ty, const Type *&Base, } // Homogeneous aggregates for AAPCS-VFP must have base types of float, - // double, or 64-bit or 128-bit vectors. + // double, or 64-bit or 128-bit vectors. "long double" has the same machine + // type as double, so it is also allowed as a base type. + // Homogeneous aggregates for AAPCS64 must have base types of a floating + // point type or a short-vector type. This is the same as the 32-bit ABI, + // but with the difference that any floating-point type is allowed, + // including __fp16. if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { - if (BT->getKind() != BuiltinType::Float && - BT->getKind() != BuiltinType::Double && - BT->getKind() != BuiltinType::LongDouble) - return false; + if (isAArch64) { + if (!BT->isFloatingPoint()) + return false; + } else { + if (BT->getKind() != BuiltinType::Float && + BT->getKind() != BuiltinType::Double && + BT->getKind() != BuiltinType::LongDouble) + return false; + } } else if (const VectorType *VT = Ty->getAs<VectorType>()) { unsigned VecSize = Context.getTypeSize(VT); if (VecSize != 64 && VecSize != 128) @@ -4491,7 +4503,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, // into VFP registers. const Type *Base = nullptr; uint64_t Members = 0; - if (isHomogeneousAggregate(Ty, Base, getContext(), &Members)) { + if (isARMHomogeneousAggregate(Ty, Base, getContext(), false, &Members)) { assert(Base && "Base class should be set for homogeneous aggregate"); // Base can be a floating-point or a vector. if (Base->isVectorType()) { @@ -4696,7 +4708,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, // Check for homogeneous aggregates with AAPCS-VFP. if (getABIKind() == AAPCS_VFP && !isVariadic) { const Type *Base = nullptr; - if (isHomogeneousAggregate(RetTy, Base, getContext())) { + if (isARMHomogeneousAggregate(RetTy, Base, getContext(), false)) { assert(Base && "Base class should be set for homogeneous aggregate"); // Homogeneous Aggregates are returned directly. return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP); |