|
@@ -5597,8 +5597,10 @@ public:
|
|
ABIKind getABIKind() const { return Kind; }
|
|
ABIKind getABIKind() const { return Kind; }
|
|
|
|
|
|
private:
|
|
private:
|
|
- ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const;
|
|
|
|
- ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic) const;
|
|
|
|
|
|
+ ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic,
|
|
|
|
+ unsigned functionCallConv) const;
|
|
|
|
+ ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic,
|
|
|
|
+ unsigned functionCallConv) const;
|
|
ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base,
|
|
ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base,
|
|
uint64_t Members) const;
|
|
uint64_t Members) const;
|
|
ABIArgInfo coerceIllegalVector(QualType Ty) const;
|
|
ABIArgInfo coerceIllegalVector(QualType Ty) const;
|
|
@@ -5608,6 +5610,8 @@ private:
|
|
bool isHomogeneousAggregateSmallEnough(const Type *Ty,
|
|
bool isHomogeneousAggregateSmallEnough(const Type *Ty,
|
|
uint64_t Members) const override;
|
|
uint64_t Members) const override;
|
|
|
|
|
|
|
|
+ bool isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const;
|
|
|
|
+
|
|
void computeInfo(CGFunctionInfo &FI) const override;
|
|
void computeInfo(CGFunctionInfo &FI) const override;
|
|
|
|
|
|
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
@@ -5728,11 +5732,13 @@ void WindowsARMTargetCodeGenInfo::setTargetAttributes(
|
|
|
|
|
|
void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
|
|
void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
|
|
if (!::classifyReturnType(getCXXABI(), FI, *this))
|
|
if (!::classifyReturnType(getCXXABI(), FI, *this))
|
|
- FI.getReturnInfo() =
|
|
|
|
- classifyReturnType(FI.getReturnType(), FI.isVariadic());
|
|
|
|
|
|
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic(),
|
|
|
|
+ FI.getCallingConvention());
|
|
|
|
|
|
for (auto &I : FI.arguments())
|
|
for (auto &I : FI.arguments())
|
|
- I.info = classifyArgumentType(I.type, FI.isVariadic());
|
|
|
|
|
|
+ I.info = classifyArgumentType(I.type, FI.isVariadic(),
|
|
|
|
+ FI.getCallingConvention());
|
|
|
|
+
|
|
|
|
|
|
// Always honor user-specified calling convention.
|
|
// Always honor user-specified calling convention.
|
|
if (FI.getCallingConvention() != llvm::CallingConv::C)
|
|
if (FI.getCallingConvention() != llvm::CallingConv::C)
|
|
@@ -5811,8 +5817,8 @@ ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty,
|
|
return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
|
|
return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
|
|
}
|
|
}
|
|
|
|
|
|
-ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
|
|
|
|
- bool isVariadic) const {
|
|
|
|
|
|
+ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
|
|
|
|
+ unsigned functionCallConv) const {
|
|
// 6.1.2.1 The following argument types are VFP CPRCs:
|
|
// 6.1.2.1 The following argument types are VFP CPRCs:
|
|
// A single-precision floating-point type (including promoted
|
|
// A single-precision floating-point type (including promoted
|
|
// half-precision types); A double-precision floating-point type;
|
|
// half-precision types); A double-precision floating-point type;
|
|
@@ -5820,7 +5826,9 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
|
|
// with a Base Type of a single- or double-precision floating-point type,
|
|
// with a Base Type of a single- or double-precision floating-point type,
|
|
// 64-bit containerized vectors or 128-bit containerized vectors with one
|
|
// 64-bit containerized vectors or 128-bit containerized vectors with one
|
|
// to four Elements.
|
|
// to four Elements.
|
|
- bool IsEffectivelyAAPCS_VFP = getABIKind() == AAPCS_VFP && !isVariadic;
|
|
|
|
|
|
+ // Variadic functions should always marshal to the base standard.
|
|
|
|
+ bool IsAAPCS_VFP =
|
|
|
|
+ !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ false);
|
|
|
|
|
|
Ty = useFirstFieldIfTransparentUnion(Ty);
|
|
Ty = useFirstFieldIfTransparentUnion(Ty);
|
|
|
|
|
|
@@ -5833,7 +5841,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
|
|
// half type natively, and does not need to interwork with AAPCS code.
|
|
// half type natively, and does not need to interwork with AAPCS code.
|
|
if ((Ty->isFloat16Type() || Ty->isHalfType()) &&
|
|
if ((Ty->isFloat16Type() || Ty->isHalfType()) &&
|
|
!getContext().getLangOpts().NativeHalfArgsAndReturns) {
|
|
!getContext().getLangOpts().NativeHalfArgsAndReturns) {
|
|
- llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
|
|
|
|
|
|
+ llvm::Type *ResType = IsAAPCS_VFP ?
|
|
llvm::Type::getFloatTy(getVMContext()) :
|
|
llvm::Type::getFloatTy(getVMContext()) :
|
|
llvm::Type::getInt32Ty(getVMContext());
|
|
llvm::Type::getInt32Ty(getVMContext());
|
|
return ABIArgInfo::getDirect(ResType);
|
|
return ABIArgInfo::getDirect(ResType);
|
|
@@ -5857,7 +5865,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
|
|
if (isEmptyRecord(getContext(), Ty, true))
|
|
if (isEmptyRecord(getContext(), Ty, true))
|
|
return ABIArgInfo::getIgnore();
|
|
return ABIArgInfo::getIgnore();
|
|
|
|
|
|
- if (IsEffectivelyAAPCS_VFP) {
|
|
|
|
|
|
+ if (IsAAPCS_VFP) {
|
|
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
|
|
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
|
|
// into VFP registers.
|
|
// into VFP registers.
|
|
const Type *Base = nullptr;
|
|
const Type *Base = nullptr;
|
|
@@ -6014,10 +6022,12 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
|
|
|
|
- bool isVariadic) const {
|
|
|
|
- bool IsEffectivelyAAPCS_VFP =
|
|
|
|
- (getABIKind() == AAPCS_VFP || getABIKind() == AAPCS16_VFP) && !isVariadic;
|
|
|
|
|
|
+ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic,
|
|
|
|
+ unsigned functionCallConv) const {
|
|
|
|
+
|
|
|
|
+ // Variadic functions should always marshal to the base standard.
|
|
|
|
+ bool IsAAPCS_VFP =
|
|
|
|
+ !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ true);
|
|
|
|
|
|
if (RetTy->isVoidType())
|
|
if (RetTy->isVoidType())
|
|
return ABIArgInfo::getIgnore();
|
|
return ABIArgInfo::getIgnore();
|
|
@@ -6038,7 +6048,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
|
|
// half type natively, and does not need to interwork with AAPCS code.
|
|
// half type natively, and does not need to interwork with AAPCS code.
|
|
if ((RetTy->isFloat16Type() || RetTy->isHalfType()) &&
|
|
if ((RetTy->isFloat16Type() || RetTy->isHalfType()) &&
|
|
!getContext().getLangOpts().NativeHalfArgsAndReturns) {
|
|
!getContext().getLangOpts().NativeHalfArgsAndReturns) {
|
|
- llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
|
|
|
|
|
|
+ llvm::Type *ResType = IsAAPCS_VFP ?
|
|
llvm::Type::getFloatTy(getVMContext()) :
|
|
llvm::Type::getFloatTy(getVMContext()) :
|
|
llvm::Type::getInt32Ty(getVMContext());
|
|
llvm::Type::getInt32Ty(getVMContext());
|
|
return ABIArgInfo::getDirect(ResType);
|
|
return ABIArgInfo::getDirect(ResType);
|
|
@@ -6087,7 +6097,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
|
|
return ABIArgInfo::getIgnore();
|
|
return ABIArgInfo::getIgnore();
|
|
|
|
|
|
// Check for homogeneous aggregates with AAPCS-VFP.
|
|
// Check for homogeneous aggregates with AAPCS-VFP.
|
|
- if (IsEffectivelyAAPCS_VFP) {
|
|
|
|
|
|
+ if (IsAAPCS_VFP) {
|
|
const Type *Base = nullptr;
|
|
const Type *Base = nullptr;
|
|
uint64_t Members = 0;
|
|
uint64_t Members = 0;
|
|
if (isHomogeneousAggregate(RetTy, Base, Members))
|
|
if (isHomogeneousAggregate(RetTy, Base, Members))
|
|
@@ -6192,6 +6202,16 @@ bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
|
|
return Members <= 4;
|
|
return Members <= 4;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool ARMABIInfo::isEffectivelyAAPCS_VFP(unsigned callConvention,
|
|
|
|
+ bool acceptHalf) const {
|
|
|
|
+ // Give precedence to user-specified calling conventions.
|
|
|
|
+ if (callConvention != llvm::CallingConv::C)
|
|
|
|
+ return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP);
|
|
|
|
+ else
|
|
|
|
+ return (getABIKind() == AAPCS_VFP) ||
|
|
|
|
+ (acceptHalf && (getABIKind() == AAPCS16_VFP));
|
|
|
|
+}
|
|
|
|
+
|
|
Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
Address ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
QualType Ty) const {
|
|
QualType Ty) const {
|
|
CharUnits SlotSize = CharUnits::fromQuantity(4);
|
|
CharUnits SlotSize = CharUnits::fromQuantity(4);
|