1992cb984SSergei Barannikov //===- AArch64.cpp --------------------------------------------------------===// 2992cb984SSergei Barannikov // 3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information. 5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6992cb984SSergei Barannikov // 7992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 8992cb984SSergei Barannikov 9992cb984SSergei Barannikov #include "ABIInfoImpl.h" 10992cb984SSergei Barannikov #include "TargetInfo.h" 116a6fcbffSSander de Smalen #include "clang/AST/Decl.h" 12b47f63d3SSam Tebbs #include "clang/Basic/DiagnosticFrontend.h" 13b42b7c8aSAlexandros Lamprineas #include "llvm/TargetParser/AArch64TargetParser.h" 14992cb984SSergei Barannikov 15992cb984SSergei Barannikov using namespace clang; 16992cb984SSergei Barannikov using namespace clang::CodeGen; 17992cb984SSergei Barannikov 18992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 19992cb984SSergei Barannikov // AArch64 ABI Implementation 20992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 21992cb984SSergei Barannikov 22992cb984SSergei Barannikov namespace { 23992cb984SSergei Barannikov 24992cb984SSergei Barannikov class AArch64ABIInfo : public ABIInfo { 25992cb984SSergei Barannikov AArch64ABIKind Kind; 26992cb984SSergei Barannikov 27992cb984SSergei Barannikov public: 28992cb984SSergei Barannikov AArch64ABIInfo(CodeGenTypes &CGT, AArch64ABIKind Kind) 29992cb984SSergei Barannikov : ABIInfo(CGT), Kind(Kind) {} 30992cb984SSergei Barannikov 31ef395a49Sostannard bool isSoftFloat() const { return Kind == AArch64ABIKind::AAPCSSoft; } 32ef395a49Sostannard 33992cb984SSergei Barannikov private: 34992cb984SSergei Barannikov AArch64ABIKind getABIKind() const { return Kind; } 35992cb984SSergei Barannikov bool isDarwinPCS() const { return Kind == AArch64ABIKind::DarwinPCS; } 36992cb984SSergei Barannikov 3753f7f8ecSMomchil Velikov ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadicFn) const; 3853f7f8ecSMomchil Velikov ABIArgInfo classifyArgumentType(QualType RetTy, bool IsVariadicFn, 3953f7f8ecSMomchil Velikov bool IsNamedArg, unsigned CallingConvention, 4053f7f8ecSMomchil Velikov unsigned &NSRN, unsigned &NPRN) const; 4153f7f8ecSMomchil Velikov llvm::Type *convertFixedToScalableVectorType(const VectorType *VT) const; 4253f7f8ecSMomchil Velikov ABIArgInfo coerceIllegalVector(QualType Ty, unsigned &NSRN, 4353f7f8ecSMomchil Velikov unsigned &NPRN) const; 4453f7f8ecSMomchil Velikov ABIArgInfo coerceAndExpandPureScalableAggregate( 4553f7f8ecSMomchil Velikov QualType Ty, bool IsNamedArg, unsigned NVec, unsigned NPred, 4653f7f8ecSMomchil Velikov const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq, unsigned &NSRN, 4753f7f8ecSMomchil Velikov unsigned &NPRN) const; 48992cb984SSergei Barannikov bool isHomogeneousAggregateBaseType(QualType Ty) const override; 49992cb984SSergei Barannikov bool isHomogeneousAggregateSmallEnough(const Type *Ty, 50992cb984SSergei Barannikov uint64_t Members) const override; 51992cb984SSergei Barannikov bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; 52992cb984SSergei Barannikov 53992cb984SSergei Barannikov bool isIllegalVectorType(QualType Ty) const; 54992cb984SSergei Barannikov 55f70ab7d9SMomchil Velikov bool passAsAggregateType(QualType Ty) const; 5653f7f8ecSMomchil Velikov bool passAsPureScalableType(QualType Ty, unsigned &NV, unsigned &NP, 5753f7f8ecSMomchil Velikov SmallVectorImpl<llvm::Type *> &CoerceToSeq) const; 5853f7f8ecSMomchil Velikov 5953f7f8ecSMomchil Velikov void flattenType(llvm::Type *Ty, 6053f7f8ecSMomchil Velikov SmallVectorImpl<llvm::Type *> &Flattened) const; 6153f7f8ecSMomchil Velikov 62992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override { 63992cb984SSergei Barannikov if (!::classifyReturnType(getCXXABI(), FI, *this)) 64992cb984SSergei Barannikov FI.getReturnInfo() = 65992cb984SSergei Barannikov classifyReturnType(FI.getReturnType(), FI.isVariadic()); 66992cb984SSergei Barannikov 6753f7f8ecSMomchil Velikov unsigned ArgNo = 0; 6853f7f8ecSMomchil Velikov unsigned NSRN = 0, NPRN = 0; 6953f7f8ecSMomchil Velikov for (auto &it : FI.arguments()) { 7053f7f8ecSMomchil Velikov const bool IsNamedArg = 7153f7f8ecSMomchil Velikov !FI.isVariadic() || ArgNo < FI.getRequiredArgs().getNumRequiredArgs(); 7253f7f8ecSMomchil Velikov ++ArgNo; 7353f7f8ecSMomchil Velikov it.info = classifyArgumentType(it.type, FI.isVariadic(), IsNamedArg, 7453f7f8ecSMomchil Velikov FI.getCallingConvention(), NSRN, NPRN); 7553f7f8ecSMomchil Velikov } 76992cb984SSergei Barannikov } 77992cb984SSergei Barannikov 786d973b45SMariya Podchishchaeva RValue EmitDarwinVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF, 796d973b45SMariya Podchishchaeva AggValueSlot Slot) const; 80992cb984SSergei Barannikov 816d973b45SMariya Podchishchaeva RValue EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF, 826d973b45SMariya Podchishchaeva AArch64ABIKind Kind, AggValueSlot Slot) const; 83992cb984SSergei Barannikov 846d973b45SMariya Podchishchaeva RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 856d973b45SMariya Podchishchaeva AggValueSlot Slot) const override { 86992cb984SSergei Barannikov llvm::Type *BaseTy = CGF.ConvertType(Ty); 87992cb984SSergei Barannikov if (isa<llvm::ScalableVectorType>(BaseTy)) 88992cb984SSergei Barannikov llvm::report_fatal_error("Passing SVE types to variadic functions is " 89992cb984SSergei Barannikov "currently not supported"); 90992cb984SSergei Barannikov 916d973b45SMariya Podchishchaeva return Kind == AArch64ABIKind::Win64 926d973b45SMariya Podchishchaeva ? EmitMSVAArg(CGF, VAListAddr, Ty, Slot) 936d973b45SMariya Podchishchaeva : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF, Slot) 946d973b45SMariya Podchishchaeva : EmitAAPCSVAArg(VAListAddr, Ty, CGF, Kind, Slot); 95992cb984SSergei Barannikov } 96992cb984SSergei Barannikov 976d973b45SMariya Podchishchaeva RValue EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 986d973b45SMariya Podchishchaeva AggValueSlot Slot) const override; 99992cb984SSergei Barannikov 100992cb984SSergei Barannikov bool allowBFloatArgsAndRet() const override { 101992cb984SSergei Barannikov return getTarget().hasBFloat16Type(); 102992cb984SSergei Barannikov } 103b42b7c8aSAlexandros Lamprineas 104b42b7c8aSAlexandros Lamprineas using ABIInfo::appendAttributeMangling; 105b42b7c8aSAlexandros Lamprineas void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index, 106b42b7c8aSAlexandros Lamprineas raw_ostream &Out) const override; 107b42b7c8aSAlexandros Lamprineas void appendAttributeMangling(StringRef AttrStr, 108b42b7c8aSAlexandros Lamprineas raw_ostream &Out) const override; 109992cb984SSergei Barannikov }; 110992cb984SSergei Barannikov 111992cb984SSergei Barannikov class AArch64SwiftABIInfo : public SwiftABIInfo { 112992cb984SSergei Barannikov public: 113992cb984SSergei Barannikov explicit AArch64SwiftABIInfo(CodeGenTypes &CGT) 114992cb984SSergei Barannikov : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {} 115992cb984SSergei Barannikov 116992cb984SSergei Barannikov bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, 117992cb984SSergei Barannikov unsigned NumElts) const override; 118992cb984SSergei Barannikov }; 119992cb984SSergei Barannikov 120992cb984SSergei Barannikov class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { 121992cb984SSergei Barannikov public: 122992cb984SSergei Barannikov AArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind Kind) 123992cb984SSergei Barannikov : TargetCodeGenInfo(std::make_unique<AArch64ABIInfo>(CGT, Kind)) { 124992cb984SSergei Barannikov SwiftInfo = std::make_unique<AArch64SwiftABIInfo>(CGT); 125992cb984SSergei Barannikov } 126992cb984SSergei Barannikov 127992cb984SSergei Barannikov StringRef getARCRetainAutoreleasedReturnValueMarker() const override { 128992cb984SSergei Barannikov return "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue"; 129992cb984SSergei Barannikov } 130992cb984SSergei Barannikov 131992cb984SSergei Barannikov int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 132992cb984SSergei Barannikov return 31; 133992cb984SSergei Barannikov } 134992cb984SSergei Barannikov 135992cb984SSergei Barannikov bool doesReturnSlotInterfereWithArgs() const override { return false; } 136992cb984SSergei Barannikov 137992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 138992cb984SSergei Barannikov CodeGen::CodeGenModule &CGM) const override { 139992cb984SSergei Barannikov const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 140992cb984SSergei Barannikov if (!FD) 141992cb984SSergei Barannikov return; 142992cb984SSergei Barannikov 1431782810bSDaniel Kiss TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts()); 144992cb984SSergei Barannikov 1451782810bSDaniel Kiss if (const auto *TA = FD->getAttr<TargetAttr>()) { 146992cb984SSergei Barannikov ParsedTargetAttr Attr = 147992cb984SSergei Barannikov CGM.getTarget().parseTargetAttr(TA->getFeaturesStr()); 1481782810bSDaniel Kiss if (!Attr.BranchProtection.empty()) { 149992cb984SSergei Barannikov StringRef Error; 150992cb984SSergei Barannikov (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection, 151992cb984SSergei Barannikov Attr.CPU, BPI, Error); 152992cb984SSergei Barannikov assert(Error.empty()); 1534b2daeccSDaniel Kiss } 1541782810bSDaniel Kiss } 1551782810bSDaniel Kiss auto *Fn = cast<llvm::Function>(GV); 156f34a1654SDaniel Kiss setBranchProtectionFnAttributes(BPI, *Fn); 157992cb984SSergei Barannikov } 158992cb984SSergei Barannikov 159992cb984SSergei Barannikov bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, 160992cb984SSergei Barannikov llvm::Type *Ty) const override { 161992cb984SSergei Barannikov if (CGF.getTarget().hasFeature("ls64")) { 162992cb984SSergei Barannikov auto *ST = dyn_cast<llvm::StructType>(Ty); 163992cb984SSergei Barannikov if (ST && ST->getNumElements() == 1) { 164992cb984SSergei Barannikov auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0)); 165992cb984SSergei Barannikov if (AT && AT->getNumElements() == 8 && 166992cb984SSergei Barannikov AT->getElementType()->isIntegerTy(64)) 167992cb984SSergei Barannikov return true; 168992cb984SSergei Barannikov } 169992cb984SSergei Barannikov } 170992cb984SSergei Barannikov return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty); 171992cb984SSergei Barannikov } 172b47f63d3SSam Tebbs 173ef395a49Sostannard void checkFunctionABI(CodeGenModule &CGM, 174ef395a49Sostannard const FunctionDecl *Decl) const override; 175ef395a49Sostannard 176b47f63d3SSam Tebbs void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc, 177b47f63d3SSam Tebbs const FunctionDecl *Caller, 1781fd196c8Sostannard const FunctionDecl *Callee, const CallArgList &Args, 1791fd196c8Sostannard QualType ReturnType) const override; 1801fd196c8Sostannard 181db6f627fSBenjamin Maxwell bool wouldInliningViolateFunctionCallABI( 182db6f627fSBenjamin Maxwell const FunctionDecl *Caller, const FunctionDecl *Callee) const override; 183db6f627fSBenjamin Maxwell 1841fd196c8Sostannard private: 1851fd196c8Sostannard // Diagnose calls between functions with incompatible Streaming SVE 1861fd196c8Sostannard // attributes. 1871fd196c8Sostannard void checkFunctionCallABIStreaming(CodeGenModule &CGM, SourceLocation CallLoc, 1881fd196c8Sostannard const FunctionDecl *Caller, 1891fd196c8Sostannard const FunctionDecl *Callee) const; 1901fd196c8Sostannard // Diagnose calls which must pass arguments in floating-point registers when 1911fd196c8Sostannard // the selected target does not have floating-point registers. 1921fd196c8Sostannard void checkFunctionCallABISoftFloat(CodeGenModule &CGM, SourceLocation CallLoc, 1931fd196c8Sostannard const FunctionDecl *Caller, 194b47f63d3SSam Tebbs const FunctionDecl *Callee, 1951fd196c8Sostannard const CallArgList &Args, 1961fd196c8Sostannard QualType ReturnType) const; 197992cb984SSergei Barannikov }; 198992cb984SSergei Barannikov 199992cb984SSergei Barannikov class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo { 200992cb984SSergei Barannikov public: 201992cb984SSergei Barannikov WindowsAArch64TargetCodeGenInfo(CodeGenTypes &CGT, AArch64ABIKind K) 202992cb984SSergei Barannikov : AArch64TargetCodeGenInfo(CGT, K) {} 203992cb984SSergei Barannikov 204992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 205992cb984SSergei Barannikov CodeGen::CodeGenModule &CGM) const override; 206992cb984SSergei Barannikov 207992cb984SSergei Barannikov void getDependentLibraryOption(llvm::StringRef Lib, 208992cb984SSergei Barannikov llvm::SmallString<24> &Opt) const override { 209992cb984SSergei Barannikov Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); 210992cb984SSergei Barannikov } 211992cb984SSergei Barannikov 212992cb984SSergei Barannikov void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, 213992cb984SSergei Barannikov llvm::SmallString<32> &Opt) const override { 214992cb984SSergei Barannikov Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; 215992cb984SSergei Barannikov } 216992cb984SSergei Barannikov }; 217992cb984SSergei Barannikov 218992cb984SSergei Barannikov void WindowsAArch64TargetCodeGenInfo::setTargetAttributes( 219992cb984SSergei Barannikov const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { 220992cb984SSergei Barannikov AArch64TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); 221992cb984SSergei Barannikov if (GV->isDeclaration()) 222992cb984SSergei Barannikov return; 223992cb984SSergei Barannikov addStackProbeTargetAttributes(D, GV, CGM); 224992cb984SSergei Barannikov } 225992cb984SSergei Barannikov } 226992cb984SSergei Barannikov 22753f7f8ecSMomchil Velikov llvm::Type * 22853f7f8ecSMomchil Velikov AArch64ABIInfo::convertFixedToScalableVectorType(const VectorType *VT) const { 22953f7f8ecSMomchil Velikov assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); 23053f7f8ecSMomchil Velikov 23153f7f8ecSMomchil Velikov if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { 23253f7f8ecSMomchil Velikov assert(VT->getElementType()->castAs<BuiltinType>()->getKind() == 23353f7f8ecSMomchil Velikov BuiltinType::UChar && 23453f7f8ecSMomchil Velikov "unexpected builtin type for SVE predicate!"); 23553f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get(llvm::Type::getInt1Ty(getVMContext()), 23653f7f8ecSMomchil Velikov 16); 23753f7f8ecSMomchil Velikov } 23853f7f8ecSMomchil Velikov 23953f7f8ecSMomchil Velikov if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { 24053f7f8ecSMomchil Velikov const auto *BT = VT->getElementType()->castAs<BuiltinType>(); 24153f7f8ecSMomchil Velikov switch (BT->getKind()) { 24253f7f8ecSMomchil Velikov default: 24353f7f8ecSMomchil Velikov llvm_unreachable("unexpected builtin type for SVE vector!"); 24453f7f8ecSMomchil Velikov 24553f7f8ecSMomchil Velikov case BuiltinType::SChar: 24653f7f8ecSMomchil Velikov case BuiltinType::UChar: 247f95a8bdeSMomchil Velikov case BuiltinType::MFloat8: 24853f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 24953f7f8ecSMomchil Velikov llvm::Type::getInt8Ty(getVMContext()), 16); 25053f7f8ecSMomchil Velikov 25153f7f8ecSMomchil Velikov case BuiltinType::Short: 25253f7f8ecSMomchil Velikov case BuiltinType::UShort: 25353f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 25453f7f8ecSMomchil Velikov llvm::Type::getInt16Ty(getVMContext()), 8); 25553f7f8ecSMomchil Velikov 25653f7f8ecSMomchil Velikov case BuiltinType::Int: 25753f7f8ecSMomchil Velikov case BuiltinType::UInt: 25853f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 25953f7f8ecSMomchil Velikov llvm::Type::getInt32Ty(getVMContext()), 4); 26053f7f8ecSMomchil Velikov 26153f7f8ecSMomchil Velikov case BuiltinType::Long: 26253f7f8ecSMomchil Velikov case BuiltinType::ULong: 26353f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 26453f7f8ecSMomchil Velikov llvm::Type::getInt64Ty(getVMContext()), 2); 26553f7f8ecSMomchil Velikov 26653f7f8ecSMomchil Velikov case BuiltinType::Half: 26753f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 26853f7f8ecSMomchil Velikov llvm::Type::getHalfTy(getVMContext()), 8); 26953f7f8ecSMomchil Velikov 27053f7f8ecSMomchil Velikov case BuiltinType::Float: 27153f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 27253f7f8ecSMomchil Velikov llvm::Type::getFloatTy(getVMContext()), 4); 27353f7f8ecSMomchil Velikov 27453f7f8ecSMomchil Velikov case BuiltinType::Double: 27553f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 27653f7f8ecSMomchil Velikov llvm::Type::getDoubleTy(getVMContext()), 2); 27753f7f8ecSMomchil Velikov 27853f7f8ecSMomchil Velikov case BuiltinType::BFloat16: 27953f7f8ecSMomchil Velikov return llvm::ScalableVectorType::get( 28053f7f8ecSMomchil Velikov llvm::Type::getBFloatTy(getVMContext()), 8); 28153f7f8ecSMomchil Velikov } 28253f7f8ecSMomchil Velikov } 28353f7f8ecSMomchil Velikov 28453f7f8ecSMomchil Velikov llvm_unreachable("expected fixed-length SVE vector"); 28553f7f8ecSMomchil Velikov } 28653f7f8ecSMomchil Velikov 28753f7f8ecSMomchil Velikov ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty, unsigned &NSRN, 28853f7f8ecSMomchil Velikov unsigned &NPRN) const { 289992cb984SSergei Barannikov assert(Ty->isVectorType() && "expected vector type!"); 290992cb984SSergei Barannikov 291992cb984SSergei Barannikov const auto *VT = Ty->castAs<VectorType>(); 292ae7b20b5SVlad Serebrennikov if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { 293992cb984SSergei Barannikov assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); 294992cb984SSergei Barannikov assert(VT->getElementType()->castAs<BuiltinType>()->getKind() == 295992cb984SSergei Barannikov BuiltinType::UChar && 296992cb984SSergei Barannikov "unexpected builtin type for SVE predicate!"); 29753f7f8ecSMomchil Velikov NPRN = std::min(NPRN + 1, 4u); 298992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::ScalableVectorType::get( 299992cb984SSergei Barannikov llvm::Type::getInt1Ty(getVMContext()), 16)); 300992cb984SSergei Barannikov } 301992cb984SSergei Barannikov 302ae7b20b5SVlad Serebrennikov if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { 30353f7f8ecSMomchil Velikov NSRN = std::min(NSRN + 1, 8u); 30453f7f8ecSMomchil Velikov return ABIArgInfo::getDirect(convertFixedToScalableVectorType(VT)); 305992cb984SSergei Barannikov } 306992cb984SSergei Barannikov 307992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(Ty); 308992cb984SSergei Barannikov // Android promotes <2 x i8> to i16, not i32 309992cb984SSergei Barannikov if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) { 310992cb984SSergei Barannikov llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); 311992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 312992cb984SSergei Barannikov } 313992cb984SSergei Barannikov if (Size <= 32) { 314992cb984SSergei Barannikov llvm::Type *ResType = llvm::Type::getInt32Ty(getVMContext()); 315992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 316992cb984SSergei Barannikov } 317992cb984SSergei Barannikov if (Size == 64) { 31853f7f8ecSMomchil Velikov NSRN = std::min(NSRN + 1, 8u); 319992cb984SSergei Barannikov auto *ResType = 320992cb984SSergei Barannikov llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 2); 321992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 322992cb984SSergei Barannikov } 323992cb984SSergei Barannikov if (Size == 128) { 32453f7f8ecSMomchil Velikov NSRN = std::min(NSRN + 1, 8u); 325992cb984SSergei Barannikov auto *ResType = 326992cb984SSergei Barannikov llvm::FixedVectorType::get(llvm::Type::getInt32Ty(getVMContext()), 4); 327992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 328992cb984SSergei Barannikov } 32953f7f8ecSMomchil Velikov 330992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 331992cb984SSergei Barannikov } 332992cb984SSergei Barannikov 33353f7f8ecSMomchil Velikov ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate( 33453f7f8ecSMomchil Velikov QualType Ty, bool IsNamedArg, unsigned NVec, unsigned NPred, 33553f7f8ecSMomchil Velikov const SmallVectorImpl<llvm::Type *> &UnpaddedCoerceToSeq, unsigned &NSRN, 33653f7f8ecSMomchil Velikov unsigned &NPRN) const { 33753f7f8ecSMomchil Velikov if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4) 33853f7f8ecSMomchil Velikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 33953f7f8ecSMomchil Velikov NSRN += NVec; 34053f7f8ecSMomchil Velikov NPRN += NPred; 34153f7f8ecSMomchil Velikov 342f70ab7d9SMomchil Velikov // Handle SVE vector tuples. 343f70ab7d9SMomchil Velikov if (Ty->isSVESizelessBuiltinType()) 344f70ab7d9SMomchil Velikov return ABIArgInfo::getDirect(); 345f70ab7d9SMomchil Velikov 34653f7f8ecSMomchil Velikov llvm::Type *UnpaddedCoerceToType = 34753f7f8ecSMomchil Velikov UnpaddedCoerceToSeq.size() == 1 34853f7f8ecSMomchil Velikov ? UnpaddedCoerceToSeq[0] 34953f7f8ecSMomchil Velikov : llvm::StructType::get(CGT.getLLVMContext(), UnpaddedCoerceToSeq, 35053f7f8ecSMomchil Velikov true); 35153f7f8ecSMomchil Velikov 35253f7f8ecSMomchil Velikov SmallVector<llvm::Type *> CoerceToSeq; 35353f7f8ecSMomchil Velikov flattenType(CGT.ConvertType(Ty), CoerceToSeq); 35453f7f8ecSMomchil Velikov auto *CoerceToType = 35553f7f8ecSMomchil Velikov llvm::StructType::get(CGT.getLLVMContext(), CoerceToSeq, false); 35653f7f8ecSMomchil Velikov 35753f7f8ecSMomchil Velikov return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType); 35853f7f8ecSMomchil Velikov } 35953f7f8ecSMomchil Velikov 36053f7f8ecSMomchil Velikov ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, 36153f7f8ecSMomchil Velikov bool IsNamedArg, 36253f7f8ecSMomchil Velikov unsigned CallingConvention, 36353f7f8ecSMomchil Velikov unsigned &NSRN, 36453f7f8ecSMomchil Velikov unsigned &NPRN) const { 365992cb984SSergei Barannikov Ty = useFirstFieldIfTransparentUnion(Ty); 366992cb984SSergei Barannikov 367992cb984SSergei Barannikov // Handle illegal vector types here. 368992cb984SSergei Barannikov if (isIllegalVectorType(Ty)) 36953f7f8ecSMomchil Velikov return coerceIllegalVector(Ty, NSRN, NPRN); 370992cb984SSergei Barannikov 371f70ab7d9SMomchil Velikov if (!passAsAggregateType(Ty)) { 372992cb984SSergei Barannikov // Treat an enum type as its underlying type. 373992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 374992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 375992cb984SSergei Barannikov 376992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) 377992cb984SSergei Barannikov if (EIT->getNumBits() > 128) 378421862f8SLukacma return getNaturalAlignIndirect(Ty, false); 379992cb984SSergei Barannikov 38053f7f8ecSMomchil Velikov if (Ty->isVectorType()) 38153f7f8ecSMomchil Velikov NSRN = std::min(NSRN + 1, 8u); 38253f7f8ecSMomchil Velikov else if (const auto *BT = Ty->getAs<BuiltinType>()) { 38353f7f8ecSMomchil Velikov if (BT->isFloatingPoint()) 38453f7f8ecSMomchil Velikov NSRN = std::min(NSRN + 1, 8u); 38553f7f8ecSMomchil Velikov else { 38653f7f8ecSMomchil Velikov switch (BT->getKind()) { 38753f7f8ecSMomchil Velikov case BuiltinType::SveBool: 38853f7f8ecSMomchil Velikov case BuiltinType::SveCount: 38953f7f8ecSMomchil Velikov NPRN = std::min(NPRN + 1, 4u); 39053f7f8ecSMomchil Velikov break; 39153f7f8ecSMomchil Velikov case BuiltinType::SveBoolx2: 39253f7f8ecSMomchil Velikov NPRN = std::min(NPRN + 2, 4u); 39353f7f8ecSMomchil Velikov break; 39453f7f8ecSMomchil Velikov case BuiltinType::SveBoolx4: 39553f7f8ecSMomchil Velikov NPRN = std::min(NPRN + 4, 4u); 39653f7f8ecSMomchil Velikov break; 39753f7f8ecSMomchil Velikov default: 39853f7f8ecSMomchil Velikov if (BT->isSVESizelessBuiltinType()) 39953f7f8ecSMomchil Velikov NSRN = std::min( 40053f7f8ecSMomchil Velikov NSRN + getContext().getBuiltinVectorTypeInfo(BT).NumVectors, 40153f7f8ecSMomchil Velikov 8u); 40253f7f8ecSMomchil Velikov } 40353f7f8ecSMomchil Velikov } 40453f7f8ecSMomchil Velikov } 40553f7f8ecSMomchil Velikov 406992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(Ty) && isDarwinPCS() 407ea920450SLei Huang ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) 408992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 409992cb984SSergei Barannikov } 410992cb984SSergei Barannikov 411992cb984SSergei Barannikov // Structures with either a non-trivial destructor or a non-trivial 412992cb984SSergei Barannikov // copy constructor are always indirect. 413992cb984SSergei Barannikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 414992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == 415992cb984SSergei Barannikov CGCXXABI::RAA_DirectInMemory); 416992cb984SSergei Barannikov } 417992cb984SSergei Barannikov 418*e9c2e0acSOliver Stannard // Empty records: 419992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(Ty); 420992cb984SSergei Barannikov bool IsEmpty = isEmptyRecord(getContext(), Ty, true); 421f70ab7d9SMomchil Velikov if (!Ty->isSVESizelessBuiltinType() && (IsEmpty || Size == 0)) { 422*e9c2e0acSOliver Stannard // Empty records are ignored in C mode, and in C++ on Darwin. 423992cb984SSergei Barannikov if (!getContext().getLangOpts().CPlusPlus || isDarwinPCS()) 424992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 425992cb984SSergei Barannikov 426*e9c2e0acSOliver Stannard // In C++ mode, arguments which have sizeof() == 0 (which are non-standard 427*e9c2e0acSOliver Stannard // C++) are ignored. This isn't defined by any standard, so we copy GCC's 428*e9c2e0acSOliver Stannard // behaviour here. 429*e9c2e0acSOliver Stannard if (Size == 0) 430992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 431*e9c2e0acSOliver Stannard 432*e9c2e0acSOliver Stannard // Otherwise, they are passed as if they have a size of 1 byte. 433992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); 434992cb984SSergei Barannikov } 435992cb984SSergei Barannikov 436992cb984SSergei Barannikov // Homogeneous Floating-point Aggregates (HFAs) need to be expanded. 437992cb984SSergei Barannikov const Type *Base = nullptr; 438992cb984SSergei Barannikov uint64_t Members = 0; 439992cb984SSergei Barannikov bool IsWin64 = Kind == AArch64ABIKind::Win64 || 440992cb984SSergei Barannikov CallingConvention == llvm::CallingConv::Win64; 44153f7f8ecSMomchil Velikov bool IsWinVariadic = IsWin64 && IsVariadicFn; 442992cb984SSergei Barannikov // In variadic functions on Windows, all composite types are treated alike, 443992cb984SSergei Barannikov // no special handling of HFAs/HVAs. 444992cb984SSergei Barannikov if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) { 44553f7f8ecSMomchil Velikov NSRN = std::min(NSRN + Members, uint64_t(8)); 446992cb984SSergei Barannikov if (Kind != AArch64ABIKind::AAPCS) 447992cb984SSergei Barannikov return ABIArgInfo::getDirect( 448992cb984SSergei Barannikov llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members)); 449992cb984SSergei Barannikov 450c9de04eaSJirui Wu // For HFAs/HVAs, cap the argument alignment to 16, otherwise 451c9de04eaSJirui Wu // set it to 8 according to the AAPCS64 document. 452992cb984SSergei Barannikov unsigned Align = 453992cb984SSergei Barannikov getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); 454c9de04eaSJirui Wu Align = (Align >= 16) ? 16 : 8; 455992cb984SSergei Barannikov return ABIArgInfo::getDirect( 456992cb984SSergei Barannikov llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0, 457992cb984SSergei Barannikov nullptr, true, Align); 458992cb984SSergei Barannikov } 459992cb984SSergei Barannikov 46053f7f8ecSMomchil Velikov // In AAPCS named arguments of a Pure Scalable Type are passed expanded in 46153f7f8ecSMomchil Velikov // registers, or indirectly if there are not enough registers. 46253f7f8ecSMomchil Velikov if (Kind == AArch64ABIKind::AAPCS) { 46353f7f8ecSMomchil Velikov unsigned NVec = 0, NPred = 0; 46453f7f8ecSMomchil Velikov SmallVector<llvm::Type *> UnpaddedCoerceToSeq; 46553f7f8ecSMomchil Velikov if (passAsPureScalableType(Ty, NVec, NPred, UnpaddedCoerceToSeq) && 46653f7f8ecSMomchil Velikov (NVec + NPred) > 0) 46753f7f8ecSMomchil Velikov return coerceAndExpandPureScalableAggregate( 46853f7f8ecSMomchil Velikov Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN); 46953f7f8ecSMomchil Velikov } 47053f7f8ecSMomchil Velikov 471992cb984SSergei Barannikov // Aggregates <= 16 bytes are passed directly in registers or on the stack. 472992cb984SSergei Barannikov if (Size <= 128) { 473992cb984SSergei Barannikov unsigned Alignment; 474992cb984SSergei Barannikov if (Kind == AArch64ABIKind::AAPCS) { 475992cb984SSergei Barannikov Alignment = getContext().getTypeUnadjustedAlign(Ty); 476992cb984SSergei Barannikov Alignment = Alignment < 128 ? 64 : 128; 477992cb984SSergei Barannikov } else { 478992cb984SSergei Barannikov Alignment = 479992cb984SSergei Barannikov std::max(getContext().getTypeAlign(Ty), 480992cb984SSergei Barannikov (unsigned)getTarget().getPointerWidth(LangAS::Default)); 481992cb984SSergei Barannikov } 482992cb984SSergei Barannikov Size = llvm::alignTo(Size, Alignment); 483992cb984SSergei Barannikov 484992cb984SSergei Barannikov // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. 485992cb984SSergei Barannikov // For aggregates with 16-byte alignment, we use i128. 486992cb984SSergei Barannikov llvm::Type *BaseTy = llvm::Type::getIntNTy(getVMContext(), Alignment); 487992cb984SSergei Barannikov return ABIArgInfo::getDirect( 488992cb984SSergei Barannikov Size == Alignment ? BaseTy 489992cb984SSergei Barannikov : llvm::ArrayType::get(BaseTy, Size / Alignment)); 490992cb984SSergei Barannikov } 491992cb984SSergei Barannikov 492992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 493992cb984SSergei Barannikov } 494992cb984SSergei Barannikov 495992cb984SSergei Barannikov ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, 49653f7f8ecSMomchil Velikov bool IsVariadicFn) const { 497992cb984SSergei Barannikov if (RetTy->isVoidType()) 498992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 499992cb984SSergei Barannikov 500992cb984SSergei Barannikov if (const auto *VT = RetTy->getAs<VectorType>()) { 501ae7b20b5SVlad Serebrennikov if (VT->getVectorKind() == VectorKind::SveFixedLengthData || 50253f7f8ecSMomchil Velikov VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { 50353f7f8ecSMomchil Velikov unsigned NSRN = 0, NPRN = 0; 50453f7f8ecSMomchil Velikov return coerceIllegalVector(RetTy, NSRN, NPRN); 50553f7f8ecSMomchil Velikov } 506992cb984SSergei Barannikov } 507992cb984SSergei Barannikov 508992cb984SSergei Barannikov // Large vector types should be returned via memory. 509992cb984SSergei Barannikov if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) 510992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 511992cb984SSergei Barannikov 512f70ab7d9SMomchil Velikov if (!passAsAggregateType(RetTy)) { 513992cb984SSergei Barannikov // Treat an enum type as its underlying type. 514992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 515992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType(); 516992cb984SSergei Barannikov 517992cb984SSergei Barannikov if (const auto *EIT = RetTy->getAs<BitIntType>()) 518992cb984SSergei Barannikov if (EIT->getNumBits() > 128) 519992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 520992cb984SSergei Barannikov 521992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS() 522992cb984SSergei Barannikov ? ABIArgInfo::getExtend(RetTy) 523992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 524992cb984SSergei Barannikov } 525992cb984SSergei Barannikov 526992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(RetTy); 527f70ab7d9SMomchil Velikov if (!RetTy->isSVESizelessBuiltinType() && 528f70ab7d9SMomchil Velikov (isEmptyRecord(getContext(), RetTy, true) || Size == 0)) 529992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 530992cb984SSergei Barannikov 531992cb984SSergei Barannikov const Type *Base = nullptr; 532992cb984SSergei Barannikov uint64_t Members = 0; 533992cb984SSergei Barannikov if (isHomogeneousAggregate(RetTy, Base, Members) && 534992cb984SSergei Barannikov !(getTarget().getTriple().getArch() == llvm::Triple::aarch64_32 && 53553f7f8ecSMomchil Velikov IsVariadicFn)) 536992cb984SSergei Barannikov // Homogeneous Floating-point Aggregates (HFAs) are returned directly. 537992cb984SSergei Barannikov return ABIArgInfo::getDirect(); 538992cb984SSergei Barannikov 53953f7f8ecSMomchil Velikov // In AAPCS return values of a Pure Scalable type are treated as a single 54053f7f8ecSMomchil Velikov // named argument and passed expanded in registers, or indirectly if there are 54153f7f8ecSMomchil Velikov // not enough registers. 54253f7f8ecSMomchil Velikov if (Kind == AArch64ABIKind::AAPCS) { 54353f7f8ecSMomchil Velikov unsigned NSRN = 0, NPRN = 0; 54453f7f8ecSMomchil Velikov unsigned NVec = 0, NPred = 0; 54553f7f8ecSMomchil Velikov SmallVector<llvm::Type *> UnpaddedCoerceToSeq; 54653f7f8ecSMomchil Velikov if (passAsPureScalableType(RetTy, NVec, NPred, UnpaddedCoerceToSeq) && 54753f7f8ecSMomchil Velikov (NVec + NPred) > 0) 54853f7f8ecSMomchil Velikov return coerceAndExpandPureScalableAggregate( 54953f7f8ecSMomchil Velikov RetTy, /* IsNamedArg */ true, NVec, NPred, UnpaddedCoerceToSeq, NSRN, 55053f7f8ecSMomchil Velikov NPRN); 55153f7f8ecSMomchil Velikov } 55253f7f8ecSMomchil Velikov 553992cb984SSergei Barannikov // Aggregates <= 16 bytes are returned directly in registers or on the stack. 554992cb984SSergei Barannikov if (Size <= 128) { 555992cb984SSergei Barannikov if (Size <= 64 && getDataLayout().isLittleEndian()) { 556992cb984SSergei Barannikov // Composite types are returned in lower bits of a 64-bit register for LE, 557992cb984SSergei Barannikov // and in higher bits for BE. However, integer types are always returned 558992cb984SSergei Barannikov // in lower bits for both LE and BE, and they are not rounded up to 559992cb984SSergei Barannikov // 64-bits. We can skip rounding up of composite types for LE, but not for 560992cb984SSergei Barannikov // BE, otherwise composite types will be indistinguishable from integer 561992cb984SSergei Barannikov // types. 562992cb984SSergei Barannikov return ABIArgInfo::getDirect( 563992cb984SSergei Barannikov llvm::IntegerType::get(getVMContext(), Size)); 564992cb984SSergei Barannikov } 565992cb984SSergei Barannikov 566992cb984SSergei Barannikov unsigned Alignment = getContext().getTypeAlign(RetTy); 567992cb984SSergei Barannikov Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes 568992cb984SSergei Barannikov 569992cb984SSergei Barannikov // We use a pair of i64 for 16-byte aggregate with 8-byte alignment. 570992cb984SSergei Barannikov // For aggregates with 16-byte alignment, we use i128. 571992cb984SSergei Barannikov if (Alignment < 128 && Size == 128) { 572992cb984SSergei Barannikov llvm::Type *BaseTy = llvm::Type::getInt64Ty(getVMContext()); 573992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64)); 574992cb984SSergei Barannikov } 575992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); 576992cb984SSergei Barannikov } 577992cb984SSergei Barannikov 578992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 579992cb984SSergei Barannikov } 580992cb984SSergei Barannikov 581992cb984SSergei Barannikov /// isIllegalVectorType - check whether the vector type is legal for AArch64. 582992cb984SSergei Barannikov bool AArch64ABIInfo::isIllegalVectorType(QualType Ty) const { 583992cb984SSergei Barannikov if (const VectorType *VT = Ty->getAs<VectorType>()) { 584992cb984SSergei Barannikov // Check whether VT is a fixed-length SVE vector. These types are 585992cb984SSergei Barannikov // represented as scalable vectors in function args/return and must be 586992cb984SSergei Barannikov // coerced from fixed vectors. 587ae7b20b5SVlad Serebrennikov if (VT->getVectorKind() == VectorKind::SveFixedLengthData || 588ae7b20b5SVlad Serebrennikov VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) 589992cb984SSergei Barannikov return true; 590992cb984SSergei Barannikov 591992cb984SSergei Barannikov // Check whether VT is legal. 592992cb984SSergei Barannikov unsigned NumElements = VT->getNumElements(); 593992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(VT); 594992cb984SSergei Barannikov // NumElements should be power of 2. 595992cb984SSergei Barannikov if (!llvm::isPowerOf2_32(NumElements)) 596992cb984SSergei Barannikov return true; 597992cb984SSergei Barannikov 598992cb984SSergei Barannikov // arm64_32 has to be compatible with the ARM logic here, which allows huge 599992cb984SSergei Barannikov // vectors for some reason. 600992cb984SSergei Barannikov llvm::Triple Triple = getTarget().getTriple(); 601992cb984SSergei Barannikov if (Triple.getArch() == llvm::Triple::aarch64_32 && 602992cb984SSergei Barannikov Triple.isOSBinFormatMachO()) 603992cb984SSergei Barannikov return Size <= 32; 604992cb984SSergei Barannikov 605992cb984SSergei Barannikov return Size != 64 && (Size != 128 || NumElements == 1); 606992cb984SSergei Barannikov } 607992cb984SSergei Barannikov return false; 608992cb984SSergei Barannikov } 609992cb984SSergei Barannikov 610992cb984SSergei Barannikov bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, 611992cb984SSergei Barannikov llvm::Type *EltTy, 612992cb984SSergei Barannikov unsigned NumElts) const { 613992cb984SSergei Barannikov if (!llvm::isPowerOf2_32(NumElts)) 614992cb984SSergei Barannikov return false; 615992cb984SSergei Barannikov if (VectorSize.getQuantity() != 8 && 616992cb984SSergei Barannikov (VectorSize.getQuantity() != 16 || NumElts == 1)) 617992cb984SSergei Barannikov return false; 618992cb984SSergei Barannikov return true; 619992cb984SSergei Barannikov } 620992cb984SSergei Barannikov 621992cb984SSergei Barannikov bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { 622ef395a49Sostannard // For the soft-float ABI variant, no types are considered to be homogeneous 623ef395a49Sostannard // aggregates. 624b3f3c0c6SJon Roelofs if (isSoftFloat()) 625ef395a49Sostannard return false; 626ef395a49Sostannard 627992cb984SSergei Barannikov // Homogeneous aggregates for AAPCS64 must have base types of a floating 628992cb984SSergei Barannikov // point type or a short-vector type. This is the same as the 32-bit ABI, 629992cb984SSergei Barannikov // but with the difference that any floating-point type is allowed, 630992cb984SSergei Barannikov // including __fp16. 631992cb984SSergei Barannikov if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { 63287103a01SMomchil Velikov if (BT->isFloatingPoint()) 633992cb984SSergei Barannikov return true; 634992cb984SSergei Barannikov } else if (const VectorType *VT = Ty->getAs<VectorType>()) { 63553f7f8ecSMomchil Velikov if (auto Kind = VT->getVectorKind(); 63653f7f8ecSMomchil Velikov Kind == VectorKind::SveFixedLengthData || 63753f7f8ecSMomchil Velikov Kind == VectorKind::SveFixedLengthPredicate) 63853f7f8ecSMomchil Velikov return false; 63953f7f8ecSMomchil Velikov 640992cb984SSergei Barannikov unsigned VecSize = getContext().getTypeSize(VT); 641992cb984SSergei Barannikov if (VecSize == 64 || VecSize == 128) 642992cb984SSergei Barannikov return true; 643992cb984SSergei Barannikov } 644992cb984SSergei Barannikov return false; 645992cb984SSergei Barannikov } 646992cb984SSergei Barannikov 647992cb984SSergei Barannikov bool AArch64ABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, 648992cb984SSergei Barannikov uint64_t Members) const { 649992cb984SSergei Barannikov return Members <= 4; 650992cb984SSergei Barannikov } 651992cb984SSergei Barannikov 652992cb984SSergei Barannikov bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() 653992cb984SSergei Barannikov const { 654992cb984SSergei Barannikov // AAPCS64 says that the rule for whether something is a homogeneous 655992cb984SSergei Barannikov // aggregate is applied to the output of the data layout decision. So 656992cb984SSergei Barannikov // anything that doesn't affect the data layout also does not affect 657992cb984SSergei Barannikov // homogeneity. In particular, zero-length bitfields don't stop a struct 658992cb984SSergei Barannikov // being homogeneous. 659992cb984SSergei Barannikov return true; 660992cb984SSergei Barannikov } 661992cb984SSergei Barannikov 662f70ab7d9SMomchil Velikov bool AArch64ABIInfo::passAsAggregateType(QualType Ty) const { 663f70ab7d9SMomchil Velikov if (Kind == AArch64ABIKind::AAPCS && Ty->isSVESizelessBuiltinType()) { 6646279d2e0SSimon Pilgrim const auto *BT = Ty->castAs<BuiltinType>(); 665f70ab7d9SMomchil Velikov return !BT->isSVECount() && 666f70ab7d9SMomchil Velikov getContext().getBuiltinVectorTypeInfo(BT).NumVectors > 1; 667f70ab7d9SMomchil Velikov } 668f70ab7d9SMomchil Velikov return isAggregateTypeForABI(Ty); 669f70ab7d9SMomchil Velikov } 670f70ab7d9SMomchil Velikov 67153f7f8ecSMomchil Velikov // Check if a type needs to be passed in registers as a Pure Scalable Type (as 67253f7f8ecSMomchil Velikov // defined by AAPCS64). Return the number of data vectors and the number of 67353f7f8ecSMomchil Velikov // predicate vectors in the type, into `NVec` and `NPred`, respectively. Upon 67453f7f8ecSMomchil Velikov // return `CoerceToSeq` contains an expanded sequence of LLVM IR types, one 67553f7f8ecSMomchil Velikov // element for each non-composite member. For practical purposes, limit the 67653f7f8ecSMomchil Velikov // length of `CoerceToSeq` to about 12 (the maximum that could possibly fit 67753f7f8ecSMomchil Velikov // in registers) and return false, the effect of which will be to pass the 67853f7f8ecSMomchil Velikov // argument under the rules for a large (> 128 bytes) composite. 67953f7f8ecSMomchil Velikov bool AArch64ABIInfo::passAsPureScalableType( 68053f7f8ecSMomchil Velikov QualType Ty, unsigned &NVec, unsigned &NPred, 68153f7f8ecSMomchil Velikov SmallVectorImpl<llvm::Type *> &CoerceToSeq) const { 68253f7f8ecSMomchil Velikov if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { 68353f7f8ecSMomchil Velikov uint64_t NElt = AT->getZExtSize(); 68453f7f8ecSMomchil Velikov if (NElt == 0) 68553f7f8ecSMomchil Velikov return false; 68653f7f8ecSMomchil Velikov 68753f7f8ecSMomchil Velikov unsigned NV = 0, NP = 0; 68853f7f8ecSMomchil Velikov SmallVector<llvm::Type *> EltCoerceToSeq; 68953f7f8ecSMomchil Velikov if (!passAsPureScalableType(AT->getElementType(), NV, NP, EltCoerceToSeq)) 69053f7f8ecSMomchil Velikov return false; 69153f7f8ecSMomchil Velikov 69253f7f8ecSMomchil Velikov if (CoerceToSeq.size() + NElt * EltCoerceToSeq.size() > 12) 69353f7f8ecSMomchil Velikov return false; 69453f7f8ecSMomchil Velikov 69553f7f8ecSMomchil Velikov for (uint64_t I = 0; I < NElt; ++I) 69653f7f8ecSMomchil Velikov llvm::copy(EltCoerceToSeq, std::back_inserter(CoerceToSeq)); 69753f7f8ecSMomchil Velikov 69853f7f8ecSMomchil Velikov NVec += NElt * NV; 69953f7f8ecSMomchil Velikov NPred += NElt * NP; 70053f7f8ecSMomchil Velikov return true; 70153f7f8ecSMomchil Velikov } 70253f7f8ecSMomchil Velikov 70353f7f8ecSMomchil Velikov if (const RecordType *RT = Ty->getAs<RecordType>()) { 70453f7f8ecSMomchil Velikov // If the record cannot be passed in registers, then it's not a PST. 70553f7f8ecSMomchil Velikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); 70653f7f8ecSMomchil Velikov RAA != CGCXXABI::RAA_Default) 70753f7f8ecSMomchil Velikov return false; 70853f7f8ecSMomchil Velikov 70953f7f8ecSMomchil Velikov // Pure scalable types are never unions and never contain unions. 71053f7f8ecSMomchil Velikov const RecordDecl *RD = RT->getDecl(); 71153f7f8ecSMomchil Velikov if (RD->isUnion()) 71253f7f8ecSMomchil Velikov return false; 71353f7f8ecSMomchil Velikov 71453f7f8ecSMomchil Velikov // If this is a C++ record, check the bases. 71553f7f8ecSMomchil Velikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { 71653f7f8ecSMomchil Velikov for (const auto &I : CXXRD->bases()) { 71753f7f8ecSMomchil Velikov if (isEmptyRecord(getContext(), I.getType(), true)) 71853f7f8ecSMomchil Velikov continue; 71953f7f8ecSMomchil Velikov if (!passAsPureScalableType(I.getType(), NVec, NPred, CoerceToSeq)) 72053f7f8ecSMomchil Velikov return false; 72153f7f8ecSMomchil Velikov } 72253f7f8ecSMomchil Velikov } 72353f7f8ecSMomchil Velikov 72453f7f8ecSMomchil Velikov // Check members. 72553f7f8ecSMomchil Velikov for (const auto *FD : RD->fields()) { 72653f7f8ecSMomchil Velikov QualType FT = FD->getType(); 72753f7f8ecSMomchil Velikov if (isEmptyField(getContext(), FD, /* AllowArrays */ true)) 72853f7f8ecSMomchil Velikov continue; 72953f7f8ecSMomchil Velikov if (!passAsPureScalableType(FT, NVec, NPred, CoerceToSeq)) 73053f7f8ecSMomchil Velikov return false; 73153f7f8ecSMomchil Velikov } 73253f7f8ecSMomchil Velikov 73353f7f8ecSMomchil Velikov return true; 73453f7f8ecSMomchil Velikov } 73553f7f8ecSMomchil Velikov 736f70ab7d9SMomchil Velikov if (const auto *VT = Ty->getAs<VectorType>()) { 73753f7f8ecSMomchil Velikov if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) { 73853f7f8ecSMomchil Velikov ++NPred; 73953f7f8ecSMomchil Velikov if (CoerceToSeq.size() + 1 > 12) 74053f7f8ecSMomchil Velikov return false; 74153f7f8ecSMomchil Velikov CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); 74253f7f8ecSMomchil Velikov return true; 74353f7f8ecSMomchil Velikov } 74453f7f8ecSMomchil Velikov 74553f7f8ecSMomchil Velikov if (VT->getVectorKind() == VectorKind::SveFixedLengthData) { 74653f7f8ecSMomchil Velikov ++NVec; 74753f7f8ecSMomchil Velikov if (CoerceToSeq.size() + 1 > 12) 74853f7f8ecSMomchil Velikov return false; 74953f7f8ecSMomchil Velikov CoerceToSeq.push_back(convertFixedToScalableVectorType(VT)); 75053f7f8ecSMomchil Velikov return true; 75153f7f8ecSMomchil Velikov } 75253f7f8ecSMomchil Velikov 753f70ab7d9SMomchil Velikov return false; 754f70ab7d9SMomchil Velikov } 755f70ab7d9SMomchil Velikov 756f70ab7d9SMomchil Velikov if (!Ty->isBuiltinType()) 75753f7f8ecSMomchil Velikov return false; 75853f7f8ecSMomchil Velikov 759f70ab7d9SMomchil Velikov bool isPredicate; 760f70ab7d9SMomchil Velikov switch (Ty->getAs<BuiltinType>()->getKind()) { 76153f7f8ecSMomchil Velikov #define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \ 76253f7f8ecSMomchil Velikov case BuiltinType::Id: \ 763f70ab7d9SMomchil Velikov isPredicate = false; \ 76453f7f8ecSMomchil Velikov break; 76553f7f8ecSMomchil Velikov #define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \ 76653f7f8ecSMomchil Velikov case BuiltinType::Id: \ 767f70ab7d9SMomchil Velikov isPredicate = true; \ 76853f7f8ecSMomchil Velikov break; 76953f7f8ecSMomchil Velikov #define SVE_TYPE(Name, Id, SingletonId) 77053f7f8ecSMomchil Velikov #include "clang/Basic/AArch64SVEACLETypes.def" 77153f7f8ecSMomchil Velikov default: 77253f7f8ecSMomchil Velikov return false; 77353f7f8ecSMomchil Velikov } 77453f7f8ecSMomchil Velikov 77553f7f8ecSMomchil Velikov ASTContext::BuiltinVectorTypeInfo Info = 77653f7f8ecSMomchil Velikov getContext().getBuiltinVectorTypeInfo(cast<BuiltinType>(Ty)); 77753f7f8ecSMomchil Velikov assert(Info.NumVectors > 0 && Info.NumVectors <= 4 && 77853f7f8ecSMomchil Velikov "Expected 1, 2, 3 or 4 vectors!"); 779f70ab7d9SMomchil Velikov if (isPredicate) 780f70ab7d9SMomchil Velikov NPred += Info.NumVectors; 781f70ab7d9SMomchil Velikov else 782f70ab7d9SMomchil Velikov NVec += Info.NumVectors; 783f95a8bdeSMomchil Velikov llvm::Type *EltTy = Info.ElementType->isMFloat8Type() 784f95a8bdeSMomchil Velikov ? llvm::Type::getInt8Ty(getVMContext()) 785f95a8bdeSMomchil Velikov : CGT.ConvertType(Info.ElementType); 786f95a8bdeSMomchil Velikov auto *VTy = llvm::ScalableVectorType::get(EltTy, Info.EC.getKnownMinValue()); 78753f7f8ecSMomchil Velikov 78853f7f8ecSMomchil Velikov if (CoerceToSeq.size() + Info.NumVectors > 12) 78953f7f8ecSMomchil Velikov return false; 79053f7f8ecSMomchil Velikov std::fill_n(std::back_inserter(CoerceToSeq), Info.NumVectors, VTy); 79153f7f8ecSMomchil Velikov 79253f7f8ecSMomchil Velikov return true; 79353f7f8ecSMomchil Velikov } 79453f7f8ecSMomchil Velikov 79553f7f8ecSMomchil Velikov // Expand an LLVM IR type into a sequence with a element for each non-struct, 79653f7f8ecSMomchil Velikov // non-array member of the type, with the exception of the padding types, which 79753f7f8ecSMomchil Velikov // are retained. 79853f7f8ecSMomchil Velikov void AArch64ABIInfo::flattenType( 79953f7f8ecSMomchil Velikov llvm::Type *Ty, SmallVectorImpl<llvm::Type *> &Flattened) const { 80053f7f8ecSMomchil Velikov 80153f7f8ecSMomchil Velikov if (ABIArgInfo::isPaddingForCoerceAndExpand(Ty)) { 80253f7f8ecSMomchil Velikov Flattened.push_back(Ty); 80353f7f8ecSMomchil Velikov return; 80453f7f8ecSMomchil Velikov } 80553f7f8ecSMomchil Velikov 80653f7f8ecSMomchil Velikov if (const auto *AT = dyn_cast<llvm::ArrayType>(Ty)) { 80753f7f8ecSMomchil Velikov uint64_t NElt = AT->getNumElements(); 80853f7f8ecSMomchil Velikov if (NElt == 0) 80953f7f8ecSMomchil Velikov return; 81053f7f8ecSMomchil Velikov 81153f7f8ecSMomchil Velikov SmallVector<llvm::Type *> EltFlattened; 81253f7f8ecSMomchil Velikov flattenType(AT->getElementType(), EltFlattened); 81353f7f8ecSMomchil Velikov 81453f7f8ecSMomchil Velikov for (uint64_t I = 0; I < NElt; ++I) 81553f7f8ecSMomchil Velikov llvm::copy(EltFlattened, std::back_inserter(Flattened)); 81653f7f8ecSMomchil Velikov return; 81753f7f8ecSMomchil Velikov } 81853f7f8ecSMomchil Velikov 81953f7f8ecSMomchil Velikov if (const auto *ST = dyn_cast<llvm::StructType>(Ty)) { 82053f7f8ecSMomchil Velikov for (auto *ET : ST->elements()) 82153f7f8ecSMomchil Velikov flattenType(ET, Flattened); 82253f7f8ecSMomchil Velikov return; 82353f7f8ecSMomchil Velikov } 82453f7f8ecSMomchil Velikov 82553f7f8ecSMomchil Velikov Flattened.push_back(Ty); 82653f7f8ecSMomchil Velikov } 82753f7f8ecSMomchil Velikov 8286d973b45SMariya Podchishchaeva RValue AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty, 8296d973b45SMariya Podchishchaeva CodeGenFunction &CGF, AArch64ABIKind Kind, 8306d973b45SMariya Podchishchaeva AggValueSlot Slot) const { 83153f7f8ecSMomchil Velikov // These numbers are not used for variadic arguments, hence it doesn't matter 83253f7f8ecSMomchil Velikov // they don't retain their values across multiple calls to 83353f7f8ecSMomchil Velikov // `classifyArgumentType` here. 83453f7f8ecSMomchil Velikov unsigned NSRN = 0, NPRN = 0; 83553f7f8ecSMomchil Velikov ABIArgInfo AI = 83653f7f8ecSMomchil Velikov classifyArgumentType(Ty, /*IsVariadicFn=*/true, /* IsNamedArg */ false, 83753f7f8ecSMomchil Velikov CGF.CurFnInfo->getCallingConvention(), NSRN, NPRN); 838992cb984SSergei Barannikov // Empty records are ignored for parameter passing purposes. 8396d973b45SMariya Podchishchaeva if (AI.isIgnore()) 8406d973b45SMariya Podchishchaeva return Slot.asRValue(); 841992cb984SSergei Barannikov 842992cb984SSergei Barannikov bool IsIndirect = AI.isIndirect(); 843992cb984SSergei Barannikov 844992cb984SSergei Barannikov llvm::Type *BaseTy = CGF.ConvertType(Ty); 845992cb984SSergei Barannikov if (IsIndirect) 846992cb984SSergei Barannikov BaseTy = llvm::PointerType::getUnqual(BaseTy); 847992cb984SSergei Barannikov else if (AI.getCoerceToType()) 848992cb984SSergei Barannikov BaseTy = AI.getCoerceToType(); 849992cb984SSergei Barannikov 850992cb984SSergei Barannikov unsigned NumRegs = 1; 851992cb984SSergei Barannikov if (llvm::ArrayType *ArrTy = dyn_cast<llvm::ArrayType>(BaseTy)) { 852992cb984SSergei Barannikov BaseTy = ArrTy->getElementType(); 853992cb984SSergei Barannikov NumRegs = ArrTy->getNumElements(); 854992cb984SSergei Barannikov } 855b3f3c0c6SJon Roelofs bool IsFPR = 856b3f3c0c6SJon Roelofs !isSoftFloat() && (BaseTy->isFloatingPointTy() || BaseTy->isVectorTy()); 857992cb984SSergei Barannikov 858992cb984SSergei Barannikov // The AArch64 va_list type and handling is specified in the Procedure Call 859992cb984SSergei Barannikov // Standard, section B.4: 860992cb984SSergei Barannikov // 861992cb984SSergei Barannikov // struct { 862992cb984SSergei Barannikov // void *__stack; 863992cb984SSergei Barannikov // void *__gr_top; 864992cb984SSergei Barannikov // void *__vr_top; 865992cb984SSergei Barannikov // int __gr_offs; 866992cb984SSergei Barannikov // int __vr_offs; 867992cb984SSergei Barannikov // }; 868992cb984SSergei Barannikov 869992cb984SSergei Barannikov llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg"); 870992cb984SSergei Barannikov llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); 871992cb984SSergei Barannikov llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack"); 872992cb984SSergei Barannikov llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); 873992cb984SSergei Barannikov 874992cb984SSergei Barannikov CharUnits TySize = getContext().getTypeSizeInChars(Ty); 875992cb984SSergei Barannikov CharUnits TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty); 876992cb984SSergei Barannikov 877992cb984SSergei Barannikov Address reg_offs_p = Address::invalid(); 878992cb984SSergei Barannikov llvm::Value *reg_offs = nullptr; 879992cb984SSergei Barannikov int reg_top_index; 880992cb984SSergei Barannikov int RegSize = IsIndirect ? 8 : TySize.getQuantity(); 881992cb984SSergei Barannikov if (!IsFPR) { 882992cb984SSergei Barannikov // 3 is the field number of __gr_offs 883992cb984SSergei Barannikov reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 3, "gr_offs_p"); 884992cb984SSergei Barannikov reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "gr_offs"); 885992cb984SSergei Barannikov reg_top_index = 1; // field number for __gr_top 886992cb984SSergei Barannikov RegSize = llvm::alignTo(RegSize, 8); 887992cb984SSergei Barannikov } else { 888992cb984SSergei Barannikov // 4 is the field number of __vr_offs. 889992cb984SSergei Barannikov reg_offs_p = CGF.Builder.CreateStructGEP(VAListAddr, 4, "vr_offs_p"); 890992cb984SSergei Barannikov reg_offs = CGF.Builder.CreateLoad(reg_offs_p, "vr_offs"); 891992cb984SSergei Barannikov reg_top_index = 2; // field number for __vr_top 892992cb984SSergei Barannikov RegSize = 16 * NumRegs; 893992cb984SSergei Barannikov } 894992cb984SSergei Barannikov 895992cb984SSergei Barannikov //======================================= 896992cb984SSergei Barannikov // Find out where argument was passed 897992cb984SSergei Barannikov //======================================= 898992cb984SSergei Barannikov 899992cb984SSergei Barannikov // If reg_offs >= 0 we're already using the stack for this type of 900992cb984SSergei Barannikov // argument. We don't want to keep updating reg_offs (in case it overflows, 901992cb984SSergei Barannikov // though anyone passing 2GB of arguments, each at most 16 bytes, deserves 902992cb984SSergei Barannikov // whatever they get). 903992cb984SSergei Barannikov llvm::Value *UsingStack = nullptr; 904992cb984SSergei Barannikov UsingStack = CGF.Builder.CreateICmpSGE( 905992cb984SSergei Barannikov reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, 0)); 906992cb984SSergei Barannikov 907992cb984SSergei Barannikov CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, MaybeRegBlock); 908992cb984SSergei Barannikov 909992cb984SSergei Barannikov // Otherwise, at least some kind of argument could go in these registers, the 910992cb984SSergei Barannikov // question is whether this particular type is too big. 911992cb984SSergei Barannikov CGF.EmitBlock(MaybeRegBlock); 912992cb984SSergei Barannikov 913992cb984SSergei Barannikov // Integer arguments may need to correct register alignment (for example a 914992cb984SSergei Barannikov // "struct { __int128 a; };" gets passed in x_2N, x_{2N+1}). In this case we 915992cb984SSergei Barannikov // align __gr_offs to calculate the potential address. 916992cb984SSergei Barannikov if (!IsFPR && !IsIndirect && TyAlign.getQuantity() > 8) { 917992cb984SSergei Barannikov int Align = TyAlign.getQuantity(); 918992cb984SSergei Barannikov 919992cb984SSergei Barannikov reg_offs = CGF.Builder.CreateAdd( 920992cb984SSergei Barannikov reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, Align - 1), 921992cb984SSergei Barannikov "align_regoffs"); 922992cb984SSergei Barannikov reg_offs = CGF.Builder.CreateAnd( 923992cb984SSergei Barannikov reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, -Align), 924992cb984SSergei Barannikov "aligned_regoffs"); 925992cb984SSergei Barannikov } 926992cb984SSergei Barannikov 927992cb984SSergei Barannikov // Update the gr_offs/vr_offs pointer for next call to va_arg on this va_list. 928992cb984SSergei Barannikov // The fact that this is done unconditionally reflects the fact that 929992cb984SSergei Barannikov // allocating an argument to the stack also uses up all the remaining 930992cb984SSergei Barannikov // registers of the appropriate kind. 931992cb984SSergei Barannikov llvm::Value *NewOffset = nullptr; 932992cb984SSergei Barannikov NewOffset = CGF.Builder.CreateAdd( 933992cb984SSergei Barannikov reg_offs, llvm::ConstantInt::get(CGF.Int32Ty, RegSize), "new_reg_offs"); 934992cb984SSergei Barannikov CGF.Builder.CreateStore(NewOffset, reg_offs_p); 935992cb984SSergei Barannikov 936992cb984SSergei Barannikov // Now we're in a position to decide whether this argument really was in 937992cb984SSergei Barannikov // registers or not. 938992cb984SSergei Barannikov llvm::Value *InRegs = nullptr; 939992cb984SSergei Barannikov InRegs = CGF.Builder.CreateICmpSLE( 940992cb984SSergei Barannikov NewOffset, llvm::ConstantInt::get(CGF.Int32Ty, 0), "inreg"); 941992cb984SSergei Barannikov 942992cb984SSergei Barannikov CGF.Builder.CreateCondBr(InRegs, InRegBlock, OnStackBlock); 943992cb984SSergei Barannikov 944992cb984SSergei Barannikov //======================================= 945992cb984SSergei Barannikov // Argument was in registers 946992cb984SSergei Barannikov //======================================= 947992cb984SSergei Barannikov 948992cb984SSergei Barannikov // Now we emit the code for if the argument was originally passed in 949992cb984SSergei Barannikov // registers. First start the appropriate block: 950992cb984SSergei Barannikov CGF.EmitBlock(InRegBlock); 951992cb984SSergei Barannikov 952992cb984SSergei Barannikov llvm::Value *reg_top = nullptr; 953992cb984SSergei Barannikov Address reg_top_p = 954992cb984SSergei Barannikov CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p"); 955992cb984SSergei Barannikov reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top"); 956992cb984SSergei Barannikov Address BaseAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, reg_top, reg_offs), 957992cb984SSergei Barannikov CGF.Int8Ty, CharUnits::fromQuantity(IsFPR ? 16 : 8)); 958992cb984SSergei Barannikov Address RegAddr = Address::invalid(); 959992cb984SSergei Barannikov llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty), *ElementTy = MemTy; 960992cb984SSergei Barannikov 961992cb984SSergei Barannikov if (IsIndirect) { 962992cb984SSergei Barannikov // If it's been passed indirectly (actually a struct), whatever we find from 963992cb984SSergei Barannikov // stored registers or on the stack will actually be a struct **. 964992cb984SSergei Barannikov MemTy = llvm::PointerType::getUnqual(MemTy); 965992cb984SSergei Barannikov } 966992cb984SSergei Barannikov 967992cb984SSergei Barannikov const Type *Base = nullptr; 968992cb984SSergei Barannikov uint64_t NumMembers = 0; 969992cb984SSergei Barannikov bool IsHFA = isHomogeneousAggregate(Ty, Base, NumMembers); 970992cb984SSergei Barannikov if (IsHFA && NumMembers > 1) { 971992cb984SSergei Barannikov // Homogeneous aggregates passed in registers will have their elements split 972992cb984SSergei Barannikov // and stored 16-bytes apart regardless of size (they're notionally in qN, 973992cb984SSergei Barannikov // qN+1, ...). We reload and store into a temporary local variable 974992cb984SSergei Barannikov // contiguously. 975992cb984SSergei Barannikov assert(!IsIndirect && "Homogeneous aggregates should be passed directly"); 976992cb984SSergei Barannikov auto BaseTyInfo = getContext().getTypeInfoInChars(QualType(Base, 0)); 977992cb984SSergei Barannikov llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0)); 978992cb984SSergei Barannikov llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers); 979992cb984SSergei Barannikov Address Tmp = CGF.CreateTempAlloca(HFATy, 980992cb984SSergei Barannikov std::max(TyAlign, BaseTyInfo.Align)); 981992cb984SSergei Barannikov 982992cb984SSergei Barannikov // On big-endian platforms, the value will be right-aligned in its slot. 983992cb984SSergei Barannikov int Offset = 0; 984992cb984SSergei Barannikov if (CGF.CGM.getDataLayout().isBigEndian() && 985992cb984SSergei Barannikov BaseTyInfo.Width.getQuantity() < 16) 986992cb984SSergei Barannikov Offset = 16 - BaseTyInfo.Width.getQuantity(); 987992cb984SSergei Barannikov 988992cb984SSergei Barannikov for (unsigned i = 0; i < NumMembers; ++i) { 989992cb984SSergei Barannikov CharUnits BaseOffset = CharUnits::fromQuantity(16 * i + Offset); 990992cb984SSergei Barannikov Address LoadAddr = 991992cb984SSergei Barannikov CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, BaseOffset); 992474ec694SYoungsuk Kim LoadAddr = LoadAddr.withElementType(BaseTy); 993992cb984SSergei Barannikov 994992cb984SSergei Barannikov Address StoreAddr = CGF.Builder.CreateConstArrayGEP(Tmp, i); 995992cb984SSergei Barannikov 996992cb984SSergei Barannikov llvm::Value *Elem = CGF.Builder.CreateLoad(LoadAddr); 997992cb984SSergei Barannikov CGF.Builder.CreateStore(Elem, StoreAddr); 998992cb984SSergei Barannikov } 999992cb984SSergei Barannikov 1000474ec694SYoungsuk Kim RegAddr = Tmp.withElementType(MemTy); 1001992cb984SSergei Barannikov } else { 1002992cb984SSergei Barannikov // Otherwise the object is contiguous in memory. 1003992cb984SSergei Barannikov 1004992cb984SSergei Barannikov // It might be right-aligned in its slot. 1005992cb984SSergei Barannikov CharUnits SlotSize = BaseAddr.getAlignment(); 1006992cb984SSergei Barannikov if (CGF.CGM.getDataLayout().isBigEndian() && !IsIndirect && 1007992cb984SSergei Barannikov (IsHFA || !isAggregateTypeForABI(Ty)) && 1008992cb984SSergei Barannikov TySize < SlotSize) { 1009992cb984SSergei Barannikov CharUnits Offset = SlotSize - TySize; 1010992cb984SSergei Barannikov BaseAddr = CGF.Builder.CreateConstInBoundsByteGEP(BaseAddr, Offset); 1011992cb984SSergei Barannikov } 1012992cb984SSergei Barannikov 1013474ec694SYoungsuk Kim RegAddr = BaseAddr.withElementType(MemTy); 1014992cb984SSergei Barannikov } 1015992cb984SSergei Barannikov 1016992cb984SSergei Barannikov CGF.EmitBranch(ContBlock); 1017992cb984SSergei Barannikov 1018992cb984SSergei Barannikov //======================================= 1019992cb984SSergei Barannikov // Argument was on the stack 1020992cb984SSergei Barannikov //======================================= 1021992cb984SSergei Barannikov CGF.EmitBlock(OnStackBlock); 1022992cb984SSergei Barannikov 1023992cb984SSergei Barannikov Address stack_p = CGF.Builder.CreateStructGEP(VAListAddr, 0, "stack_p"); 1024992cb984SSergei Barannikov llvm::Value *OnStackPtr = CGF.Builder.CreateLoad(stack_p, "stack"); 1025992cb984SSergei Barannikov 1026992cb984SSergei Barannikov // Again, stack arguments may need realignment. In this case both integer and 1027992cb984SSergei Barannikov // floating-point ones might be affected. 1028992cb984SSergei Barannikov if (!IsIndirect && TyAlign.getQuantity() > 8) { 1029b2d7d72fSJon Chesterfield OnStackPtr = emitRoundPointerUpToAlignment(CGF, OnStackPtr, TyAlign); 1030992cb984SSergei Barannikov } 1031992cb984SSergei Barannikov Address OnStackAddr = Address(OnStackPtr, CGF.Int8Ty, 1032992cb984SSergei Barannikov std::max(CharUnits::fromQuantity(8), TyAlign)); 1033992cb984SSergei Barannikov 1034992cb984SSergei Barannikov // All stack slots are multiples of 8 bytes. 1035992cb984SSergei Barannikov CharUnits StackSlotSize = CharUnits::fromQuantity(8); 1036992cb984SSergei Barannikov CharUnits StackSize; 1037992cb984SSergei Barannikov if (IsIndirect) 1038992cb984SSergei Barannikov StackSize = StackSlotSize; 1039992cb984SSergei Barannikov else 1040992cb984SSergei Barannikov StackSize = TySize.alignTo(StackSlotSize); 1041992cb984SSergei Barannikov 1042992cb984SSergei Barannikov llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize); 1043992cb984SSergei Barannikov llvm::Value *NewStack = CGF.Builder.CreateInBoundsGEP( 1044992cb984SSergei Barannikov CGF.Int8Ty, OnStackPtr, StackSizeC, "new_stack"); 1045992cb984SSergei Barannikov 1046992cb984SSergei Barannikov // Write the new value of __stack for the next call to va_arg 1047992cb984SSergei Barannikov CGF.Builder.CreateStore(NewStack, stack_p); 1048992cb984SSergei Barannikov 1049992cb984SSergei Barannikov if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) && 1050992cb984SSergei Barannikov TySize < StackSlotSize) { 1051992cb984SSergei Barannikov CharUnits Offset = StackSlotSize - TySize; 1052992cb984SSergei Barannikov OnStackAddr = CGF.Builder.CreateConstInBoundsByteGEP(OnStackAddr, Offset); 1053992cb984SSergei Barannikov } 1054992cb984SSergei Barannikov 1055474ec694SYoungsuk Kim OnStackAddr = OnStackAddr.withElementType(MemTy); 1056992cb984SSergei Barannikov 1057992cb984SSergei Barannikov CGF.EmitBranch(ContBlock); 1058992cb984SSergei Barannikov 1059992cb984SSergei Barannikov //======================================= 1060992cb984SSergei Barannikov // Tidy up 1061992cb984SSergei Barannikov //======================================= 1062992cb984SSergei Barannikov CGF.EmitBlock(ContBlock); 1063992cb984SSergei Barannikov 1064992cb984SSergei Barannikov Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, OnStackAddr, 1065992cb984SSergei Barannikov OnStackBlock, "vaargs.addr"); 1066992cb984SSergei Barannikov 1067992cb984SSergei Barannikov if (IsIndirect) 10686d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue( 10696d973b45SMariya Podchishchaeva CGF.MakeAddrLValue( 10706d973b45SMariya Podchishchaeva Address(CGF.Builder.CreateLoad(ResAddr, "vaarg.addr"), ElementTy, 10716d973b45SMariya Podchishchaeva TyAlign), 10726d973b45SMariya Podchishchaeva Ty), 10736d973b45SMariya Podchishchaeva Slot); 1074992cb984SSergei Barannikov 10756d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot); 1076992cb984SSergei Barannikov } 1077992cb984SSergei Barannikov 10786d973b45SMariya Podchishchaeva RValue AArch64ABIInfo::EmitDarwinVAArg(Address VAListAddr, QualType Ty, 10796d973b45SMariya Podchishchaeva CodeGenFunction &CGF, 10806d973b45SMariya Podchishchaeva AggValueSlot Slot) const { 1081992cb984SSergei Barannikov // The backend's lowering doesn't support va_arg for aggregates or 1082992cb984SSergei Barannikov // illegal vector types. Lower VAArg here for these cases and use 1083992cb984SSergei Barannikov // the LLVM va_arg instruction for everything else. 1084992cb984SSergei Barannikov if (!isAggregateTypeForABI(Ty) && !isIllegalVectorType(Ty)) 10856d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue( 10866d973b45SMariya Podchishchaeva CGF.MakeAddrLValue( 10876d973b45SMariya Podchishchaeva EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()), Ty), 10886d973b45SMariya Podchishchaeva Slot); 1089992cb984SSergei Barannikov 1090992cb984SSergei Barannikov uint64_t PointerSize = getTarget().getPointerWidth(LangAS::Default) / 8; 1091992cb984SSergei Barannikov CharUnits SlotSize = CharUnits::fromQuantity(PointerSize); 1092992cb984SSergei Barannikov 1093992cb984SSergei Barannikov // Empty records are ignored for parameter passing purposes. 1094474ec694SYoungsuk Kim if (isEmptyRecord(getContext(), Ty, true)) 10956d973b45SMariya Podchishchaeva return Slot.asRValue(); 1096992cb984SSergei Barannikov 1097992cb984SSergei Barannikov // The size of the actual thing passed, which might end up just 1098992cb984SSergei Barannikov // being a pointer for indirect types. 1099992cb984SSergei Barannikov auto TyInfo = getContext().getTypeInfoInChars(Ty); 1100992cb984SSergei Barannikov 1101992cb984SSergei Barannikov // Arguments bigger than 16 bytes which aren't homogeneous 1102992cb984SSergei Barannikov // aggregates should be passed indirectly. 1103992cb984SSergei Barannikov bool IsIndirect = false; 1104992cb984SSergei Barannikov if (TyInfo.Width.getQuantity() > 16) { 1105992cb984SSergei Barannikov const Type *Base = nullptr; 1106992cb984SSergei Barannikov uint64_t Members = 0; 1107992cb984SSergei Barannikov IsIndirect = !isHomogeneousAggregate(Ty, Base, Members); 1108992cb984SSergei Barannikov } 1109992cb984SSergei Barannikov 11106d973b45SMariya Podchishchaeva return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo, SlotSize, 11116d973b45SMariya Podchishchaeva /*AllowHigherAlign*/ true, Slot); 1112992cb984SSergei Barannikov } 1113992cb984SSergei Barannikov 11146d973b45SMariya Podchishchaeva RValue AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, 11156d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const { 1116992cb984SSergei Barannikov bool IsIndirect = false; 1117992cb984SSergei Barannikov 1118992cb984SSergei Barannikov // Composites larger than 16 bytes are passed by reference. 1119992cb984SSergei Barannikov if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128) 1120992cb984SSergei Barannikov IsIndirect = true; 1121992cb984SSergei Barannikov 1122992cb984SSergei Barannikov return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, 1123992cb984SSergei Barannikov CGF.getContext().getTypeInfoInChars(Ty), 1124992cb984SSergei Barannikov CharUnits::fromQuantity(8), 11256d973b45SMariya Podchishchaeva /*allowHigherAlign*/ false, Slot); 1126992cb984SSergei Barannikov } 1127992cb984SSergei Barannikov 1128b47f63d3SSam Tebbs static bool isStreamingCompatible(const FunctionDecl *F) { 1129b47f63d3SSam Tebbs if (const auto *T = F->getType()->getAs<FunctionProtoType>()) 1130b47f63d3SSam Tebbs return T->getAArch64SMEAttributes() & 1131b47f63d3SSam Tebbs FunctionType::SME_PStateSMCompatibleMask; 1132b47f63d3SSam Tebbs return false; 1133b47f63d3SSam Tebbs } 1134b47f63d3SSam Tebbs 11351fd196c8Sostannard // Report an error if an argument or return value of type Ty would need to be 11361fd196c8Sostannard // passed in a floating-point register. 11371fd196c8Sostannard static void diagnoseIfNeedsFPReg(DiagnosticsEngine &Diags, 11381fd196c8Sostannard const StringRef ABIName, 11391fd196c8Sostannard const AArch64ABIInfo &ABIInfo, 1140019ef522SJon Roelofs const QualType &Ty, const NamedDecl *D, 1141019ef522SJon Roelofs SourceLocation loc) { 11421fd196c8Sostannard const Type *HABase = nullptr; 11431fd196c8Sostannard uint64_t HAMembers = 0; 11441fd196c8Sostannard if (Ty->isFloatingType() || Ty->isVectorType() || 11451fd196c8Sostannard ABIInfo.isHomogeneousAggregate(Ty, HABase, HAMembers)) { 1146019ef522SJon Roelofs Diags.Report(loc, diag::err_target_unsupported_type_for_abi) 11471fd196c8Sostannard << D->getDeclName() << Ty << ABIName; 11481fd196c8Sostannard } 11491fd196c8Sostannard } 11501fd196c8Sostannard 11511fd196c8Sostannard // If we are using a hard-float ABI, but do not have floating point registers, 11521fd196c8Sostannard // then report an error for any function arguments or returns which would be 11531fd196c8Sostannard // passed in floating-pint registers. 1154ef395a49Sostannard void AArch64TargetCodeGenInfo::checkFunctionABI( 1155ef395a49Sostannard CodeGenModule &CGM, const FunctionDecl *FuncDecl) const { 1156ef395a49Sostannard const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>(); 1157ef395a49Sostannard const TargetInfo &TI = ABIInfo.getContext().getTargetInfo(); 1158ef395a49Sostannard 1159ef395a49Sostannard if (!TI.hasFeature("fp") && !ABIInfo.isSoftFloat()) { 11601fd196c8Sostannard diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, 1161019ef522SJon Roelofs FuncDecl->getReturnType(), FuncDecl, 1162019ef522SJon Roelofs FuncDecl->getLocation()); 1163ef395a49Sostannard for (ParmVarDecl *PVD : FuncDecl->parameters()) { 11641fd196c8Sostannard diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, PVD->getType(), 1165019ef522SJon Roelofs PVD, FuncDecl->getLocation()); 1166ef395a49Sostannard } 1167ef395a49Sostannard } 1168ef395a49Sostannard } 1169ef395a49Sostannard 1170db6f627fSBenjamin Maxwell enum class ArmSMEInlinability : uint8_t { 1171db6f627fSBenjamin Maxwell Ok = 0, 1172db6f627fSBenjamin Maxwell ErrorCalleeRequiresNewZA = 1 << 0, 1173d8d4c187SKerry McLaughlin ErrorCalleeRequiresNewZT0 = 1 << 1, 1174d8d4c187SKerry McLaughlin WarnIncompatibleStreamingModes = 1 << 2, 1175d8d4c187SKerry McLaughlin ErrorIncompatibleStreamingModes = 1 << 3, 1176b47f63d3SSam Tebbs 1177db6f627fSBenjamin Maxwell IncompatibleStreamingModes = 1178db6f627fSBenjamin Maxwell WarnIncompatibleStreamingModes | ErrorIncompatibleStreamingModes, 1179db6f627fSBenjamin Maxwell 1180db6f627fSBenjamin Maxwell LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ErrorIncompatibleStreamingModes), 1181db6f627fSBenjamin Maxwell }; 1182db6f627fSBenjamin Maxwell 1183db6f627fSBenjamin Maxwell /// Determines if there are any Arm SME ABI issues with inlining \p Callee into 1184db6f627fSBenjamin Maxwell /// \p Caller. Returns the issue (if any) in the ArmSMEInlinability bit enum. 1185db6f627fSBenjamin Maxwell static ArmSMEInlinability GetArmSMEInlinability(const FunctionDecl *Caller, 1186db6f627fSBenjamin Maxwell const FunctionDecl *Callee) { 11876a6fcbffSSander de Smalen bool CallerIsStreaming = 11886a6fcbffSSander de Smalen IsArmStreamingFunction(Caller, /*IncludeLocallyStreaming=*/true); 11896a6fcbffSSander de Smalen bool CalleeIsStreaming = 11906a6fcbffSSander de Smalen IsArmStreamingFunction(Callee, /*IncludeLocallyStreaming=*/true); 1191b47f63d3SSam Tebbs bool CallerIsStreamingCompatible = isStreamingCompatible(Caller); 1192b47f63d3SSam Tebbs bool CalleeIsStreamingCompatible = isStreamingCompatible(Callee); 1193b47f63d3SSam Tebbs 1194db6f627fSBenjamin Maxwell ArmSMEInlinability Inlinability = ArmSMEInlinability::Ok; 1195db6f627fSBenjamin Maxwell 1196b47f63d3SSam Tebbs if (!CalleeIsStreamingCompatible && 1197db6f627fSBenjamin Maxwell (CallerIsStreaming != CalleeIsStreaming || CallerIsStreamingCompatible)) { 1198db6f627fSBenjamin Maxwell if (CalleeIsStreaming) 1199db6f627fSBenjamin Maxwell Inlinability |= ArmSMEInlinability::ErrorIncompatibleStreamingModes; 1200db6f627fSBenjamin Maxwell else 1201db6f627fSBenjamin Maxwell Inlinability |= ArmSMEInlinability::WarnIncompatibleStreamingModes; 1202db6f627fSBenjamin Maxwell } 1203d8d4c187SKerry McLaughlin if (auto *NewAttr = Callee->getAttr<ArmNewAttr>()) { 1204db6f627fSBenjamin Maxwell if (NewAttr->isNewZA()) 1205db6f627fSBenjamin Maxwell Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZA; 1206d8d4c187SKerry McLaughlin if (NewAttr->isNewZT0()) 1207d8d4c187SKerry McLaughlin Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZT0; 1208d8d4c187SKerry McLaughlin } 1209db6f627fSBenjamin Maxwell 1210db6f627fSBenjamin Maxwell return Inlinability; 1211db6f627fSBenjamin Maxwell } 1212db6f627fSBenjamin Maxwell 1213db6f627fSBenjamin Maxwell void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming( 1214db6f627fSBenjamin Maxwell CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, 1215db6f627fSBenjamin Maxwell const FunctionDecl *Callee) const { 1216db6f627fSBenjamin Maxwell if (!Caller || !Callee || !Callee->hasAttr<AlwaysInlineAttr>()) 1217db6f627fSBenjamin Maxwell return; 1218db6f627fSBenjamin Maxwell 1219db6f627fSBenjamin Maxwell ArmSMEInlinability Inlinability = GetArmSMEInlinability(Caller, Callee); 1220db6f627fSBenjamin Maxwell 1221db6f627fSBenjamin Maxwell if ((Inlinability & ArmSMEInlinability::IncompatibleStreamingModes) != 1222db6f627fSBenjamin Maxwell ArmSMEInlinability::Ok) 1223389679d5SSander de Smalen CGM.getDiags().Report( 1224db6f627fSBenjamin Maxwell CallLoc, 1225db6f627fSBenjamin Maxwell (Inlinability & ArmSMEInlinability::ErrorIncompatibleStreamingModes) == 1226db6f627fSBenjamin Maxwell ArmSMEInlinability::ErrorIncompatibleStreamingModes 1227389679d5SSander de Smalen ? diag::err_function_always_inline_attribute_mismatch 1228389679d5SSander de Smalen : diag::warn_function_always_inline_attribute_mismatch) 1229b47f63d3SSam Tebbs << Caller->getDeclName() << Callee->getDeclName() << "streaming"; 1230db6f627fSBenjamin Maxwell 1231db6f627fSBenjamin Maxwell if ((Inlinability & ArmSMEInlinability::ErrorCalleeRequiresNewZA) == 1232db6f627fSBenjamin Maxwell ArmSMEInlinability::ErrorCalleeRequiresNewZA) 1233b47f63d3SSam Tebbs CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) 1234b47f63d3SSam Tebbs << Callee->getDeclName(); 1235d8d4c187SKerry McLaughlin 1236d8d4c187SKerry McLaughlin if ((Inlinability & ArmSMEInlinability::ErrorCalleeRequiresNewZT0) == 1237d8d4c187SKerry McLaughlin ArmSMEInlinability::ErrorCalleeRequiresNewZT0) 1238d8d4c187SKerry McLaughlin CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_zt0) 1239d8d4c187SKerry McLaughlin << Callee->getDeclName(); 1240b47f63d3SSam Tebbs } 1241b47f63d3SSam Tebbs 12421fd196c8Sostannard // If the target does not have floating-point registers, but we are using a 12431fd196c8Sostannard // hard-float ABI, there is no way to pass floating-point, vector or HFA values 12441fd196c8Sostannard // to functions, so we report an error. 12451fd196c8Sostannard void AArch64TargetCodeGenInfo::checkFunctionCallABISoftFloat( 12461fd196c8Sostannard CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, 12471fd196c8Sostannard const FunctionDecl *Callee, const CallArgList &Args, 12481fd196c8Sostannard QualType ReturnType) const { 12491fd196c8Sostannard const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>(); 12501fd196c8Sostannard const TargetInfo &TI = ABIInfo.getContext().getTargetInfo(); 12511fd196c8Sostannard 12521fd196c8Sostannard if (!Caller || TI.hasFeature("fp") || ABIInfo.isSoftFloat()) 12531fd196c8Sostannard return; 12541fd196c8Sostannard 12551fd196c8Sostannard diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, ReturnType, 1256019ef522SJon Roelofs Callee ? Callee : Caller, CallLoc); 12571fd196c8Sostannard 12581fd196c8Sostannard for (const CallArg &Arg : Args) 12591fd196c8Sostannard diagnoseIfNeedsFPReg(CGM.getDiags(), TI.getABI(), ABIInfo, Arg.getType(), 1260019ef522SJon Roelofs Callee ? Callee : Caller, CallLoc); 12611fd196c8Sostannard } 12621fd196c8Sostannard 12631fd196c8Sostannard void AArch64TargetCodeGenInfo::checkFunctionCallABI(CodeGenModule &CGM, 12641fd196c8Sostannard SourceLocation CallLoc, 12651fd196c8Sostannard const FunctionDecl *Caller, 12661fd196c8Sostannard const FunctionDecl *Callee, 12671fd196c8Sostannard const CallArgList &Args, 12681fd196c8Sostannard QualType ReturnType) const { 12691fd196c8Sostannard checkFunctionCallABIStreaming(CGM, CallLoc, Caller, Callee); 12701fd196c8Sostannard checkFunctionCallABISoftFloat(CGM, CallLoc, Caller, Callee, Args, ReturnType); 12711fd196c8Sostannard } 12721fd196c8Sostannard 1273db6f627fSBenjamin Maxwell bool AArch64TargetCodeGenInfo::wouldInliningViolateFunctionCallABI( 1274db6f627fSBenjamin Maxwell const FunctionDecl *Caller, const FunctionDecl *Callee) const { 1275db6f627fSBenjamin Maxwell return Caller && Callee && 1276db6f627fSBenjamin Maxwell GetArmSMEInlinability(Caller, Callee) != ArmSMEInlinability::Ok; 1277db6f627fSBenjamin Maxwell } 1278db6f627fSBenjamin Maxwell 1279b42b7c8aSAlexandros Lamprineas void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, 1280b42b7c8aSAlexandros Lamprineas unsigned Index, 1281b42b7c8aSAlexandros Lamprineas raw_ostream &Out) const { 1282b42b7c8aSAlexandros Lamprineas appendAttributeMangling(Attr->getFeatureStr(Index), Out); 1283b42b7c8aSAlexandros Lamprineas } 1284b42b7c8aSAlexandros Lamprineas 1285b42b7c8aSAlexandros Lamprineas void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr, 1286b42b7c8aSAlexandros Lamprineas raw_ostream &Out) const { 1287b42b7c8aSAlexandros Lamprineas if (AttrStr == "default") { 1288b42b7c8aSAlexandros Lamprineas Out << ".default"; 1289b42b7c8aSAlexandros Lamprineas return; 1290b42b7c8aSAlexandros Lamprineas } 1291b42b7c8aSAlexandros Lamprineas 1292b42b7c8aSAlexandros Lamprineas Out << "._"; 1293b42b7c8aSAlexandros Lamprineas SmallVector<StringRef, 8> Features; 1294b42b7c8aSAlexandros Lamprineas AttrStr.split(Features, "+"); 1295b42b7c8aSAlexandros Lamprineas for (auto &Feat : Features) 1296b42b7c8aSAlexandros Lamprineas Feat = Feat.trim(); 1297b42b7c8aSAlexandros Lamprineas 12986ed67ca1SJie Fu llvm::sort(Features, [](const StringRef LHS, const StringRef RHS) { 1299e81ef463SAlexandros Lamprineas return LHS.compare(RHS) < 0; 1300b42b7c8aSAlexandros Lamprineas }); 1301b42b7c8aSAlexandros Lamprineas 13026f54a54cSAlexandros Lamprineas llvm::SmallDenseSet<StringRef, 8> UniqueFeats; 1303b42b7c8aSAlexandros Lamprineas for (auto &Feat : Features) 1304fa6d38d6STomas Matheson if (auto Ext = llvm::AArch64::parseFMVExtension(Feat)) 13056f54a54cSAlexandros Lamprineas if (UniqueFeats.insert(Ext->Name).second) 1306b42b7c8aSAlexandros Lamprineas Out << 'M' << Ext->Name; 1307b42b7c8aSAlexandros Lamprineas } 1308b42b7c8aSAlexandros Lamprineas 1309992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 1310992cb984SSergei Barannikov CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM, 1311992cb984SSergei Barannikov AArch64ABIKind Kind) { 1312992cb984SSergei Barannikov return std::make_unique<AArch64TargetCodeGenInfo>(CGM.getTypes(), Kind); 1313992cb984SSergei Barannikov } 1314992cb984SSergei Barannikov 1315992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 1316992cb984SSergei Barannikov CodeGen::createWindowsAArch64TargetCodeGenInfo(CodeGenModule &CGM, 1317992cb984SSergei Barannikov AArch64ABIKind K) { 1318992cb984SSergei Barannikov return std::make_unique<WindowsAArch64TargetCodeGenInfo>(CGM.getTypes(), K); 1319992cb984SSergei Barannikov } 1320