106c3fb27SDimitry Andric //===- AArch64.cpp --------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric
906c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1006c3fb27SDimitry Andric #include "TargetInfo.h"
110fca6ea1SDimitry Andric #include "clang/AST/Decl.h"
120fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticFrontend.h"
130fca6ea1SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h"
1406c3fb27SDimitry Andric
1506c3fb27SDimitry Andric using namespace clang;
1606c3fb27SDimitry Andric using namespace clang::CodeGen;
1706c3fb27SDimitry Andric
1806c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1906c3fb27SDimitry Andric // AArch64 ABI Implementation
2006c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
2106c3fb27SDimitry Andric
2206c3fb27SDimitry Andric namespace {
2306c3fb27SDimitry Andric
2406c3fb27SDimitry Andric class AArch64ABIInfo : public ABIInfo {
2506c3fb27SDimitry Andric AArch64ABIKind Kind;
2606c3fb27SDimitry Andric
2706c3fb27SDimitry Andric public:
AArch64ABIInfo(CodeGenTypes & CGT,AArch64ABIKind Kind)2806c3fb27SDimitry Andric AArch64ABIInfo(CodeGenTypes &CGT, AArch64ABIKind Kind)
2906c3fb27SDimitry Andric : ABIInfo(CGT), Kind(Kind) {}
3006c3fb27SDimitry Andric
isSoftFloat() const310fca6ea1SDimitry Andric bool isSoftFloat() const { return Kind == AArch64ABIKind::AAPCSSoft; }
320fca6ea1SDimitry Andric
3306c3fb27SDimitry Andric private:
getABIKind() const3406c3fb27SDimitry Andric AArch64ABIKind getABIKind() const { return Kind; }
isDarwinPCS() const3506c3fb27SDimitry Andric bool isDarwinPCS() const { return Kind == AArch64ABIKind::DarwinPCS; }
3606c3fb27SDimitry Andric
3706c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const;
3806c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType RetTy, bool IsVariadic,
3906c3fb27SDimitry Andric unsigned CallingConvention) const;
4006c3fb27SDimitry Andric ABIArgInfo coerceIllegalVector(QualType Ty) const;
4106c3fb27SDimitry Andric bool isHomogeneousAggregateBaseType(QualType Ty) const override;
4206c3fb27SDimitry Andric bool isHomogeneousAggregateSmallEnough(const Type *Ty,
4306c3fb27SDimitry Andric uint64_t Members) const override;
4406c3fb27SDimitry Andric bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override;
4506c3fb27SDimitry Andric
4606c3fb27SDimitry Andric bool isIllegalVectorType(QualType Ty) const;
4706c3fb27SDimitry Andric
computeInfo(CGFunctionInfo & FI) const4806c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override {
4906c3fb27SDimitry Andric if (!::classifyReturnType(getCXXABI(), FI, *this))
5006c3fb27SDimitry Andric FI.getReturnInfo() =
5106c3fb27SDimitry Andric classifyReturnType(FI.getReturnType(), FI.isVariadic());
5206c3fb27SDimitry Andric
5306c3fb27SDimitry Andric for (auto &it : FI.arguments())
5406c3fb27SDimitry Andric it.info = classifyArgumentType(it.type, FI.isVariadic(),
5506c3fb27SDimitry Andric FI.getCallingConvention());
5606c3fb27SDimitry Andric }
5706c3fb27SDimitry Andric
580fca6ea1SDimitry Andric RValue EmitDarwinVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
590fca6ea1SDimitry Andric AggValueSlot Slot) const;
6006c3fb27SDimitry Andric
610fca6ea1SDimitry Andric RValue EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
620fca6ea1SDimitry Andric AArch64ABIKind Kind, AggValueSlot Slot) const;
6306c3fb27SDimitry Andric
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const640fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
650fca6ea1SDimitry Andric AggValueSlot Slot) const override {
6606c3fb27SDimitry Andric llvm::Type *BaseTy = CGF.ConvertType(Ty);
6706c3fb27SDimitry Andric if (isa<llvm::ScalableVectorType>(BaseTy))
6806c3fb27SDimitry Andric llvm::report_fatal_error("Passing SVE types to variadic functions is "
6906c3fb27SDimitry Andric "currently not supported");
7006c3fb27SDimitry Andric
710fca6ea1SDimitry Andric return Kind == AArch64ABIKind::Win64
720fca6ea1SDimitry Andric ? EmitMSVAArg(CGF, VAListAddr, Ty, Slot)
730fca6ea1SDimitry Andric : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF, Slot)
740fca6ea1SDimitry Andric : EmitAAPCSVAArg(VAListAddr, Ty, CGF, Kind, Slot);
7506c3fb27SDimitry Andric }
7606c3fb27SDimitry Andric
770fca6ea1SDimitry Andric RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
780fca6ea1SDimitry Andric AggValueSlot Slot) const override;
7906c3fb27SDimitry Andric
allowBFloatArgsAndRet() const8006c3fb27SDimitry Andric bool allowBFloatArgsAndRet() const override {
8106c3fb27SDimitry Andric return getTarget().hasBFloat16Type();
8206c3fb27SDimitry Andric }
830fca6ea1SDimitry Andric
840fca6ea1SDimitry Andric using ABIInfo::appendAttributeMangling;
850fca6ea1SDimitry Andric void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
860fca6ea1SDimitry Andric raw_ostream &Out) const override;
870fca6ea1SDimitry Andric void appendAttributeMangling(StringRef AttrStr,
880fca6ea1SDimitry Andric raw_ostream &Out) const override;
8906c3fb27SDimitry Andric };
9006c3fb27SDimitry Andric
9106c3fb27SDimitry Andric class AArch64SwiftABIInfo : public SwiftABIInfo {
9206c3fb27SDimitry Andric public:
AArch64SwiftABIInfo(CodeGenTypes & CGT)9306c3fb27SDimitry Andric explicit AArch64SwiftABIInfo(CodeGenTypes &CGT)
9406c3fb27SDimitry Andric : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {}
9506c3fb27SDimitry Andric
9606c3fb27SDimitry Andric bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy,
9706c3fb27SDimitry Andric unsigned NumElts) const override;
9806c3fb27SDimitry Andric };
9906c3fb27SDimitry Andric
10006c3fb27SDimitry Andric class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
10106c3fb27SDimitry Andric public:
AArch64TargetCodeGenInfo(CodeGenTypes & CGT,AArch64ABIKind Kind)10206c3fb27SDimitry Andric AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind Kind)
10306c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGT, Kind)) {
10406c3fb27SDimitry Andric SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGT);
10506c3fb27SDimitry Andric }
10606c3fb27SDimitry Andric
getARCRetainAutoreleasedReturnValueMarker() const10706c3fb27SDimitry Andric StringRef getARCRetainAutoreleasedReturnValueMarker() const override {
10806c3fb27SDimitry Andric return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue";
10906c3fb27SDimitry Andric }
11006c3fb27SDimitry Andric
getDwarfEHStackPointer(CodeGen::CodeGenModule & M) const11106c3fb27SDimitry Andric int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
11206c3fb27SDimitry Andric return 31;
11306c3fb27SDimitry Andric }
11406c3fb27SDimitry Andric
doesReturnSlotInterfereWithArgs() const11506c3fb27SDimitry Andric bool doesReturnSlotInterfereWithArgs() const override { return false; }
11606c3fb27SDimitry Andric
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & CGM) const11706c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
11806c3fb27SDimitry Andric CodeGen::CodeGenModule &CGM) const override {
11906c3fb27SDimitry Andric const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
12006c3fb27SDimitry Andric if (!FD)
12106c3fb27SDimitry Andric return;
12206c3fb27SDimitry Andric
1230fca6ea1SDimitry Andric TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
12406c3fb27SDimitry Andric
1250fca6ea1SDimitry Andric if (const auto *TA = FD->getAttr<TargetAttr>()) {
12606c3fb27SDimitry Andric ParsedTargetAttr Attr =
12706c3fb27SDimitry Andric CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
1280fca6ea1SDimitry Andric if (!Attr.BranchProtection.empty()) {
12906c3fb27SDimitry Andric StringRef Error;
13006c3fb27SDimitry Andric (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
13106c3fb27SDimitry Andric Attr.CPU, BPI, Error);
13206c3fb27SDimitry Andric assert(Error.empty());
13306c3fb27SDimitry Andric }
1340fca6ea1SDimitry Andric }
1350fca6ea1SDimitry Andric auto *Fn = cast<llvm::Function>(GV);
1360fca6ea1SDimitry Andric setBranchProtectionFnAttributes(BPI, *Fn);
13706c3fb27SDimitry Andric }
13806c3fb27SDimitry Andric
isScalarizableAsmOperand(CodeGen::CodeGenFunction & CGF,llvm::Type * Ty) const13906c3fb27SDimitry Andric bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
14006c3fb27SDimitry Andric llvm::Type *Ty) const override {
14106c3fb27SDimitry Andric if (CGF.getTarget().hasFeature("ls64")) {
14206c3fb27SDimitry Andric auto *ST = dyn_cast<llvm::StructType>(Ty);
14306c3fb27SDimitry Andric if (ST && ST->getNumElements() == 1) {
14406c3fb27SDimitry Andric auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
14506c3fb27SDimitry Andric if (AT && AT->getNumElements() == 8 &&
14606c3fb27SDimitry Andric AT->getElementType()->isIntegerTy(64))
14706c3fb27SDimitry Andric return true;
14806c3fb27SDimitry Andric }
14906c3fb27SDimitry Andric }
15006c3fb27SDimitry Andric return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty);
15106c3fb27SDimitry Andric }
1520fca6ea1SDimitry Andric
1530fca6ea1SDimitry Andric void checkFunctionABI(CodeGenModule &CGM,
1540fca6ea1SDimitry Andric const FunctionDecl *Decl) const override;
1550fca6ea1SDimitry Andric
1560fca6ea1SDimitry Andric void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc,
1570fca6ea1SDimitry Andric const FunctionDecl *Caller,
1580fca6ea1SDimitry Andric const FunctionDecl *Callee, const CallArgList &Args,
1590fca6ea1SDimitry Andric QualType ReturnType) const override;
1600fca6ea1SDimitry Andric
1610fca6ea1SDimitry Andric private:
1620fca6ea1SDimitry Andric // Diagnose calls between functions with incompatible Streaming SVE
1630fca6ea1SDimitry Andric // attributes.
1640fca6ea1SDimitry Andric void checkFunctionCallABIStreaming(CodeGenModule &CGM, SourceLocation CallLoc,
1650fca6ea1SDimitry Andric const FunctionDecl *Caller,
1660fca6ea1SDimitry Andric const FunctionDecl *Callee) const;
1670fca6ea1SDimitry Andric // Diagnose calls which must pass arguments in floating-point registers when
1680fca6ea1SDimitry Andric // the selected target does not have floating-point registers.
1690fca6ea1SDimitry Andric void checkFunctionCallABISoftFloat(CodeGenModule &CGM, SourceLocation CallLoc,
1700fca6ea1SDimitry Andric const FunctionDecl *Caller,
1710fca6ea1SDimitry Andric const FunctionDecl *Callee,
1720fca6ea1SDimitry Andric const CallArgList &Args,
1730fca6ea1SDimitry Andric QualType ReturnType) const;
17406c3fb27SDimitry Andric };
17506c3fb27SDimitry Andric
17606c3fb27SDimitry Andric class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
17706c3fb27SDimitry Andric public:
WindowsAArch64TargetCodeGenInfo(CodeGenTypes & CGT,AArch64ABIKind K)17806c3fb27SDimitry Andric WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind K)
17906c3fb27SDimitry Andric : AArch64TargetCodeGenInfo(CGT, K) {}
18006c3fb27SDimitry Andric
18106c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
18206c3fb27SDimitry Andric CodeGen::CodeGenModule &CGM) const override;
18306c3fb27SDimitry Andric
getDependentLibraryOption(llvm::StringRef Lib,llvm::SmallString<24> & Opt) const18406c3fb27SDimitry Andric void getDependentLibraryOption(llvm::StringRef Lib,
18506c3fb27SDimitry Andric llvm::SmallString<24> &Opt) const override {
18606c3fb27SDimitry Andric Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib);
18706c3fb27SDimitry Andric }
18806c3fb27SDimitry Andric
getDetectMismatchOption(llvm::StringRef Name,llvm::StringRef Value,llvm::SmallString<32> & Opt) const18906c3fb27SDimitry Andric void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value,
19006c3fb27SDimitry Andric llvm::SmallString<32> &Opt) const override {
19106c3fb27SDimitry Andric Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
19206c3fb27SDimitry Andric }
19306c3fb27SDimitry Andric };
19406c3fb27SDimitry Andric
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & CGM) const19506c3fb27SDimitry Andric void WindowsAArch64TargetCodeGenInfo::setTargetAttributes(
19606c3fb27SDimitry Andric const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
19706c3fb27SDimitry Andric AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
19806c3fb27SDimitry Andric if (GV->isDeclaration())
19906c3fb27SDimitry Andric return;
20006c3fb27SDimitry Andric addStackProbeTargetAttributes(D, GV, CGM);
20106c3fb27SDimitry Andric }
20206c3fb27SDimitry Andric }
20306c3fb27SDimitry Andric
coerceIllegalVector(QualType Ty) const20406c3fb27SDimitry Andric ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty) const {
20506c3fb27SDimitry Andric assert(Ty->isVectorType() && "expected vector type!");
20606c3fb27SDimitry Andric
20706c3fb27SDimitry Andric const auto *VT = Ty->castAs<VectorType>();
2085f757f3fSDimitry Andric if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) {
20906c3fb27SDimitry Andric assert(VT->getElementType()->isBuiltinType() && "expected builtin type!");
21006c3fb27SDimitry Andric assert(VT->getElementType()->castAs<BuiltinType>()->getKind() ==
21106c3fb27SDimitry Andric BuiltinType::UChar &&
21206c3fb27SDimitry Andric "unexpected builtin type for SVE predicate!");
21306c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::ScalableVectorType::get(
21406c3fb27SDimitry Andric llvm::Type::getInt1Ty(getVMContext()), 16));
21506c3fb27SDimitry Andric }
21606c3fb27SDimitry Andric
2175f757f3fSDimitry Andric if (VT->getVectorKind() == VectorKind::SveFixedLengthData) {
21806c3fb27SDimitry Andric assert(VT->getElementType()->isBuiltinType() && "expected builtin type!");
21906c3fb27SDimitry Andric
22006c3fb27SDimitry Andric const auto *BT = VT->getElementType()->castAs<BuiltinType>();
22106c3fb27SDimitry Andric llvm::ScalableVectorType *ResType = nullptr;
22206c3fb27SDimitry Andric switch (BT->getKind()) {
22306c3fb27SDimitry Andric default:
22406c3fb27SDimitry Andric llvm_unreachable("unexpected builtin type for SVE vector!");
22506c3fb27SDimitry Andric case BuiltinType::SChar:
22606c3fb27SDimitry Andric case BuiltinType::UChar:
22706c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
22806c3fb27SDimitry Andric llvm::Type::getInt8Ty(getVMContext()), 16);
22906c3fb27SDimitry Andric break;
23006c3fb27SDimitry Andric case BuiltinType::Short:
23106c3fb27SDimitry Andric case BuiltinType::UShort:
23206c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
23306c3fb27SDimitry Andric llvm::Type::getInt16Ty(getVMContext()), 8);
23406c3fb27SDimitry Andric break;
23506c3fb27SDimitry Andric case BuiltinType::Int:
23606c3fb27SDimitry Andric case BuiltinType::UInt:
23706c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
23806c3fb27SDimitry Andric llvm::Type::getInt32Ty(getVMContext()), 4);
23906c3fb27SDimitry Andric break;
24006c3fb27SDimitry Andric case BuiltinType::Long:
24106c3fb27SDimitry Andric case BuiltinType::ULong:
24206c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
24306c3fb27SDimitry Andric llvm::Type::getInt64Ty(getVMContext()), 2);
24406c3fb27SDimitry Andric break;
24506c3fb27SDimitry Andric case BuiltinType::Half:
24606c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
24706c3fb27SDimitry Andric llvm::Type::getHalfTy(getVMContext()), 8);
24806c3fb27SDimitry Andric break;
24906c3fb27SDimitry Andric case BuiltinType::Float:
25006c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
25106c3fb27SDimitry Andric llvm::Type::getFloatTy(getVMContext()), 4);
25206c3fb27SDimitry Andric break;
25306c3fb27SDimitry Andric case BuiltinType::Double:
25406c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
25506c3fb27SDimitry Andric llvm::Type::getDoubleTy(getVMContext()), 2);
25606c3fb27SDimitry Andric break;
25706c3fb27SDimitry Andric case BuiltinType::BFloat16:
25806c3fb27SDimitry Andric ResType = llvm::ScalableVectorType::get(
25906c3fb27SDimitry Andric llvm::Type::getBFloatTy(getVMContext()), 8);
26006c3fb27SDimitry Andric break;
26106c3fb27SDimitry Andric }
26206c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType);
26306c3fb27SDimitry Andric }
26406c3fb27SDimitry Andric
26506c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty);
26606c3fb27SDimitry Andric // Android promotes <2 x i8> to i16, not i32
26706c3fb27SDimitry Andric if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) {
26806c3fb27SDimitry Andric llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext());
26906c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType);
27006c3fb27SDimitry Andric }
27106c3fb27SDimitry Andric if (Size <= 32) {
27206c3fb27SDimitry Andric llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext());
27306c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType);
27406c3fb27SDimitry Andric }
27506c3fb27SDimitry Andric if (Size == 64) {
27606c3fb27SDimitry Andric auto *ResType =
27706c3fb27SDimitry Andric llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2);
27806c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType);
27906c3fb27SDimitry Andric }
28006c3fb27SDimitry Andric if (Size == 128) {
28106c3fb27SDimitry Andric auto *ResType =
28206c3fb27SDimitry Andric llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4);
28306c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType);
28406c3fb27SDimitry Andric }
28506c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
28606c3fb27SDimitry Andric }
28706c3fb27SDimitry Andric
28806c3fb27SDimitry Andric ABIArgInfo
classifyArgumentType(QualType Ty,bool IsVariadic,unsigned CallingConvention) const28906c3fb27SDimitry Andric AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic,
29006c3fb27SDimitry Andric unsigned CallingConvention) const {
29106c3fb27SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty);
29206c3fb27SDimitry Andric
29306c3fb27SDimitry Andric // Handle illegal vector types here.
29406c3fb27SDimitry Andric if (isIllegalVectorType(Ty))
29506c3fb27SDimitry Andric return coerceIllegalVector(Ty);
29606c3fb27SDimitry Andric
29706c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty)) {
29806c3fb27SDimitry Andric // Treat an enum type as its underlying type.
29906c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>())
30006c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType();
30106c3fb27SDimitry Andric
30206c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>())
30306c3fb27SDimitry Andric if (EIT->getNumBits() > 128)
3040fca6ea1SDimitry Andric return getNaturalAlignIndirect(Ty, false);
30506c3fb27SDimitry Andric
30606c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS()
30706c3fb27SDimitry Andric ? ABIArgInfo::getExtend(Ty)
30806c3fb27SDimitry Andric : ABIArgInfo::getDirect());
30906c3fb27SDimitry Andric }
31006c3fb27SDimitry Andric
31106c3fb27SDimitry Andric // Structures with either a non-trivial destructor or a non-trivial
31206c3fb27SDimitry Andric // copy constructor are always indirect.
31306c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
31406c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
31506c3fb27SDimitry Andric CGCXXABI::RAA_DirectInMemory);
31606c3fb27SDimitry Andric }
31706c3fb27SDimitry Andric
31806c3fb27SDimitry Andric // Empty records are always ignored on Darwin, but actually passed in C++ mode
31906c3fb27SDimitry Andric // elsewhere for GNU compatibility.
32006c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty);
32106c3fb27SDimitry Andric bool IsEmpty = isEmptyRecord(getContext(), Ty, true);
32206c3fb27SDimitry Andric if (IsEmpty || Size == 0) {
32306c3fb27SDimitry Andric if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS())
32406c3fb27SDimitry Andric return ABIArgInfo::getIgnore();
32506c3fb27SDimitry Andric
32606c3fb27SDimitry Andric // GNU C mode. The only argument that gets ignored is an empty one with size
32706c3fb27SDimitry Andric // 0.
32806c3fb27SDimitry Andric if (IsEmpty && Size == 0)
32906c3fb27SDimitry Andric return ABIArgInfo::getIgnore();
33006c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
33106c3fb27SDimitry Andric }
33206c3fb27SDimitry Andric
33306c3fb27SDimitry Andric // Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
33406c3fb27SDimitry Andric const Type *Base = nullptr;
33506c3fb27SDimitry Andric uint64_t Members = 0;
33606c3fb27SDimitry Andric bool IsWin64 = Kind == AArch64ABIKind::Win64 ||
33706c3fb27SDimitry Andric CallingConvention == llvm::CallingConv::Win64;
33806c3fb27SDimitry Andric bool IsWinVariadic = IsWin64 && IsVariadic;
33906c3fb27SDimitry Andric // In variadic functions on Windows, all composite types are treated alike,
34006c3fb27SDimitry Andric // no special handling of HFAs/HVAs.
34106c3fb27SDimitry Andric if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
34206c3fb27SDimitry Andric if (Kind != AArch64ABIKind::AAPCS)
34306c3fb27SDimitry Andric return ABIArgInfo::getDirect(
34406c3fb27SDimitry Andric llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members));
34506c3fb27SDimitry Andric
3465f757f3fSDimitry Andric // For HFAs/HVAs, cap the argument alignment to 16, otherwise
3475f757f3fSDimitry Andric // set it to 8 according to the AAPCS64 document.
34806c3fb27SDimitry Andric unsigned Align =
34906c3fb27SDimitry Andric getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
3505f757f3fSDimitry Andric Align = (Align >= 16) ? 16 : 8;
35106c3fb27SDimitry Andric return ABIArgInfo::getDirect(
35206c3fb27SDimitry Andric llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0,
35306c3fb27SDimitry Andric nullptr, true, Align);
35406c3fb27SDimitry Andric }
35506c3fb27SDimitry Andric
35606c3fb27SDimitry Andric // Aggregates <= 16 bytes are passed directly in registers or on the stack.
35706c3fb27SDimitry Andric if (Size <= 128) {
35806c3fb27SDimitry Andric // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of
35906c3fb27SDimitry Andric // same size and alignment.
36006c3fb27SDimitry Andric if (getTarget().isRenderScriptTarget()) {
36106c3fb27SDimitry Andric return coerceToIntArray(Ty, getContext(), getVMContext());
36206c3fb27SDimitry Andric }
36306c3fb27SDimitry Andric unsigned Alignment;
36406c3fb27SDimitry Andric if (Kind == AArch64ABIKind::AAPCS) {
36506c3fb27SDimitry Andric Alignment = getContext().getTypeUnadjustedAlign(Ty);
36606c3fb27SDimitry Andric Alignment = Alignment < 128 ? 64 : 128;
36706c3fb27SDimitry Andric } else {
36806c3fb27SDimitry Andric Alignment =
36906c3fb27SDimitry Andric std::max(getContext().getTypeAlign(Ty),
37006c3fb27SDimitry Andric (unsigned)getTarget().getPointerWidth(LangAS::Default));
37106c3fb27SDimitry Andric }
37206c3fb27SDimitry Andric Size = llvm::alignTo(Size, Alignment);
37306c3fb27SDimitry Andric
37406c3fb27SDimitry Andric // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
37506c3fb27SDimitry Andric // For aggregates with 16-byte alignment, we use i128.
37606c3fb27SDimitry Andric llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment);
37706c3fb27SDimitry Andric return ABIArgInfo::getDirect(
37806c3fb27SDimitry Andric Size == Alignment ? BaseTy
37906c3fb27SDimitry Andric : llvm::ArrayType::get(BaseTy, Size / Alignment));
38006c3fb27SDimitry Andric }
38106c3fb27SDimitry Andric
38206c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
38306c3fb27SDimitry Andric }
38406c3fb27SDimitry Andric
classifyReturnType(QualType RetTy,bool IsVariadic) const38506c3fb27SDimitry Andric ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy,
38606c3fb27SDimitry Andric bool IsVariadic) const {
38706c3fb27SDimitry Andric if (RetTy->isVoidType())
38806c3fb27SDimitry Andric return ABIArgInfo::getIgnore();
38906c3fb27SDimitry Andric
39006c3fb27SDimitry Andric if (const auto *VT = RetTy->getAs<VectorType>()) {
3915f757f3fSDimitry Andric if (VT->getVectorKind() == VectorKind::SveFixedLengthData ||
3925f757f3fSDimitry Andric VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
39306c3fb27SDimitry Andric return coerceIllegalVector(RetTy);
39406c3fb27SDimitry Andric }
39506c3fb27SDimitry Andric
39606c3fb27SDimitry Andric // Large vector types should be returned via memory.
39706c3fb27SDimitry Andric if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128)
39806c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy);
39906c3fb27SDimitry Andric
40006c3fb27SDimitry Andric if (!isAggregateTypeForABI(RetTy)) {
40106c3fb27SDimitry Andric // Treat an enum type as its underlying type.
40206c3fb27SDimitry Andric if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
40306c3fb27SDimitry Andric RetTy = EnumTy->getDecl()->getIntegerType();
40406c3fb27SDimitry Andric
40506c3fb27SDimitry Andric if (const auto *EIT = RetTy->getAs<BitIntType>())
40606c3fb27SDimitry Andric if (EIT->getNumBits() > 128)
40706c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy);
40806c3fb27SDimitry Andric
40906c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS()
41006c3fb27SDimitry Andric ? ABIArgInfo::getExtend(RetTy)
41106c3fb27SDimitry Andric : ABIArgInfo::getDirect());
41206c3fb27SDimitry Andric }
41306c3fb27SDimitry Andric
41406c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(RetTy);
41506c3fb27SDimitry Andric if (isEmptyRecord(getContext(), RetTy, true) || Size == 0)
41606c3fb27SDimitry Andric return ABIArgInfo::getIgnore();
41706c3fb27SDimitry Andric
41806c3fb27SDimitry Andric const Type *Base = nullptr;
41906c3fb27SDimitry Andric uint64_t Members = 0;
42006c3fb27SDimitry Andric if (isHomogeneousAggregate(RetTy, Base, Members) &&
42106c3fb27SDimitry Andric !(getTarget().getTriple().getArch() == llvm::Triple::aarch64_32 &&
42206c3fb27SDimitry Andric IsVariadic))
42306c3fb27SDimitry Andric // Homogeneous Floating-point Aggregates (HFAs) are returned directly.
42406c3fb27SDimitry Andric return ABIArgInfo::getDirect();
42506c3fb27SDimitry Andric
42606c3fb27SDimitry Andric // Aggregates <= 16 bytes are returned directly in registers or on the stack.
42706c3fb27SDimitry Andric if (Size <= 128) {
42806c3fb27SDimitry Andric // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of
42906c3fb27SDimitry Andric // same size and alignment.
43006c3fb27SDimitry Andric if (getTarget().isRenderScriptTarget()) {
43106c3fb27SDimitry Andric return coerceToIntArray(RetTy, getContext(), getVMContext());
43206c3fb27SDimitry Andric }
43306c3fb27SDimitry Andric
43406c3fb27SDimitry Andric if (Size <= 64 && getDataLayout().isLittleEndian()) {
43506c3fb27SDimitry Andric // Composite types are returned in lower bits of a 64-bit register for LE,
43606c3fb27SDimitry Andric // and in higher bits for BE. However, integer types are always returned
43706c3fb27SDimitry Andric // in lower bits for both LE and BE, and they are not rounded up to
43806c3fb27SDimitry Andric // 64-bits. We can skip rounding up of composite types for LE, but not for
43906c3fb27SDimitry Andric // BE, otherwise composite types will be indistinguishable from integer
44006c3fb27SDimitry Andric // types.
44106c3fb27SDimitry Andric return ABIArgInfo::getDirect(
44206c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), Size));
44306c3fb27SDimitry Andric }
44406c3fb27SDimitry Andric
44506c3fb27SDimitry Andric unsigned Alignment = getContext().getTypeAlign(RetTy);
44606c3fb27SDimitry Andric Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
44706c3fb27SDimitry Andric
44806c3fb27SDimitry Andric // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
44906c3fb27SDimitry Andric // For aggregates with 16-byte alignment, we use i128.
45006c3fb27SDimitry Andric if (Alignment < 128 && Size == 128) {
45106c3fb27SDimitry Andric llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext());
45206c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
45306c3fb27SDimitry Andric }
45406c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
45506c3fb27SDimitry Andric }
45606c3fb27SDimitry Andric
45706c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy);
45806c3fb27SDimitry Andric }
45906c3fb27SDimitry Andric
46006c3fb27SDimitry Andric /// isIllegalVectorType - check whether the vector type is legal for AArch64.
isIllegalVectorType(QualType Ty) const46106c3fb27SDimitry Andric bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const {
46206c3fb27SDimitry Andric if (const VectorType *VT = Ty->getAs<VectorType>()) {
46306c3fb27SDimitry Andric // Check whether VT is a fixed-length SVE vector. These types are
46406c3fb27SDimitry Andric // represented as scalable vectors in function args/return and must be
46506c3fb27SDimitry Andric // coerced from fixed vectors.
4665f757f3fSDimitry Andric if (VT->getVectorKind() == VectorKind::SveFixedLengthData ||
4675f757f3fSDimitry Andric VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
46806c3fb27SDimitry Andric return true;
46906c3fb27SDimitry Andric
47006c3fb27SDimitry Andric // Check whether VT is legal.
47106c3fb27SDimitry Andric unsigned NumElements = VT->getNumElements();
47206c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(VT);
47306c3fb27SDimitry Andric // NumElements should be power of 2.
47406c3fb27SDimitry Andric if (!llvm::isPowerOf2_32(NumElements))
47506c3fb27SDimitry Andric return true;
47606c3fb27SDimitry Andric
47706c3fb27SDimitry Andric // arm64_32 has to be compatible with the ARM logic here, which allows huge
47806c3fb27SDimitry Andric // vectors for some reason.
47906c3fb27SDimitry Andric llvm::Triple Triple = getTarget().getTriple();
48006c3fb27SDimitry Andric if (Triple.getArch() == llvm::Triple::aarch64_32 &&
48106c3fb27SDimitry Andric Triple.isOSBinFormatMachO())
48206c3fb27SDimitry Andric return Size <= 32;
48306c3fb27SDimitry Andric
48406c3fb27SDimitry Andric return Size != 64 && (Size != 128 || NumElements == 1);
48506c3fb27SDimitry Andric }
48606c3fb27SDimitry Andric return false;
48706c3fb27SDimitry Andric }
48806c3fb27SDimitry Andric
isLegalVectorType(CharUnits VectorSize,llvm::Type * EltTy,unsigned NumElts) const48906c3fb27SDimitry Andric bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize,
49006c3fb27SDimitry Andric llvm::Type *EltTy,
49106c3fb27SDimitry Andric unsigned NumElts) const {
49206c3fb27SDimitry Andric if (!llvm::isPowerOf2_32(NumElts))
49306c3fb27SDimitry Andric return false;
49406c3fb27SDimitry Andric if (VectorSize.getQuantity() != 8 &&
49506c3fb27SDimitry Andric (VectorSize.getQuantity() != 16 || NumElts == 1))
49606c3fb27SDimitry Andric return false;
49706c3fb27SDimitry Andric return true;
49806c3fb27SDimitry Andric }
49906c3fb27SDimitry Andric
isHomogeneousAggregateBaseType(QualType Ty) const50006c3fb27SDimitry Andric bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
5010fca6ea1SDimitry Andric // For the soft-float ABI variant, no types are considered to be homogeneous
5020fca6ea1SDimitry Andric // aggregates.
5030fca6ea1SDimitry Andric if (Kind == AArch64ABIKind::AAPCSSoft)
5040fca6ea1SDimitry Andric return false;
5050fca6ea1SDimitry Andric
50606c3fb27SDimitry Andric // Homogeneous aggregates for AAPCS64 must have base types of a floating
50706c3fb27SDimitry Andric // point type or a short-vector type. This is the same as the 32-bit ABI,
50806c3fb27SDimitry Andric // but with the difference that any floating-point type is allowed,
50906c3fb27SDimitry Andric // including __fp16.
51006c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) {
51106c3fb27SDimitry Andric if (BT->isFloatingPoint())
51206c3fb27SDimitry Andric return true;
51306c3fb27SDimitry Andric } else if (const VectorType *VT = Ty->getAs<VectorType>()) {
51406c3fb27SDimitry Andric unsigned VecSize = getContext().getTypeSize(VT);
51506c3fb27SDimitry Andric if (VecSize == 64 || VecSize == 128)
51606c3fb27SDimitry Andric return true;
51706c3fb27SDimitry Andric }
51806c3fb27SDimitry Andric return false;
51906c3fb27SDimitry Andric }
52006c3fb27SDimitry Andric
isHomogeneousAggregateSmallEnough(const Type * Base,uint64_t Members) const52106c3fb27SDimitry Andric bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base,
52206c3fb27SDimitry Andric uint64_t Members) const {
52306c3fb27SDimitry Andric return Members <= 4;
52406c3fb27SDimitry Andric }
52506c3fb27SDimitry Andric
isZeroLengthBitfieldPermittedInHomogeneousAggregate() const52606c3fb27SDimitry Andric bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
52706c3fb27SDimitry Andric const {
52806c3fb27SDimitry Andric // AAPCS64 says that the rule for whether something is a homogeneous
52906c3fb27SDimitry Andric // aggregate is applied to the output of the data layout decision. So
53006c3fb27SDimitry Andric // anything that doesn't affect the data layout also does not affect
53106c3fb27SDimitry Andric // homogeneity. In particular, zero-length bitfields don't stop a struct
53206c3fb27SDimitry Andric // being homogeneous.
53306c3fb27SDimitry Andric return true;
53406c3fb27SDimitry Andric }
53506c3fb27SDimitry Andric
EmitAAPCSVAArg(Address VAListAddr,QualType Ty,CodeGenFunction & CGF,AArch64ABIKind Kind,AggValueSlot Slot) const5360fca6ea1SDimitry Andric RValue AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
5370fca6ea1SDimitry Andric CodeGenFunction &CGF, AArch64ABIKind Kind,
5380fca6ea1SDimitry Andric AggValueSlot Slot) const {
53906c3fb27SDimitry Andric ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true,
54006c3fb27SDimitry Andric CGF.CurFnInfo->getCallingConvention());
54106c3fb27SDimitry Andric // Empty records are ignored for parameter passing purposes.
5420fca6ea1SDimitry Andric if (AI.isIgnore())
5430fca6ea1SDimitry Andric return Slot.asRValue();
54406c3fb27SDimitry Andric
54506c3fb27SDimitry Andric bool IsIndirect = AI.isIndirect();
54606c3fb27SDimitry Andric
54706c3fb27SDimitry Andric llvm::Type *BaseTy = CGF.ConvertType(Ty);
54806c3fb27SDimitry Andric if (IsIndirect)
54906c3fb27SDimitry Andric BaseTy = llvm::PointerType::getUnqual(BaseTy);
55006c3fb27SDimitry Andric else if (AI.getCoerceToType())
55106c3fb27SDimitry Andric BaseTy = AI.getCoerceToType();
55206c3fb27SDimitry Andric
55306c3fb27SDimitry Andric unsigned NumRegs = 1;
55406c3fb27SDimitry Andric if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) {
55506c3fb27SDimitry Andric BaseTy = ArrTy->getElementType();
55606c3fb27SDimitry Andric NumRegs = ArrTy->getNumElements();
55706c3fb27SDimitry Andric }
5580fca6ea1SDimitry Andric bool IsFPR = Kind != AArch64ABIKind::AAPCSSoft &&
5590fca6ea1SDimitry Andric (BaseTy->isFloatingPointTy() || BaseTy->isVectorTy());
56006c3fb27SDimitry Andric
56106c3fb27SDimitry Andric // The AArch64 va_list type and handling is specified in the Procedure Call
56206c3fb27SDimitry Andric // Standard, section B.4:
56306c3fb27SDimitry Andric //
56406c3fb27SDimitry Andric // struct {
56506c3fb27SDimitry Andric // void *__stack;
56606c3fb27SDimitry Andric // void *__gr_top;
56706c3fb27SDimitry Andric // void *__vr_top;
56806c3fb27SDimitry Andric // int __gr_offs;
56906c3fb27SDimitry Andric // int __vr_offs;
57006c3fb27SDimitry Andric // };
57106c3fb27SDimitry Andric
57206c3fb27SDimitry Andric llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg");
57306c3fb27SDimitry Andric llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
57406c3fb27SDimitry Andric llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack");
57506c3fb27SDimitry Andric llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
57606c3fb27SDimitry Andric
57706c3fb27SDimitry Andric CharUnits TySize = getContext().getTypeSizeInChars(Ty);
57806c3fb27SDimitry Andric CharUnits TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty);
57906c3fb27SDimitry Andric
58006c3fb27SDimitry Andric Address reg_offs_p = Address::invalid();
58106c3fb27SDimitry Andric llvm::Value *reg_offs = nullptr;
58206c3fb27SDimitry Andric int reg_top_index;
58306c3fb27SDimitry Andric int RegSize = IsIndirect ? 8 : TySize.getQuantity();
58406c3fb27SDimitry Andric if (!IsFPR) {
58506c3fb27SDimitry Andric // 3 is the field number of __gr_offs
58606c3fb27SDimitry Andric reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 3, "gr_offs_p");
58706c3fb27SDimitry Andric reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs");
58806c3fb27SDimitry Andric reg_top_index = 1; // field number for __gr_top
58906c3fb27SDimitry Andric RegSize = llvm::alignTo(RegSize, 8);
59006c3fb27SDimitry Andric } else {
59106c3fb27SDimitry Andric // 4 is the field number of __vr_offs.
59206c3fb27SDimitry Andric reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 4, "vr_offs_p");
59306c3fb27SDimitry Andric reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs");
59406c3fb27SDimitry Andric reg_top_index = 2; // field number for __vr_top
59506c3fb27SDimitry Andric RegSize = 16 * NumRegs;
59606c3fb27SDimitry Andric }
59706c3fb27SDimitry Andric
59806c3fb27SDimitry Andric //=======================================
59906c3fb27SDimitry Andric // Find out where argument was passed
60006c3fb27SDimitry Andric //=======================================
60106c3fb27SDimitry Andric
60206c3fb27SDimitry Andric // If reg_offs >= 0 we're already using the stack for this type of
60306c3fb27SDimitry Andric // argument. We don't want to keep updating reg_offs (in case it overflows,
60406c3fb27SDimitry Andric // though anyone passing 2GB of arguments, each at most 16 bytes, deserves
60506c3fb27SDimitry Andric // whatever they get).
60606c3fb27SDimitry Andric llvm::Value *UsingStack = nullptr;
60706c3fb27SDimitry Andric UsingStack = CGF.Builder.CreateICmpSGE(
60806c3fb27SDimitry Andric reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, 0));
60906c3fb27SDimitry Andric
61006c3fb27SDimitry Andric CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock);
61106c3fb27SDimitry Andric
61206c3fb27SDimitry Andric // Otherwise, at least some kind of argument could go in these registers, the
61306c3fb27SDimitry Andric // question is whether this particular type is too big.
61406c3fb27SDimitry Andric CGF.EmitBlock(MaybeRegBlock);
61506c3fb27SDimitry Andric
61606c3fb27SDimitry Andric // Integer arguments may need to correct register alignment (for example a
61706c3fb27SDimitry Andric // "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we
61806c3fb27SDimitry Andric // align __gr_offs to calculate the potential address.
61906c3fb27SDimitry Andric if (!IsFPR && !IsIndirect && TyAlign.getQuantity() > 8) {
62006c3fb27SDimitry Andric int Align = TyAlign.getQuantity();
62106c3fb27SDimitry Andric
62206c3fb27SDimitry Andric reg_offs = CGF.Builder.CreateAdd(
62306c3fb27SDimitry Andric reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, Align - 1),
62406c3fb27SDimitry Andric "align_regoffs");
62506c3fb27SDimitry Andric reg_offs = CGF.Builder.CreateAnd(
62606c3fb27SDimitry Andric reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, -Align),
62706c3fb27SDimitry Andric "aligned_regoffs");
62806c3fb27SDimitry Andric }
62906c3fb27SDimitry Andric
63006c3fb27SDimitry Andric // Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list.
63106c3fb27SDimitry Andric // The fact that this is done unconditionally reflects the fact that
63206c3fb27SDimitry Andric // allocating an argument to the stack also uses up all the remaining
63306c3fb27SDimitry Andric // registers of the appropriate kind.
63406c3fb27SDimitry Andric llvm::Value *NewOffset = nullptr;
63506c3fb27SDimitry Andric NewOffset = CGF.Builder.CreateAdd(
63606c3fb27SDimitry Andric reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs");
63706c3fb27SDimitry Andric CGF.Builder.CreateStore(NewOffset, reg_offs_p);
63806c3fb27SDimitry Andric
63906c3fb27SDimitry Andric // Now we're in a position to decide whether this argument really was in
64006c3fb27SDimitry Andric // registers or not.
64106c3fb27SDimitry Andric llvm::Value *InRegs = nullptr;
64206c3fb27SDimitry Andric InRegs = CGF.Builder.CreateICmpSLE(
64306c3fb27SDimitry Andric NewOffset, llvm::ConstantInt::get(CGF.Int32Ty, 0), "inreg");
64406c3fb27SDimitry Andric
64506c3fb27SDimitry Andric CGF.Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock);
64606c3fb27SDimitry Andric
64706c3fb27SDimitry Andric //=======================================
64806c3fb27SDimitry Andric // Argument was in registers
64906c3fb27SDimitry Andric //=======================================
65006c3fb27SDimitry Andric
65106c3fb27SDimitry Andric // Now we emit the code for if the argument was originally passed in
65206c3fb27SDimitry Andric // registers. First start the appropriate block:
65306c3fb27SDimitry Andric CGF.EmitBlock(InRegBlock);
65406c3fb27SDimitry Andric
65506c3fb27SDimitry Andric llvm::Value *reg_top = nullptr;
65606c3fb27SDimitry Andric Address reg_top_p =
65706c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p");
65806c3fb27SDimitry Andric reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top");
65906c3fb27SDimitry Andric Address BaseAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, reg_top, reg_offs),
66006c3fb27SDimitry Andric CGF.Int8Ty, CharUnits::fromQuantity(IsFPR ? 16 : 8));
66106c3fb27SDimitry Andric Address RegAddr = Address::invalid();
66206c3fb27SDimitry Andric llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty), *ElementTy = MemTy;
66306c3fb27SDimitry Andric
66406c3fb27SDimitry Andric if (IsIndirect) {
66506c3fb27SDimitry Andric // If it's been passed indirectly (actually a struct), whatever we find from
66606c3fb27SDimitry Andric // stored registers or on the stack will actually be a struct **.
66706c3fb27SDimitry Andric MemTy = llvm::PointerType::getUnqual(MemTy);
66806c3fb27SDimitry Andric }
66906c3fb27SDimitry Andric
67006c3fb27SDimitry Andric const Type *Base = nullptr;
67106c3fb27SDimitry Andric uint64_t NumMembers = 0;
67206c3fb27SDimitry Andric bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers);
67306c3fb27SDimitry Andric if (IsHFA && NumMembers > 1) {
67406c3fb27SDimitry Andric // Homogeneous aggregates passed in registers will have their elements split
67506c3fb27SDimitry Andric // and stored 16-bytes apart regardless of size (they're notionally in qN,
67606c3fb27SDimitry Andric // qN+1, ...). We reload and store into a temporary local variable
67706c3fb27SDimitry Andric // contiguously.
67806c3fb27SDimitry Andric assert(!IsIndirect && "Homogeneous aggregates should be passed directly");
67906c3fb27SDimitry Andric auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0));
68006c3fb27SDimitry Andric llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0));
68106c3fb27SDimitry Andric llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers);
68206c3fb27SDimitry Andric Address Tmp = CGF.CreateTempAlloca(HFATy,
68306c3fb27SDimitry Andric std::max(TyAlign, BaseTyInfo.Align));
68406c3fb27SDimitry Andric
68506c3fb27SDimitry Andric // On big-endian platforms, the value will be right-aligned in its slot.
68606c3fb27SDimitry Andric int Offset = 0;
68706c3fb27SDimitry Andric if (CGF.CGM.getDataLayout().isBigEndian() &&
68806c3fb27SDimitry Andric BaseTyInfo.Width.getQuantity() < 16)
68906c3fb27SDimitry Andric Offset = 16 - BaseTyInfo.Width.getQuantity();
69006c3fb27SDimitry Andric
69106c3fb27SDimitry Andric for (unsigned i = 0; i < NumMembers; ++i) {
69206c3fb27SDimitry Andric CharUnits BaseOffset = CharUnits::fromQuantity(16 * i + Offset);
69306c3fb27SDimitry Andric Address LoadAddr =
69406c3fb27SDimitry Andric CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, BaseOffset);
69506c3fb27SDimitry Andric LoadAddr = LoadAddr.withElementType(BaseTy);
69606c3fb27SDimitry Andric
69706c3fb27SDimitry Andric Address StoreAddr = CGF.Builder.CreateConstArrayGEP(Tmp, i);
69806c3fb27SDimitry Andric
69906c3fb27SDimitry Andric llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr);
70006c3fb27SDimitry Andric CGF.Builder.CreateStore(Elem, StoreAddr);
70106c3fb27SDimitry Andric }
70206c3fb27SDimitry Andric
70306c3fb27SDimitry Andric RegAddr = Tmp.withElementType(MemTy);
70406c3fb27SDimitry Andric } else {
70506c3fb27SDimitry Andric // Otherwise the object is contiguous in memory.
70606c3fb27SDimitry Andric
70706c3fb27SDimitry Andric // It might be right-aligned in its slot.
70806c3fb27SDimitry Andric CharUnits SlotSize = BaseAddr.getAlignment();
70906c3fb27SDimitry Andric if (CGF.CGM.getDataLayout().isBigEndian() && !IsIndirect &&
71006c3fb27SDimitry Andric (IsHFA || !isAggregateTypeForABI(Ty)) &&
71106c3fb27SDimitry Andric TySize < SlotSize) {
71206c3fb27SDimitry Andric CharUnits Offset = SlotSize - TySize;
71306c3fb27SDimitry Andric BaseAddr = CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, Offset);
71406c3fb27SDimitry Andric }
71506c3fb27SDimitry Andric
71606c3fb27SDimitry Andric RegAddr = BaseAddr.withElementType(MemTy);
71706c3fb27SDimitry Andric }
71806c3fb27SDimitry Andric
71906c3fb27SDimitry Andric CGF.EmitBranch(ContBlock);
72006c3fb27SDimitry Andric
72106c3fb27SDimitry Andric //=======================================
72206c3fb27SDimitry Andric // Argument was on the stack
72306c3fb27SDimitry Andric //=======================================
72406c3fb27SDimitry Andric CGF.EmitBlock(OnStackBlock);
72506c3fb27SDimitry Andric
72606c3fb27SDimitry Andric Address stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p");
72706c3fb27SDimitry Andric llvm::Value *OnStackPtr = CGF.Builder.CreateLoad(stack_p, "stack");
72806c3fb27SDimitry Andric
72906c3fb27SDimitry Andric // Again, stack arguments may need realignment. In this case both integer and
73006c3fb27SDimitry Andric // floating-point ones might be affected.
73106c3fb27SDimitry Andric if (!IsIndirect && TyAlign.getQuantity() > 8) {
7320fca6ea1SDimitry Andric OnStackPtr = emitRoundPointerUpToAlignment(CGF, OnStackPtr, TyAlign);
73306c3fb27SDimitry Andric }
73406c3fb27SDimitry Andric Address OnStackAddr = Address(OnStackPtr, CGF.Int8Ty,
73506c3fb27SDimitry Andric std::max(CharUnits::fromQuantity(8), TyAlign));
73606c3fb27SDimitry Andric
73706c3fb27SDimitry Andric // All stack slots are multiples of 8 bytes.
73806c3fb27SDimitry Andric CharUnits StackSlotSize = CharUnits::fromQuantity(8);
73906c3fb27SDimitry Andric CharUnits StackSize;
74006c3fb27SDimitry Andric if (IsIndirect)
74106c3fb27SDimitry Andric StackSize = StackSlotSize;
74206c3fb27SDimitry Andric else
74306c3fb27SDimitry Andric StackSize = TySize.alignTo(StackSlotSize);
74406c3fb27SDimitry Andric
74506c3fb27SDimitry Andric llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize);
74606c3fb27SDimitry Andric llvm::Value *NewStack = CGF.Builder.CreateInBoundsGEP(
74706c3fb27SDimitry Andric CGF.Int8Ty, OnStackPtr, StackSizeC, "new_stack");
74806c3fb27SDimitry Andric
74906c3fb27SDimitry Andric // Write the new value of __stack for the next call to va_arg
75006c3fb27SDimitry Andric CGF.Builder.CreateStore(NewStack, stack_p);
75106c3fb27SDimitry Andric
75206c3fb27SDimitry Andric if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) &&
75306c3fb27SDimitry Andric TySize < StackSlotSize) {
75406c3fb27SDimitry Andric CharUnits Offset = StackSlotSize - TySize;
75506c3fb27SDimitry Andric OnStackAddr = CGF.Builder.CreateConstInBoundsByteGEP(OnStackAddr, Offset);
75606c3fb27SDimitry Andric }
75706c3fb27SDimitry Andric
75806c3fb27SDimitry Andric OnStackAddr = OnStackAddr.withElementType(MemTy);
75906c3fb27SDimitry Andric
76006c3fb27SDimitry Andric CGF.EmitBranch(ContBlock);
76106c3fb27SDimitry Andric
76206c3fb27SDimitry Andric //=======================================
76306c3fb27SDimitry Andric // Tidy up
76406c3fb27SDimitry Andric //=======================================
76506c3fb27SDimitry Andric CGF.EmitBlock(ContBlock);
76606c3fb27SDimitry Andric
76706c3fb27SDimitry Andric Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, OnStackAddr,
76806c3fb27SDimitry Andric OnStackBlock, "vaargs.addr");
76906c3fb27SDimitry Andric
77006c3fb27SDimitry Andric if (IsIndirect)
7710fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(
7720fca6ea1SDimitry Andric CGF.MakeAddrLValue(
7730fca6ea1SDimitry Andric Address(CGF.Builder.CreateLoad(ResAddr, "vaarg.addr"), ElementTy,
7740fca6ea1SDimitry Andric TyAlign),
7750fca6ea1SDimitry Andric Ty),
7760fca6ea1SDimitry Andric Slot);
77706c3fb27SDimitry Andric
7780fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot);
77906c3fb27SDimitry Andric }
78006c3fb27SDimitry Andric
EmitDarwinVAArg(Address VAListAddr,QualType Ty,CodeGenFunction & CGF,AggValueSlot Slot) const7810fca6ea1SDimitry Andric RValue AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty,
7820fca6ea1SDimitry Andric CodeGenFunction &CGF,
7830fca6ea1SDimitry Andric AggValueSlot Slot) const {
78406c3fb27SDimitry Andric // The backend's lowering doesn't support va_arg for aggregates or
78506c3fb27SDimitry Andric // illegal vector types. Lower VAArg here for these cases and use
78606c3fb27SDimitry Andric // the LLVM va_arg instruction for everything else.
78706c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty))
7880fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(
7890fca6ea1SDimitry Andric CGF.MakeAddrLValue(
7900fca6ea1SDimitry Andric EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty),
7910fca6ea1SDimitry Andric Slot);
79206c3fb27SDimitry Andric
79306c3fb27SDimitry Andric uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8;
79406c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(PointerSize);
79506c3fb27SDimitry Andric
79606c3fb27SDimitry Andric // Empty records are ignored for parameter passing purposes.
79706c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true))
7980fca6ea1SDimitry Andric return Slot.asRValue();
79906c3fb27SDimitry Andric
80006c3fb27SDimitry Andric // The size of the actual thing passed, which might end up just
80106c3fb27SDimitry Andric // being a pointer for indirect types.
80206c3fb27SDimitry Andric auto TyInfo = getContext().getTypeInfoInChars(Ty);
80306c3fb27SDimitry Andric
80406c3fb27SDimitry Andric // Arguments bigger than 16 bytes which aren't homogeneous
80506c3fb27SDimitry Andric // aggregates should be passed indirectly.
80606c3fb27SDimitry Andric bool IsIndirect = false;
80706c3fb27SDimitry Andric if (TyInfo.Width.getQuantity() > 16) {
80806c3fb27SDimitry Andric const Type *Base = nullptr;
80906c3fb27SDimitry Andric uint64_t Members = 0;
81006c3fb27SDimitry Andric IsIndirect = !isHomogeneousAggregate(Ty, Base, Members);
81106c3fb27SDimitry Andric }
81206c3fb27SDimitry Andric
8130fca6ea1SDimitry Andric return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo, SlotSize,
8140fca6ea1SDimitry Andric /*AllowHigherAlign*/ true, Slot);
81506c3fb27SDimitry Andric }
81606c3fb27SDimitry Andric
EmitMSVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const8170fca6ea1SDimitry Andric RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
8180fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const {
81906c3fb27SDimitry Andric bool IsIndirect = false;
82006c3fb27SDimitry Andric
82106c3fb27SDimitry Andric // Composites larger than 16 bytes are passed by reference.
82206c3fb27SDimitry Andric if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
82306c3fb27SDimitry Andric IsIndirect = true;
82406c3fb27SDimitry Andric
82506c3fb27SDimitry Andric return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
82606c3fb27SDimitry Andric CGF.getContext().getTypeInfoInChars(Ty),
82706c3fb27SDimitry Andric CharUnits::fromQuantity(8),
8280fca6ea1SDimitry Andric /*allowHigherAlign*/ false, Slot);
8290fca6ea1SDimitry Andric }
8300fca6ea1SDimitry Andric
isStreamingCompatible(const FunctionDecl * F)8310fca6ea1SDimitry Andric static bool isStreamingCompatible(const FunctionDecl *F) {
8320fca6ea1SDimitry Andric if (const auto *T = F->getType()->getAs<FunctionProtoType>())
8330fca6ea1SDimitry Andric return T->getAArch64SMEAttributes() &
8340fca6ea1SDimitry Andric FunctionType::SME_PStateSMCompatibleMask;
8350fca6ea1SDimitry Andric return false;
8360fca6ea1SDimitry Andric }
8370fca6ea1SDimitry Andric
8380fca6ea1SDimitry Andric // Report an error if an argument or return value of type Ty would need to be
8390fca6ea1SDimitry Andric // passed in a floating-point register.
diagnoseIfNeedsFPReg(DiagnosticsEngine & Diags,const StringRef ABIName,const AArch64ABIInfo & ABIInfo,const QualType & Ty,const NamedDecl * D,SourceLocation loc)8400fca6ea1SDimitry Andric static void diagnoseIfNeedsFPReg(DiagnosticsEngine &Diags,
8410fca6ea1SDimitry Andric const StringRef ABIName,
8420fca6ea1SDimitry Andric const AArch64ABIInfo &ABIInfo,
843*62987288SDimitry Andric const QualType &Ty, const NamedDecl *D,
844*62987288SDimitry Andric SourceLocation loc) {
8450fca6ea1SDimitry Andric const Type *HABase = nullptr;
8460fca6ea1SDimitry Andric uint64_t HAMembers = 0;
8470fca6ea1SDimitry Andric if (Ty->isFloatingType() || Ty->isVectorType() ||
8480fca6ea1SDimitry Andric ABIInfo.isHomogeneousAggregate(Ty, HABase, HAMembers)) {
849*62987288SDimitry Andric Diags.Report(loc, diag::err_target_unsupported_type_for_abi)
8500fca6ea1SDimitry Andric << D->getDeclName() << Ty << ABIName;
8510fca6ea1SDimitry Andric }
8520fca6ea1SDimitry Andric }
8530fca6ea1SDimitry Andric
8540fca6ea1SDimitry Andric // If we are using a hard-float ABI, but do not have floating point registers,
8550fca6ea1SDimitry Andric // then report an error for any function arguments or returns which would be
8560fca6ea1SDimitry Andric // passed in floating-pint registers.
checkFunctionABI(CodeGenModule & CGM,const FunctionDecl * FuncDecl) const8570fca6ea1SDimitry Andric void AArch64TargetCodeGenInfo::checkFunctionABI(
8580fca6ea1SDimitry Andric CodeGenModule &CGM, const FunctionDecl *FuncDecl) const {
8590fca6ea1SDimitry Andric const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
8600fca6ea1SDimitry Andric const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
8610fca6ea1SDimitry Andric
8620fca6ea1SDimitry Andric if (!TI.hasFeature("fp") && !ABIInfo.isSoftFloat()) {
8630fca6ea1SDimitry Andric diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo,
864*62987288SDimitry Andric FuncDecl->getReturnType(), FuncDecl,
865*62987288SDimitry Andric FuncDecl->getLocation());
8660fca6ea1SDimitry Andric for (ParmVarDecl *PVD : FuncDecl->parameters()) {
8670fca6ea1SDimitry Andric diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, PVD->getType(),
868*62987288SDimitry Andric PVD, FuncDecl->getLocation());
8690fca6ea1SDimitry Andric }
8700fca6ea1SDimitry Andric }
8710fca6ea1SDimitry Andric }
8720fca6ea1SDimitry Andric
checkFunctionCallABIStreaming(CodeGenModule & CGM,SourceLocation CallLoc,const FunctionDecl * Caller,const FunctionDecl * Callee) const8730fca6ea1SDimitry Andric void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming(
8740fca6ea1SDimitry Andric CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
8750fca6ea1SDimitry Andric const FunctionDecl *Callee) const {
8760fca6ea1SDimitry Andric if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>())
8770fca6ea1SDimitry Andric return;
8780fca6ea1SDimitry Andric
8790fca6ea1SDimitry Andric bool CallerIsStreaming =
8800fca6ea1SDimitry Andric IsArmStreamingFunction(Caller, /*IncludeLocallyStreaming=*/true);
8810fca6ea1SDimitry Andric bool CalleeIsStreaming =
8820fca6ea1SDimitry Andric IsArmStreamingFunction(Callee, /*IncludeLocallyStreaming=*/true);
8830fca6ea1SDimitry Andric bool CallerIsStreamingCompatible = isStreamingCompatible(Caller);
8840fca6ea1SDimitry Andric bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee);
8850fca6ea1SDimitry Andric
8860fca6ea1SDimitry Andric if (!CalleeIsStreamingCompatible &&
8870fca6ea1SDimitry Andric (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible))
88852418fc2SDimitry Andric CGM.getDiags().Report(
88952418fc2SDimitry Andric CallLoc, CalleeIsStreaming
89052418fc2SDimitry Andric ? diag::err_function_always_inline_attribute_mismatch
89152418fc2SDimitry Andric : diag::warn_function_always_inline_attribute_mismatch)
8920fca6ea1SDimitry Andric << Caller->getDeclName() << Callee->getDeclName() << "streaming";
8930fca6ea1SDimitry Andric if (auto *NewAttr = Callee->getAttr<ArmNewAttr>())
8940fca6ea1SDimitry Andric if (NewAttr->isNewZA())
8950fca6ea1SDimitry Andric CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za)
8960fca6ea1SDimitry Andric << Callee->getDeclName();
8970fca6ea1SDimitry Andric }
8980fca6ea1SDimitry Andric
8990fca6ea1SDimitry Andric // If the target does not have floating-point registers, but we are using a
9000fca6ea1SDimitry Andric // hard-float ABI, there is no way to pass floating-point, vector or HFA values
9010fca6ea1SDimitry Andric // to functions, so we report an error.
checkFunctionCallABISoftFloat(CodeGenModule & CGM,SourceLocation CallLoc,const FunctionDecl * Caller,const FunctionDecl * Callee,const CallArgList & Args,QualType ReturnType) const9020fca6ea1SDimitry Andric void AArch64TargetCodeGenInfo::checkFunctionCallABISoftFloat(
9030fca6ea1SDimitry Andric CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller,
9040fca6ea1SDimitry Andric const FunctionDecl *Callee, const CallArgList &Args,
9050fca6ea1SDimitry Andric QualType ReturnType) const {
9060fca6ea1SDimitry Andric const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>();
9070fca6ea1SDimitry Andric const TargetInfo &TI = ABIInfo.getContext().getTargetInfo();
9080fca6ea1SDimitry Andric
9090fca6ea1SDimitry Andric if (!Caller || TI.hasFeature("fp") || ABIInfo.isSoftFloat())
9100fca6ea1SDimitry Andric return;
9110fca6ea1SDimitry Andric
9120fca6ea1SDimitry Andric diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, ReturnType,
913*62987288SDimitry Andric Callee ? Callee : Caller, CallLoc);
9140fca6ea1SDimitry Andric
9150fca6ea1SDimitry Andric for (const CallArg &Arg : Args)
9160fca6ea1SDimitry Andric diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, Arg.getType(),
917*62987288SDimitry Andric Callee ? Callee : Caller, CallLoc);
9180fca6ea1SDimitry Andric }
9190fca6ea1SDimitry Andric
checkFunctionCallABI(CodeGenModule & CGM,SourceLocation CallLoc,const FunctionDecl * Caller,const FunctionDecl * Callee,const CallArgList & Args,QualType ReturnType) const9200fca6ea1SDimitry Andric void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM,
9210fca6ea1SDimitry Andric SourceLocation CallLoc,
9220fca6ea1SDimitry Andric const FunctionDecl *Caller,
9230fca6ea1SDimitry Andric const FunctionDecl *Callee,
9240fca6ea1SDimitry Andric const CallArgList &Args,
9250fca6ea1SDimitry Andric QualType ReturnType) const {
9260fca6ea1SDimitry Andric checkFunctionCallABIStreaming(CGM, CallLoc, Caller, Callee);
9270fca6ea1SDimitry Andric checkFunctionCallABISoftFloat(CGM, CallLoc, Caller, Callee, Args, ReturnType);
9280fca6ea1SDimitry Andric }
9290fca6ea1SDimitry Andric
appendAttributeMangling(TargetClonesAttr * Attr,unsigned Index,raw_ostream & Out) const9300fca6ea1SDimitry Andric void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
9310fca6ea1SDimitry Andric unsigned Index,
9320fca6ea1SDimitry Andric raw_ostream &Out) const {
9330fca6ea1SDimitry Andric appendAttributeMangling(Attr->getFeatureStr(Index), Out);
9340fca6ea1SDimitry Andric }
9350fca6ea1SDimitry Andric
appendAttributeMangling(StringRef AttrStr,raw_ostream & Out) const9360fca6ea1SDimitry Andric void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
9370fca6ea1SDimitry Andric raw_ostream &Out) const {
9380fca6ea1SDimitry Andric if (AttrStr == "default") {
9390fca6ea1SDimitry Andric Out << ".default";
9400fca6ea1SDimitry Andric return;
9410fca6ea1SDimitry Andric }
9420fca6ea1SDimitry Andric
9430fca6ea1SDimitry Andric Out << "._";
9440fca6ea1SDimitry Andric SmallVector<StringRef, 8> Features;
9450fca6ea1SDimitry Andric AttrStr.split(Features, "+");
9460fca6ea1SDimitry Andric for (auto &Feat : Features)
9470fca6ea1SDimitry Andric Feat = Feat.trim();
9480fca6ea1SDimitry Andric
9490fca6ea1SDimitry Andric llvm::sort(Features, [](const StringRef LHS, const StringRef RHS) {
9500fca6ea1SDimitry Andric return LHS.compare(RHS) < 0;
9510fca6ea1SDimitry Andric });
9520fca6ea1SDimitry Andric
9530fca6ea1SDimitry Andric llvm::SmallDenseSet<StringRef, 8> UniqueFeats;
9540fca6ea1SDimitry Andric for (auto &Feat : Features)
9550fca6ea1SDimitry Andric if (auto Ext = llvm::AArch64::parseFMVExtension(Feat))
9560fca6ea1SDimitry Andric if (UniqueFeats.insert(Ext->Name).second)
9570fca6ea1SDimitry Andric Out << 'M' << Ext->Name;
95806c3fb27SDimitry Andric }
95906c3fb27SDimitry Andric
96006c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createAArch64TargetCodeGenInfo(CodeGenModule & CGM,AArch64ABIKind Kind)96106c3fb27SDimitry Andric CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
96206c3fb27SDimitry Andric AArch64ABIKind Kind) {
96306c3fb27SDimitry Andric return std::make_unique<AArch64TargetCodeGenInfo>(CGM.getTypes(), Kind);
96406c3fb27SDimitry Andric }
96506c3fb27SDimitry Andric
96606c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
createWindowsAArch64TargetCodeGenInfo(CodeGenModule & CGM,AArch64ABIKind K)96706c3fb27SDimitry Andric CodeGen::createWindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM,
96806c3fb27SDimitry Andric AArch64ABIKind K) {
96906c3fb27SDimitry Andric return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM.getTypes(), K);
97006c3fb27SDimitry Andric }
971