bool IndirectRealign : 1; // isIndirect()
bool SRetAfterThis : 1; // isIndirect()
bool InReg : 1; // isDirect() || isExtend() || isIndirect()
+ bool CanBeFlattened: 1; // isDirect()
ABIArgInfo(Kind K)
: PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
TheKind(Direct), PaddingInReg(false), InReg(false) {}
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
- llvm::Type *Padding = nullptr) {
+ llvm::Type *Padding = nullptr,
+ bool CanBeFlattened = true) {
auto AI = ABIArgInfo(Direct);
AI.setCoerceToType(T);
AI.setDirectOffset(Offset);
AI.setPaddingType(Padding);
+ AI.setCanBeFlattened(CanBeFlattened);
return AI;
}
static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
InAllocaSRet = SRet;
}
+ bool getCanBeFlattened() const {
+ assert(isDirect() && "Invalid kind!");
+ return CanBeFlattened;
+ }
+
+ void setCanBeFlattened(bool Flatten) {
+ assert(isDirect() && "Invalid kind!");
+ CanBeFlattened = Flatten;
+ }
+
void dump() const;
};
return CC_C;
}
-static bool isAAPCSVFP(const CGFunctionInfo &FI, const TargetInfo &Target) {
- switch (FI.getEffectiveCallingConvention()) {
- case llvm::CallingConv::C:
- switch (Target.getTriple().getEnvironment()) {
- case llvm::Triple::EABIHF:
- case llvm::Triple::GNUEABIHF:
- return true;
- default:
- return false;
- }
- case llvm::CallingConv::ARM_AAPCS_VFP:
- return true;
- default:
- return false;
- }
-}
-
/// Arrange the argument and result information for a call to an
/// unknown C++ non-static member function of the given abstract type.
/// (Zero value of RD means we don't have any meaningful "this" argument type,
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
- // If the coerce-to type is a first class aggregate, flatten it. Either
- // way is semantically identical, but fast-isel and the optimizer
- // generally likes scalar values better than FCAs.
- // We cannot do this for functions using the AAPCS calling convention,
- // as structures are treated differently by that calling convention.
+ // Fast-isel and the optimizer generally like scalar values better than
+ // FCAs, so we flatten them if this is safe to do for this argument.
llvm::Type *argType = argAI.getCoerceToType();
llvm::StructType *st = dyn_cast<llvm::StructType>(argType);
- if (st && !isAAPCSVFP(FI, getTarget())) {
+ if (st && argAI.isDirect() && argAI.getCanBeFlattened()) {
for (unsigned i = 0, e = st->getNumElements(); i != e; ++i)
argTypes.push_back(st->getElementType(i));
} else {
case ABIArgInfo::Direct: {
// FIXME: handle sseregparm someday...
llvm::StructType *STy = dyn_cast<llvm::StructType>(AI.getCoerceToType());
- if (!isAAPCSVFP(FI, CGM.getTarget()) && STy) {
+ if (AI.isDirect() && AI.getCanBeFlattened() && STy) {
IRArgs.NumberOfArgs = STy->getNumElements();
} else {
IRArgs.NumberOfArgs = 1;
llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
}
- // If the coerce-to type is a first class aggregate, we flatten it and
- // pass the elements. Either way is semantically identical, but fast-isel
- // and the optimizer generally likes scalar values better than FCAs.
- // We cannot do this for functions using the AAPCS calling convention,
- // as structures are treated differently by that calling convention.
+ // Fast-isel and the optimizer generally like scalar values better than
+ // FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
- if (!isAAPCSVFP(FI, getTarget()) && STy && STy->getNumElements() > 1) {
+ if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy &&
+ STy->getNumElements() > 1) {
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(STy);
llvm::Type *DstTy =
cast<llvm::PointerType>(Ptr->getType())->getElementType();
}
- // If the coerce-to type is a first class aggregate, we flatten it and
- // pass the elements. Either way is semantically identical, but fast-isel
- // and the optimizer generally likes scalar values better than FCAs.
- // We cannot do this for functions using the AAPCS calling convention,
- // as structures are treated differently by that calling convention.
+ // Fast-isel and the optimizer generally like scalar values better than
+ // FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
- if (STy && !isAAPCSVFP(CallInfo, getTarget())) {
+ if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
llvm::Type *SrcTy =
cast<llvm::PointerType>(SrcPtr->getType())->getElementType();
uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
// unallocated are marked as unavailable.
resetAllocatedRegs();
+ const bool isAAPCS_VFP =
+ getABIKind() == ARMABIInfo::AAPCS_VFP && !FI.isVariadic();
+
if (getCXXABI().classifyReturnType(FI)) {
if (FI.getReturnInfo().isIndirect())
markAllocatedGPRs(1, 1);
llvm::Type::getInt32Ty(getVMContext()), NumGPRs - PreAllocationGPRs);
if (I.info.canHaveCoerceToType()) {
I.info = ABIArgInfo::getDirect(I.info.getCoerceToType() /* type */, 0 /* offset */,
- PaddingTy);
+ PaddingTy, !isAAPCS_VFP);
} else {
I.info = ABIArgInfo::getDirect(nullptr /* type */, 0 /* offset */,
- PaddingTy);
+ PaddingTy, !isAAPCS_VFP);
}
}
}
// 64-bit containerized vectors or 128-bit containerized vectors with one
// to four Elements.
+ const bool isAAPCS_VFP =
+ getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic;
+
// Handle illegal vector types here.
if (isIllegalVectorType(Ty)) {
uint64_t Size = getContext().getTypeSize(Ty);
llvm::Type *ResType =
llvm::Type::getInt32Ty(getVMContext());
markAllocatedGPRs(1, 1);
- return ABIArgInfo::getDirect(ResType);
+ return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
}
if (Size == 64) {
llvm::Type *ResType = llvm::VectorType::get(
markAllocatedVFPs(2, 2);
IsCPRC = true;
}
- return ABIArgInfo::getDirect(ResType);
+ return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
}
if (Size == 128) {
llvm::Type *ResType = llvm::VectorType::get(
markAllocatedVFPs(4, 4);
IsCPRC = true;
}
- return ABIArgInfo::getDirect(ResType);
+ return ABIArgInfo::getDirect(ResType, 0, nullptr, !isAAPCS_VFP);
}
markAllocatedGPRs(1, 1);
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
unsigned Size = getContext().getTypeSize(Ty);
if (!IsCPRC)
markAllocatedGPRs(Size > 32 ? 2 : 1, (Size + 31) / 32);
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (Ty->isPromotableIntegerType()
+ ? ABIArgInfo::getExtend()
+ : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP));
}
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
- if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) {
+ if (isAAPCS_VFP) {
// Homogeneous Aggregates need to be expanded when we can fit the aggregate
// into VFP registers.
const Type *Base = nullptr;
markAllocatedVFPs(2, Members * 2);
}
IsCPRC = true;
- return ABIArgInfo::getDirect();
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP);
}
}
llvm::Type *STy =
llvm::StructType::get(llvm::ArrayType::get(ElemTy, SizeRegs), NULL);
- return ABIArgInfo::getDirect(STy);
+ return ABIArgInfo::getDirect(STy, 0, nullptr, !isAAPCS_VFP);
}
static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
bool isVariadic) const {
+ const bool isAAPCS_VFP =
+ getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic;
+
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ return (RetTy->isPromotableIntegerType()
+ ? ABIArgInfo::getExtend()
+ : ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP));
}
// Are we following APCS?
// FIXME: Consider using 2 x vector types if the back end handles them
// correctly.
if (RetTy->isAnyComplexType())
- return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
- getContext().getTypeSize(RetTy)));
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(
+ getVMContext(), getContext().getTypeSize(RetTy)));
// Integer like structures are returned in r0.
if (isIntegerLikeType(RetTy, getContext(), getVMContext())) {
if (isHomogeneousAggregate(RetTy, Base, getContext())) {
assert(Base && "Base class should be set for homogeneous aggregate");
// Homogeneous Aggregates are returned directly.
- return ABIArgInfo::getDirect();
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, !isAAPCS_VFP);
}
}
if (Size <= 32) {
if (getDataLayout().isBigEndian())
// Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
- return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0,
+ nullptr, !isAAPCS_VFP);
// Return in the smallest viable integer type.
if (Size <= 8)
- return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()), 0,
+ nullptr, !isAAPCS_VFP);
if (Size <= 16)
- return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
- return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()), 0,
+ nullptr, !isAAPCS_VFP);
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()), 0,
+ nullptr, !isAAPCS_VFP);
}
markAllocatedGPRs(1, 1);