1992cb984SSergei Barannikov //===- ARM.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" 11992cb984SSergei Barannikov 12992cb984SSergei Barannikov using namespace clang; 13992cb984SSergei Barannikov using namespace clang::CodeGen; 14992cb984SSergei Barannikov 15992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 16992cb984SSergei Barannikov // ARM ABI Implementation 17992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 18992cb984SSergei Barannikov 19992cb984SSergei Barannikov namespace { 20992cb984SSergei Barannikov 21992cb984SSergei Barannikov class ARMABIInfo : public ABIInfo { 22992cb984SSergei Barannikov ARMABIKind Kind; 23992cb984SSergei Barannikov bool IsFloatABISoftFP; 24992cb984SSergei Barannikov 25992cb984SSergei Barannikov public: 26992cb984SSergei Barannikov ARMABIInfo(CodeGenTypes &CGT, ARMABIKind Kind) : ABIInfo(CGT), Kind(Kind) { 27992cb984SSergei Barannikov setCCs(); 28992cb984SSergei Barannikov IsFloatABISoftFP = CGT.getCodeGenOpts().FloatABI == "softfp" || 29992cb984SSergei Barannikov CGT.getCodeGenOpts().FloatABI == ""; // default 30992cb984SSergei Barannikov } 31992cb984SSergei Barannikov 32992cb984SSergei Barannikov bool isEABI() const { 33992cb984SSergei Barannikov switch (getTarget().getTriple().getEnvironment()) { 34992cb984SSergei Barannikov case llvm::Triple::Android: 35992cb984SSergei Barannikov case llvm::Triple::EABI: 36992cb984SSergei Barannikov case llvm::Triple::EABIHF: 37992cb984SSergei Barannikov case llvm::Triple::GNUEABI: 38*387b37afSMichał Górny case llvm::Triple::GNUEABIT64: 39992cb984SSergei Barannikov case llvm::Triple::GNUEABIHF: 40*387b37afSMichał Górny case llvm::Triple::GNUEABIHFT64: 41992cb984SSergei Barannikov case llvm::Triple::MuslEABI: 42992cb984SSergei Barannikov case llvm::Triple::MuslEABIHF: 43992cb984SSergei Barannikov return true; 44992cb984SSergei Barannikov default: 45992cb984SSergei Barannikov return getTarget().getTriple().isOHOSFamily(); 46992cb984SSergei Barannikov } 47992cb984SSergei Barannikov } 48992cb984SSergei Barannikov 49992cb984SSergei Barannikov bool isEABIHF() const { 50992cb984SSergei Barannikov switch (getTarget().getTriple().getEnvironment()) { 51992cb984SSergei Barannikov case llvm::Triple::EABIHF: 52992cb984SSergei Barannikov case llvm::Triple::GNUEABIHF: 53*387b37afSMichał Górny case llvm::Triple::GNUEABIHFT64: 54992cb984SSergei Barannikov case llvm::Triple::MuslEABIHF: 55992cb984SSergei Barannikov return true; 56992cb984SSergei Barannikov default: 57992cb984SSergei Barannikov return false; 58992cb984SSergei Barannikov } 59992cb984SSergei Barannikov } 60992cb984SSergei Barannikov 61992cb984SSergei Barannikov ARMABIKind getABIKind() const { return Kind; } 62992cb984SSergei Barannikov 63992cb984SSergei Barannikov bool allowBFloatArgsAndRet() const override { 64992cb984SSergei Barannikov return !IsFloatABISoftFP && getTarget().hasBFloat16Type(); 65992cb984SSergei Barannikov } 66992cb984SSergei Barannikov 67992cb984SSergei Barannikov private: 68992cb984SSergei Barannikov ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic, 69992cb984SSergei Barannikov unsigned functionCallConv) const; 70992cb984SSergei Barannikov ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic, 71992cb984SSergei Barannikov unsigned functionCallConv) const; 72992cb984SSergei Barannikov ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base, 73992cb984SSergei Barannikov uint64_t Members) const; 74992cb984SSergei Barannikov ABIArgInfo coerceIllegalVector(QualType Ty) const; 75992cb984SSergei Barannikov bool isIllegalVectorType(QualType Ty) const; 76992cb984SSergei Barannikov bool containsAnyFP16Vectors(QualType Ty) const; 77992cb984SSergei Barannikov 78992cb984SSergei Barannikov bool isHomogeneousAggregateBaseType(QualType Ty) const override; 79992cb984SSergei Barannikov bool isHomogeneousAggregateSmallEnough(const Type *Ty, 80992cb984SSergei Barannikov uint64_t Members) const override; 81992cb984SSergei Barannikov bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; 82992cb984SSergei Barannikov 83992cb984SSergei Barannikov bool isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const; 84992cb984SSergei Barannikov 85992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override; 86992cb984SSergei Barannikov 876d973b45SMariya Podchishchaeva RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 886d973b45SMariya Podchishchaeva AggValueSlot Slot) const override; 89992cb984SSergei Barannikov 90992cb984SSergei Barannikov llvm::CallingConv::ID getLLVMDefaultCC() const; 91992cb984SSergei Barannikov llvm::CallingConv::ID getABIDefaultCC() const; 92992cb984SSergei Barannikov void setCCs(); 93992cb984SSergei Barannikov }; 94992cb984SSergei Barannikov 95992cb984SSergei Barannikov class ARMSwiftABIInfo : public SwiftABIInfo { 96992cb984SSergei Barannikov public: 97992cb984SSergei Barannikov explicit ARMSwiftABIInfo(CodeGenTypes &CGT) 98992cb984SSergei Barannikov : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {} 99992cb984SSergei Barannikov 100992cb984SSergei Barannikov bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, 101992cb984SSergei Barannikov unsigned NumElts) const override; 102992cb984SSergei Barannikov }; 103992cb984SSergei Barannikov 104992cb984SSergei Barannikov class ARMTargetCodeGenInfo : public TargetCodeGenInfo { 105992cb984SSergei Barannikov public: 106992cb984SSergei Barannikov ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) 107992cb984SSergei Barannikov : TargetCodeGenInfo(std::make_unique<ARMABIInfo>(CGT, K)) { 108992cb984SSergei Barannikov SwiftInfo = std::make_unique<ARMSwiftABIInfo>(CGT); 109992cb984SSergei Barannikov } 110992cb984SSergei Barannikov 111992cb984SSergei Barannikov int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 112992cb984SSergei Barannikov return 13; 113992cb984SSergei Barannikov } 114992cb984SSergei Barannikov 115992cb984SSergei Barannikov StringRef getARCRetainAutoreleasedReturnValueMarker() const override { 116992cb984SSergei Barannikov return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue"; 117992cb984SSergei Barannikov } 118992cb984SSergei Barannikov 119992cb984SSergei Barannikov bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 120992cb984SSergei Barannikov llvm::Value *Address) const override { 121992cb984SSergei Barannikov llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4); 122992cb984SSergei Barannikov 123992cb984SSergei Barannikov // 0-15 are the 16 integer registers. 124992cb984SSergei Barannikov AssignToArrayRange(CGF.Builder, Address, Four8, 0, 15); 125992cb984SSergei Barannikov return false; 126992cb984SSergei Barannikov } 127992cb984SSergei Barannikov 128992cb984SSergei Barannikov unsigned getSizeOfUnwindException() const override { 129992cb984SSergei Barannikov if (getABIInfo<ARMABIInfo>().isEABI()) 130992cb984SSergei Barannikov return 88; 131992cb984SSergei Barannikov return TargetCodeGenInfo::getSizeOfUnwindException(); 132992cb984SSergei Barannikov } 133992cb984SSergei Barannikov 134992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 135992cb984SSergei Barannikov CodeGen::CodeGenModule &CGM) const override { 136992cb984SSergei Barannikov if (GV->isDeclaration()) 137992cb984SSergei Barannikov return; 138992cb984SSergei Barannikov const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 139992cb984SSergei Barannikov if (!FD) 140992cb984SSergei Barannikov return; 141992cb984SSergei Barannikov auto *Fn = cast<llvm::Function>(GV); 142992cb984SSergei Barannikov 143992cb984SSergei Barannikov if (const auto *TA = FD->getAttr<TargetAttr>()) { 144992cb984SSergei Barannikov ParsedTargetAttr Attr = 145992cb984SSergei Barannikov CGM.getTarget().parseTargetAttr(TA->getFeaturesStr()); 146992cb984SSergei Barannikov if (!Attr.BranchProtection.empty()) { 147e03f6651SDaniel Kiss TargetInfo::BranchProtectionInfo BPI{}; 148992cb984SSergei Barannikov StringRef DiagMsg; 149992cb984SSergei Barannikov StringRef Arch = 150992cb984SSergei Barannikov Attr.CPU.empty() ? CGM.getTarget().getTargetOpts().CPU : Attr.CPU; 151992cb984SSergei Barannikov if (!CGM.getTarget().validateBranchProtection(Attr.BranchProtection, 152992cb984SSergei Barannikov Arch, BPI, DiagMsg)) { 153992cb984SSergei Barannikov CGM.getDiags().Report( 154992cb984SSergei Barannikov D->getLocation(), 155992cb984SSergei Barannikov diag::warn_target_unsupported_branch_protection_attribute) 156992cb984SSergei Barannikov << Arch; 157f34a1654SDaniel Kiss } else 158f34a1654SDaniel Kiss setBranchProtectionFnAttributes(BPI, (*Fn)); 159992cb984SSergei Barannikov } else if (CGM.getLangOpts().BranchTargetEnforcement || 160992cb984SSergei Barannikov CGM.getLangOpts().hasSignReturnAddress()) { 161992cb984SSergei Barannikov // If the Branch Protection attribute is missing, validate the target 162992cb984SSergei Barannikov // Architecture attribute against Branch Protection command line 163992cb984SSergei Barannikov // settings. 164992cb984SSergei Barannikov if (!CGM.getTarget().isBranchProtectionSupportedArch(Attr.CPU)) 165992cb984SSergei Barannikov CGM.getDiags().Report( 166992cb984SSergei Barannikov D->getLocation(), 167992cb984SSergei Barannikov diag::warn_target_unsupported_branch_protection_attribute) 168992cb984SSergei Barannikov << Attr.CPU; 169992cb984SSergei Barannikov } 1701782810bSDaniel Kiss } else if (CGM.getTarget().isBranchProtectionSupportedArch( 1711782810bSDaniel Kiss CGM.getTarget().getTargetOpts().CPU)) { 1721782810bSDaniel Kiss TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts()); 173f34a1654SDaniel Kiss setBranchProtectionFnAttributes(BPI, (*Fn)); 174992cb984SSergei Barannikov } 175992cb984SSergei Barannikov 176992cb984SSergei Barannikov const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); 177992cb984SSergei Barannikov if (!Attr) 178992cb984SSergei Barannikov return; 179992cb984SSergei Barannikov 180992cb984SSergei Barannikov const char *Kind; 181992cb984SSergei Barannikov switch (Attr->getInterrupt()) { 182992cb984SSergei Barannikov case ARMInterruptAttr::Generic: Kind = ""; break; 183992cb984SSergei Barannikov case ARMInterruptAttr::IRQ: Kind = "IRQ"; break; 184992cb984SSergei Barannikov case ARMInterruptAttr::FIQ: Kind = "FIQ"; break; 185992cb984SSergei Barannikov case ARMInterruptAttr::SWI: Kind = "SWI"; break; 186992cb984SSergei Barannikov case ARMInterruptAttr::ABORT: Kind = "ABORT"; break; 187992cb984SSergei Barannikov case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break; 188992cb984SSergei Barannikov } 189992cb984SSergei Barannikov 190992cb984SSergei Barannikov Fn->addFnAttr("interrupt", Kind); 191992cb984SSergei Barannikov 192992cb984SSergei Barannikov ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind(); 193992cb984SSergei Barannikov if (ABI == ARMABIKind::APCS) 194992cb984SSergei Barannikov return; 195992cb984SSergei Barannikov 196992cb984SSergei Barannikov // AAPCS guarantees that sp will be 8-byte aligned on any public interface, 197992cb984SSergei Barannikov // however this is not necessarily true on taking any interrupt. Instruct 198992cb984SSergei Barannikov // the backend to perform a realignment as part of the function prologue. 199992cb984SSergei Barannikov llvm::AttrBuilder B(Fn->getContext()); 200992cb984SSergei Barannikov B.addStackAlignmentAttr(8); 201992cb984SSergei Barannikov Fn->addFnAttrs(B); 202992cb984SSergei Barannikov } 203992cb984SSergei Barannikov }; 204992cb984SSergei Barannikov 205992cb984SSergei Barannikov class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo { 206992cb984SSergei Barannikov public: 207992cb984SSergei Barannikov WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) 208992cb984SSergei Barannikov : ARMTargetCodeGenInfo(CGT, K) {} 209992cb984SSergei Barannikov 210992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 211992cb984SSergei Barannikov CodeGen::CodeGenModule &CGM) const override; 212992cb984SSergei Barannikov 213992cb984SSergei Barannikov void getDependentLibraryOption(llvm::StringRef Lib, 214992cb984SSergei Barannikov llvm::SmallString<24> &Opt) const override { 215992cb984SSergei Barannikov Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); 216992cb984SSergei Barannikov } 217992cb984SSergei Barannikov 218992cb984SSergei Barannikov void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, 219992cb984SSergei Barannikov llvm::SmallString<32> &Opt) const override { 220992cb984SSergei Barannikov Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; 221992cb984SSergei Barannikov } 222992cb984SSergei Barannikov }; 223992cb984SSergei Barannikov 224992cb984SSergei Barannikov void WindowsARMTargetCodeGenInfo::setTargetAttributes( 225992cb984SSergei Barannikov const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { 226992cb984SSergei Barannikov ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM); 227992cb984SSergei Barannikov if (GV->isDeclaration()) 228992cb984SSergei Barannikov return; 229992cb984SSergei Barannikov addStackProbeTargetAttributes(D, GV, CGM); 230992cb984SSergei Barannikov } 231992cb984SSergei Barannikov } 232992cb984SSergei Barannikov 233992cb984SSergei Barannikov void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { 234992cb984SSergei Barannikov if (!::classifyReturnType(getCXXABI(), FI, *this)) 235992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic(), 236992cb984SSergei Barannikov FI.getCallingConvention()); 237992cb984SSergei Barannikov 238992cb984SSergei Barannikov for (auto &I : FI.arguments()) 239992cb984SSergei Barannikov I.info = classifyArgumentType(I.type, FI.isVariadic(), 240992cb984SSergei Barannikov FI.getCallingConvention()); 241992cb984SSergei Barannikov 242992cb984SSergei Barannikov 243992cb984SSergei Barannikov // Always honor user-specified calling convention. 244992cb984SSergei Barannikov if (FI.getCallingConvention() != llvm::CallingConv::C) 245992cb984SSergei Barannikov return; 246992cb984SSergei Barannikov 247992cb984SSergei Barannikov llvm::CallingConv::ID cc = getRuntimeCC(); 248992cb984SSergei Barannikov if (cc != llvm::CallingConv::C) 249992cb984SSergei Barannikov FI.setEffectiveCallingConvention(cc); 250992cb984SSergei Barannikov } 251992cb984SSergei Barannikov 252992cb984SSergei Barannikov /// Return the default calling convention that LLVM will use. 253992cb984SSergei Barannikov llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const { 254992cb984SSergei Barannikov // The default calling convention that LLVM will infer. 255992cb984SSergei Barannikov if (isEABIHF() || getTarget().getTriple().isWatchABI()) 256992cb984SSergei Barannikov return llvm::CallingConv::ARM_AAPCS_VFP; 257992cb984SSergei Barannikov else if (isEABI()) 258992cb984SSergei Barannikov return llvm::CallingConv::ARM_AAPCS; 259992cb984SSergei Barannikov else 260992cb984SSergei Barannikov return llvm::CallingConv::ARM_APCS; 261992cb984SSergei Barannikov } 262992cb984SSergei Barannikov 263992cb984SSergei Barannikov /// Return the calling convention that our ABI would like us to use 264992cb984SSergei Barannikov /// as the C calling convention. 265992cb984SSergei Barannikov llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const { 266992cb984SSergei Barannikov switch (getABIKind()) { 267992cb984SSergei Barannikov case ARMABIKind::APCS: 268992cb984SSergei Barannikov return llvm::CallingConv::ARM_APCS; 269992cb984SSergei Barannikov case ARMABIKind::AAPCS: 270992cb984SSergei Barannikov return llvm::CallingConv::ARM_AAPCS; 271992cb984SSergei Barannikov case ARMABIKind::AAPCS_VFP: 272992cb984SSergei Barannikov return llvm::CallingConv::ARM_AAPCS_VFP; 273992cb984SSergei Barannikov case ARMABIKind::AAPCS16_VFP: 274992cb984SSergei Barannikov return llvm::CallingConv::ARM_AAPCS_VFP; 275992cb984SSergei Barannikov } 276992cb984SSergei Barannikov llvm_unreachable("bad ABI kind"); 277992cb984SSergei Barannikov } 278992cb984SSergei Barannikov 279992cb984SSergei Barannikov void ARMABIInfo::setCCs() { 280992cb984SSergei Barannikov assert(getRuntimeCC() == llvm::CallingConv::C); 281992cb984SSergei Barannikov 282992cb984SSergei Barannikov // Don't muddy up the IR with a ton of explicit annotations if 283992cb984SSergei Barannikov // they'd just match what LLVM will infer from the triple. 284992cb984SSergei Barannikov llvm::CallingConv::ID abiCC = getABIDefaultCC(); 285992cb984SSergei Barannikov if (abiCC != getLLVMDefaultCC()) 286992cb984SSergei Barannikov RuntimeCC = abiCC; 287992cb984SSergei Barannikov } 288992cb984SSergei Barannikov 289992cb984SSergei Barannikov ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const { 290992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(Ty); 291992cb984SSergei Barannikov if (Size <= 32) { 292992cb984SSergei Barannikov llvm::Type *ResType = 293992cb984SSergei Barannikov llvm::Type::getInt32Ty(getVMContext()); 294992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 295992cb984SSergei Barannikov } 296992cb984SSergei Barannikov if (Size == 64 || Size == 128) { 297992cb984SSergei Barannikov auto *ResType = llvm::FixedVectorType::get( 298992cb984SSergei Barannikov llvm::Type::getInt32Ty(getVMContext()), Size / 32); 299992cb984SSergei Barannikov return ABIArgInfo::getDirect(ResType); 300992cb984SSergei Barannikov } 301992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 302992cb984SSergei Barannikov } 303992cb984SSergei Barannikov 304992cb984SSergei Barannikov ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty, 305992cb984SSergei Barannikov const Type *Base, 306992cb984SSergei Barannikov uint64_t Members) const { 307992cb984SSergei Barannikov assert(Base && "Base class should be set for homogeneous aggregate"); 308992cb984SSergei Barannikov // Base can be a floating-point or a vector. 309992cb984SSergei Barannikov if (const VectorType *VT = Base->getAs<VectorType>()) { 310992cb984SSergei Barannikov // FP16 vectors should be converted to integer vectors 311992cb984SSergei Barannikov if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) { 312992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(VT); 313992cb984SSergei Barannikov auto *NewVecTy = llvm::FixedVectorType::get( 314992cb984SSergei Barannikov llvm::Type::getInt32Ty(getVMContext()), Size / 32); 315992cb984SSergei Barannikov llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members); 316992cb984SSergei Barannikov return ABIArgInfo::getDirect(Ty, 0, nullptr, false); 317992cb984SSergei Barannikov } 318992cb984SSergei Barannikov } 319992cb984SSergei Barannikov unsigned Align = 0; 320992cb984SSergei Barannikov if (getABIKind() == ARMABIKind::AAPCS || 321992cb984SSergei Barannikov getABIKind() == ARMABIKind::AAPCS_VFP) { 322992cb984SSergei Barannikov // For alignment adjusted HFAs, cap the argument alignment to 8, leave it 323992cb984SSergei Barannikov // default otherwise. 324992cb984SSergei Barannikov Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); 325992cb984SSergei Barannikov unsigned BaseAlign = getContext().getTypeAlignInChars(Base).getQuantity(); 326992cb984SSergei Barannikov Align = (Align > BaseAlign && Align >= 8) ? 8 : 0; 327992cb984SSergei Barannikov } 328992cb984SSergei Barannikov return ABIArgInfo::getDirect(nullptr, 0, nullptr, false, Align); 329992cb984SSergei Barannikov } 330992cb984SSergei Barannikov 331992cb984SSergei Barannikov ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, 332992cb984SSergei Barannikov unsigned functionCallConv) const { 333992cb984SSergei Barannikov // 6.1.2.1 The following argument types are VFP CPRCs: 334992cb984SSergei Barannikov // A single-precision floating-point type (including promoted 335992cb984SSergei Barannikov // half-precision types); A double-precision floating-point type; 336992cb984SSergei Barannikov // A 64-bit or 128-bit containerized vector type; Homogeneous Aggregate 337992cb984SSergei Barannikov // with a Base Type of a single- or double-precision floating-point type, 338992cb984SSergei Barannikov // 64-bit containerized vectors or 128-bit containerized vectors with one 339992cb984SSergei Barannikov // to four Elements. 340992cb984SSergei Barannikov // Variadic functions should always marshal to the base standard. 341992cb984SSergei Barannikov bool IsAAPCS_VFP = 342992cb984SSergei Barannikov !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ false); 343992cb984SSergei Barannikov 344992cb984SSergei Barannikov Ty = useFirstFieldIfTransparentUnion(Ty); 345992cb984SSergei Barannikov 346992cb984SSergei Barannikov // Handle illegal vector types here. 347992cb984SSergei Barannikov if (isIllegalVectorType(Ty)) 348992cb984SSergei Barannikov return coerceIllegalVector(Ty); 349992cb984SSergei Barannikov 350992cb984SSergei Barannikov if (!isAggregateTypeForABI(Ty)) { 351992cb984SSergei Barannikov // Treat an enum type as its underlying type. 352992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { 353992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 354992cb984SSergei Barannikov } 355992cb984SSergei Barannikov 356992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) 357992cb984SSergei Barannikov if (EIT->getNumBits() > 64) 358992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/true); 359992cb984SSergei Barannikov 360ea920450SLei Huang return (isPromotableIntegerTypeForABI(Ty) 361ea920450SLei Huang ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) 362992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 363992cb984SSergei Barannikov } 364992cb984SSergei Barannikov 365992cb984SSergei Barannikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 366992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 367992cb984SSergei Barannikov } 368992cb984SSergei Barannikov 369992cb984SSergei Barannikov // Ignore empty records. 370992cb984SSergei Barannikov if (isEmptyRecord(getContext(), Ty, true)) 371992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 372992cb984SSergei Barannikov 373992cb984SSergei Barannikov if (IsAAPCS_VFP) { 374992cb984SSergei Barannikov // Homogeneous Aggregates need to be expanded when we can fit the aggregate 375992cb984SSergei Barannikov // into VFP registers. 376992cb984SSergei Barannikov const Type *Base = nullptr; 377992cb984SSergei Barannikov uint64_t Members = 0; 378992cb984SSergei Barannikov if (isHomogeneousAggregate(Ty, Base, Members)) 379992cb984SSergei Barannikov return classifyHomogeneousAggregate(Ty, Base, Members); 380992cb984SSergei Barannikov } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { 381992cb984SSergei Barannikov // WatchOS does have homogeneous aggregates. Note that we intentionally use 382992cb984SSergei Barannikov // this convention even for a variadic function: the backend will use GPRs 383992cb984SSergei Barannikov // if needed. 384992cb984SSergei Barannikov const Type *Base = nullptr; 385992cb984SSergei Barannikov uint64_t Members = 0; 386992cb984SSergei Barannikov if (isHomogeneousAggregate(Ty, Base, Members)) { 387992cb984SSergei Barannikov assert(Base && Members <= 4 && "unexpected homogeneous aggregate"); 388992cb984SSergei Barannikov llvm::Type *Ty = 389992cb984SSergei Barannikov llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members); 390992cb984SSergei Barannikov return ABIArgInfo::getDirect(Ty, 0, nullptr, false); 391992cb984SSergei Barannikov } 392992cb984SSergei Barannikov } 393992cb984SSergei Barannikov 394992cb984SSergei Barannikov if (getABIKind() == ARMABIKind::AAPCS16_VFP && 395992cb984SSergei Barannikov getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(16)) { 396992cb984SSergei Barannikov // WatchOS is adopting the 64-bit AAPCS rule on composite types: if they're 397992cb984SSergei Barannikov // bigger than 128-bits, they get placed in space allocated by the caller, 398992cb984SSergei Barannikov // and a pointer is passed. 399992cb984SSergei Barannikov return ABIArgInfo::getIndirect( 400992cb984SSergei Barannikov CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), false); 401992cb984SSergei Barannikov } 402992cb984SSergei Barannikov 403992cb984SSergei Barannikov // Support byval for ARM. 404992cb984SSergei Barannikov // The ABI alignment for APCS is 4-byte and for AAPCS at least 4-byte and at 405992cb984SSergei Barannikov // most 8-byte. We realign the indirect argument if type alignment is bigger 406992cb984SSergei Barannikov // than ABI alignment. 407992cb984SSergei Barannikov uint64_t ABIAlign = 4; 408992cb984SSergei Barannikov uint64_t TyAlign; 409992cb984SSergei Barannikov if (getABIKind() == ARMABIKind::AAPCS_VFP || 410992cb984SSergei Barannikov getABIKind() == ARMABIKind::AAPCS) { 411992cb984SSergei Barannikov TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); 412992cb984SSergei Barannikov ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8); 413992cb984SSergei Barannikov } else { 414992cb984SSergei Barannikov TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); 415992cb984SSergei Barannikov } 416992cb984SSergei Barannikov if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) { 417992cb984SSergei Barannikov assert(getABIKind() != ARMABIKind::AAPCS16_VFP && "unexpected byval"); 418992cb984SSergei Barannikov return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), 419992cb984SSergei Barannikov /*ByVal=*/true, 420992cb984SSergei Barannikov /*Realign=*/TyAlign > ABIAlign); 421992cb984SSergei Barannikov } 422992cb984SSergei Barannikov 423992cb984SSergei Barannikov // Otherwise, pass by coercing to a structure of the appropriate size. 424992cb984SSergei Barannikov llvm::Type* ElemTy; 425992cb984SSergei Barannikov unsigned SizeRegs; 426992cb984SSergei Barannikov // FIXME: Try to match the types of the arguments more accurately where 427992cb984SSergei Barannikov // we can. 428992cb984SSergei Barannikov if (TyAlign <= 4) { 429992cb984SSergei Barannikov ElemTy = llvm::Type::getInt32Ty(getVMContext()); 430992cb984SSergei Barannikov SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; 431992cb984SSergei Barannikov } else { 432992cb984SSergei Barannikov ElemTy = llvm::Type::getInt64Ty(getVMContext()); 433992cb984SSergei Barannikov SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; 434992cb984SSergei Barannikov } 435992cb984SSergei Barannikov 436992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs)); 437992cb984SSergei Barannikov } 438992cb984SSergei Barannikov 439992cb984SSergei Barannikov static bool isIntegerLikeType(QualType Ty, ASTContext &Context, 440992cb984SSergei Barannikov llvm::LLVMContext &VMContext) { 441992cb984SSergei Barannikov // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure 442992cb984SSergei Barannikov // is called integer-like if its size is less than or equal to one word, and 443992cb984SSergei Barannikov // the offset of each of its addressable sub-fields is zero. 444992cb984SSergei Barannikov 445992cb984SSergei Barannikov uint64_t Size = Context.getTypeSize(Ty); 446992cb984SSergei Barannikov 447992cb984SSergei Barannikov // Check that the type fits in a word. 448992cb984SSergei Barannikov if (Size > 32) 449992cb984SSergei Barannikov return false; 450992cb984SSergei Barannikov 451992cb984SSergei Barannikov // FIXME: Handle vector types! 452992cb984SSergei Barannikov if (Ty->isVectorType()) 453992cb984SSergei Barannikov return false; 454992cb984SSergei Barannikov 455992cb984SSergei Barannikov // Float types are never treated as "integer like". 456992cb984SSergei Barannikov if (Ty->isRealFloatingType()) 457992cb984SSergei Barannikov return false; 458992cb984SSergei Barannikov 459992cb984SSergei Barannikov // If this is a builtin or pointer type then it is ok. 460992cb984SSergei Barannikov if (Ty->getAs<BuiltinType>() || Ty->isPointerType()) 461992cb984SSergei Barannikov return true; 462992cb984SSergei Barannikov 463992cb984SSergei Barannikov // Small complex integer types are "integer like". 464992cb984SSergei Barannikov if (const ComplexType *CT = Ty->getAs<ComplexType>()) 465992cb984SSergei Barannikov return isIntegerLikeType(CT->getElementType(), Context, VMContext); 466992cb984SSergei Barannikov 467992cb984SSergei Barannikov // Single element and zero sized arrays should be allowed, by the definition 468992cb984SSergei Barannikov // above, but they are not. 469992cb984SSergei Barannikov 470992cb984SSergei Barannikov // Otherwise, it must be a record type. 471992cb984SSergei Barannikov const RecordType *RT = Ty->getAs<RecordType>(); 472992cb984SSergei Barannikov if (!RT) return false; 473992cb984SSergei Barannikov 474992cb984SSergei Barannikov // Ignore records with flexible arrays. 475992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 476992cb984SSergei Barannikov if (RD->hasFlexibleArrayMember()) 477992cb984SSergei Barannikov return false; 478992cb984SSergei Barannikov 479992cb984SSergei Barannikov // Check that all sub-fields are at offset 0, and are themselves "integer 480992cb984SSergei Barannikov // like". 481992cb984SSergei Barannikov const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); 482992cb984SSergei Barannikov 483992cb984SSergei Barannikov bool HadField = false; 484992cb984SSergei Barannikov unsigned idx = 0; 485992cb984SSergei Barannikov for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); 486992cb984SSergei Barannikov i != e; ++i, ++idx) { 487992cb984SSergei Barannikov const FieldDecl *FD = *i; 488992cb984SSergei Barannikov 489992cb984SSergei Barannikov // Bit-fields are not addressable, we only need to verify they are "integer 490992cb984SSergei Barannikov // like". We still have to disallow a subsequent non-bitfield, for example: 491992cb984SSergei Barannikov // struct { int : 0; int x } 492992cb984SSergei Barannikov // is non-integer like according to gcc. 493992cb984SSergei Barannikov if (FD->isBitField()) { 494992cb984SSergei Barannikov if (!RD->isUnion()) 495992cb984SSergei Barannikov HadField = true; 496992cb984SSergei Barannikov 497992cb984SSergei Barannikov if (!isIntegerLikeType(FD->getType(), Context, VMContext)) 498992cb984SSergei Barannikov return false; 499992cb984SSergei Barannikov 500992cb984SSergei Barannikov continue; 501992cb984SSergei Barannikov } 502992cb984SSergei Barannikov 503992cb984SSergei Barannikov // Check if this field is at offset 0. 504992cb984SSergei Barannikov if (Layout.getFieldOffset(idx) != 0) 505992cb984SSergei Barannikov return false; 506992cb984SSergei Barannikov 507992cb984SSergei Barannikov if (!isIntegerLikeType(FD->getType(), Context, VMContext)) 508992cb984SSergei Barannikov return false; 509992cb984SSergei Barannikov 510992cb984SSergei Barannikov // Only allow at most one field in a structure. This doesn't match the 511992cb984SSergei Barannikov // wording above, but follows gcc in situations with a field following an 512992cb984SSergei Barannikov // empty structure. 513992cb984SSergei Barannikov if (!RD->isUnion()) { 514992cb984SSergei Barannikov if (HadField) 515992cb984SSergei Barannikov return false; 516992cb984SSergei Barannikov 517992cb984SSergei Barannikov HadField = true; 518992cb984SSergei Barannikov } 519992cb984SSergei Barannikov } 520992cb984SSergei Barannikov 521992cb984SSergei Barannikov return true; 522992cb984SSergei Barannikov } 523992cb984SSergei Barannikov 524992cb984SSergei Barannikov ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, 525992cb984SSergei Barannikov unsigned functionCallConv) const { 526992cb984SSergei Barannikov 527992cb984SSergei Barannikov // Variadic functions should always marshal to the base standard. 528992cb984SSergei Barannikov bool IsAAPCS_VFP = 529992cb984SSergei Barannikov !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ true); 530992cb984SSergei Barannikov 531992cb984SSergei Barannikov if (RetTy->isVoidType()) 532992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 533992cb984SSergei Barannikov 534992cb984SSergei Barannikov if (const VectorType *VT = RetTy->getAs<VectorType>()) { 535992cb984SSergei Barannikov // Large vector types should be returned via memory. 536992cb984SSergei Barannikov if (getContext().getTypeSize(RetTy) > 128) 537992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 538992cb984SSergei Barannikov // TODO: FP16/BF16 vectors should be converted to integer vectors 539992cb984SSergei Barannikov // This check is similar to isIllegalVectorType - refactor? 540992cb984SSergei Barannikov if ((!getTarget().hasLegalHalfType() && 541992cb984SSergei Barannikov (VT->getElementType()->isFloat16Type() || 542992cb984SSergei Barannikov VT->getElementType()->isHalfType())) || 543992cb984SSergei Barannikov (IsFloatABISoftFP && 544992cb984SSergei Barannikov VT->getElementType()->isBFloat16Type())) 545992cb984SSergei Barannikov return coerceIllegalVector(RetTy); 546992cb984SSergei Barannikov } 547992cb984SSergei Barannikov 548992cb984SSergei Barannikov if (!isAggregateTypeForABI(RetTy)) { 549992cb984SSergei Barannikov // Treat an enum type as its underlying type. 550992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 551992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType(); 552992cb984SSergei Barannikov 553992cb984SSergei Barannikov if (const auto *EIT = RetTy->getAs<BitIntType>()) 554992cb984SSergei Barannikov if (EIT->getNumBits() > 64) 555992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); 556992cb984SSergei Barannikov 557992cb984SSergei Barannikov return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 558992cb984SSergei Barannikov : ABIArgInfo::getDirect(); 559992cb984SSergei Barannikov } 560992cb984SSergei Barannikov 561992cb984SSergei Barannikov // Are we following APCS? 562992cb984SSergei Barannikov if (getABIKind() == ARMABIKind::APCS) { 563992cb984SSergei Barannikov if (isEmptyRecord(getContext(), RetTy, false)) 564992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 565992cb984SSergei Barannikov 566992cb984SSergei Barannikov // Complex types are all returned as packed integers. 567992cb984SSergei Barannikov // 568992cb984SSergei Barannikov // FIXME: Consider using 2 x vector types if the back end handles them 569992cb984SSergei Barannikov // correctly. 570992cb984SSergei Barannikov if (RetTy->isAnyComplexType()) 571992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::IntegerType::get( 572992cb984SSergei Barannikov getVMContext(), getContext().getTypeSize(RetTy))); 573992cb984SSergei Barannikov 574992cb984SSergei Barannikov // Integer like structures are returned in r0. 575992cb984SSergei Barannikov if (isIntegerLikeType(RetTy, getContext(), getVMContext())) { 576992cb984SSergei Barannikov // Return in the smallest viable integer type. 577992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(RetTy); 578992cb984SSergei Barannikov if (Size <= 8) 579992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); 580992cb984SSergei Barannikov if (Size <= 16) 581992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); 582992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 583992cb984SSergei Barannikov } 584992cb984SSergei Barannikov 585992cb984SSergei Barannikov // Otherwise return in memory. 586992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 587992cb984SSergei Barannikov } 588992cb984SSergei Barannikov 589992cb984SSergei Barannikov // Otherwise this is an AAPCS variant. 590992cb984SSergei Barannikov 591992cb984SSergei Barannikov if (isEmptyRecord(getContext(), RetTy, true)) 592992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 593992cb984SSergei Barannikov 594992cb984SSergei Barannikov // Check for homogeneous aggregates with AAPCS-VFP. 595992cb984SSergei Barannikov if (IsAAPCS_VFP) { 596992cb984SSergei Barannikov const Type *Base = nullptr; 597992cb984SSergei Barannikov uint64_t Members = 0; 598992cb984SSergei Barannikov if (isHomogeneousAggregate(RetTy, Base, Members)) 599992cb984SSergei Barannikov return classifyHomogeneousAggregate(RetTy, Base, Members); 600992cb984SSergei Barannikov } 601992cb984SSergei Barannikov 602992cb984SSergei Barannikov // Aggregates <= 4 bytes are returned in r0; other aggregates 603992cb984SSergei Barannikov // are returned indirectly. 604992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(RetTy); 605992cb984SSergei Barannikov if (Size <= 32) { 606992cb984SSergei Barannikov if (getDataLayout().isBigEndian()) 607992cb984SSergei Barannikov // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) 608992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 609992cb984SSergei Barannikov 610992cb984SSergei Barannikov // Return in the smallest viable integer type. 611992cb984SSergei Barannikov if (Size <= 8) 612992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); 613992cb984SSergei Barannikov if (Size <= 16) 614992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); 615992cb984SSergei Barannikov return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 616992cb984SSergei Barannikov } else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) { 617992cb984SSergei Barannikov llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext()); 618992cb984SSergei Barannikov llvm::Type *CoerceTy = 619992cb984SSergei Barannikov llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32); 620992cb984SSergei Barannikov return ABIArgInfo::getDirect(CoerceTy); 621992cb984SSergei Barannikov } 622992cb984SSergei Barannikov 623992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 624992cb984SSergei Barannikov } 625992cb984SSergei Barannikov 626992cb984SSergei Barannikov /// isIllegalVector - check whether Ty is an illegal vector type. 627992cb984SSergei Barannikov bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { 628992cb984SSergei Barannikov if (const VectorType *VT = Ty->getAs<VectorType> ()) { 629992cb984SSergei Barannikov // On targets that don't support half, fp16 or bfloat, they are expanded 630992cb984SSergei Barannikov // into float, and we don't want the ABI to depend on whether or not they 631992cb984SSergei Barannikov // are supported in hardware. Thus return false to coerce vectors of these 632992cb984SSergei Barannikov // types into integer vectors. 633992cb984SSergei Barannikov // We do not depend on hasLegalHalfType for bfloat as it is a 634992cb984SSergei Barannikov // separate IR type. 635992cb984SSergei Barannikov if ((!getTarget().hasLegalHalfType() && 636992cb984SSergei Barannikov (VT->getElementType()->isFloat16Type() || 637992cb984SSergei Barannikov VT->getElementType()->isHalfType())) || 638992cb984SSergei Barannikov (IsFloatABISoftFP && 639992cb984SSergei Barannikov VT->getElementType()->isBFloat16Type())) 640992cb984SSergei Barannikov return true; 641992cb984SSergei Barannikov if (isAndroid()) { 642992cb984SSergei Barannikov // Android shipped using Clang 3.1, which supported a slightly different 643992cb984SSergei Barannikov // vector ABI. The primary differences were that 3-element vector types 644992cb984SSergei Barannikov // were legal, and so were sub 32-bit vectors (i.e. <2 x i8>). This path 645992cb984SSergei Barannikov // accepts that legacy behavior for Android only. 646992cb984SSergei Barannikov // Check whether VT is legal. 647992cb984SSergei Barannikov unsigned NumElements = VT->getNumElements(); 648992cb984SSergei Barannikov // NumElements should be power of 2 or equal to 3. 649992cb984SSergei Barannikov if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3) 650992cb984SSergei Barannikov return true; 651992cb984SSergei Barannikov } else { 652992cb984SSergei Barannikov // Check whether VT is legal. 653992cb984SSergei Barannikov unsigned NumElements = VT->getNumElements(); 654992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(VT); 655992cb984SSergei Barannikov // NumElements should be power of 2. 656992cb984SSergei Barannikov if (!llvm::isPowerOf2_32(NumElements)) 657992cb984SSergei Barannikov return true; 658992cb984SSergei Barannikov // Size should be greater than 32 bits. 659992cb984SSergei Barannikov return Size <= 32; 660992cb984SSergei Barannikov } 661992cb984SSergei Barannikov } 662992cb984SSergei Barannikov return false; 663992cb984SSergei Barannikov } 664992cb984SSergei Barannikov 665992cb984SSergei Barannikov /// Return true if a type contains any 16-bit floating point vectors 666992cb984SSergei Barannikov bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { 667992cb984SSergei Barannikov if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { 66828ddbd4aSChris B uint64_t NElements = AT->getZExtSize(); 669992cb984SSergei Barannikov if (NElements == 0) 670992cb984SSergei Barannikov return false; 671992cb984SSergei Barannikov return containsAnyFP16Vectors(AT->getElementType()); 672992cb984SSergei Barannikov } else if (const RecordType *RT = Ty->getAs<RecordType>()) { 673992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 674992cb984SSergei Barannikov 675992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 676992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 677992cb984SSergei Barannikov if (llvm::any_of(CXXRD->bases(), [this](const CXXBaseSpecifier &B) { 678992cb984SSergei Barannikov return containsAnyFP16Vectors(B.getType()); 679992cb984SSergei Barannikov })) 680992cb984SSergei Barannikov return true; 681992cb984SSergei Barannikov 682992cb984SSergei Barannikov if (llvm::any_of(RD->fields(), [this](FieldDecl *FD) { 683992cb984SSergei Barannikov return FD && containsAnyFP16Vectors(FD->getType()); 684992cb984SSergei Barannikov })) 685992cb984SSergei Barannikov return true; 686992cb984SSergei Barannikov 687992cb984SSergei Barannikov return false; 688992cb984SSergei Barannikov } else { 689992cb984SSergei Barannikov if (const VectorType *VT = Ty->getAs<VectorType>()) 690992cb984SSergei Barannikov return (VT->getElementType()->isFloat16Type() || 691992cb984SSergei Barannikov VT->getElementType()->isBFloat16Type() || 692992cb984SSergei Barannikov VT->getElementType()->isHalfType()); 693992cb984SSergei Barannikov return false; 694992cb984SSergei Barannikov } 695992cb984SSergei Barannikov } 696992cb984SSergei Barannikov 697992cb984SSergei Barannikov bool ARMSwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, 698992cb984SSergei Barannikov unsigned NumElts) const { 699992cb984SSergei Barannikov if (!llvm::isPowerOf2_32(NumElts)) 700992cb984SSergei Barannikov return false; 701992cb984SSergei Barannikov unsigned size = CGT.getDataLayout().getTypeStoreSizeInBits(EltTy); 702992cb984SSergei Barannikov if (size > 64) 703992cb984SSergei Barannikov return false; 704992cb984SSergei Barannikov if (VectorSize.getQuantity() != 8 && 705992cb984SSergei Barannikov (VectorSize.getQuantity() != 16 || NumElts == 1)) 706992cb984SSergei Barannikov return false; 707992cb984SSergei Barannikov return true; 708992cb984SSergei Barannikov } 709992cb984SSergei Barannikov 710992cb984SSergei Barannikov bool ARMABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { 711992cb984SSergei Barannikov // Homogeneous aggregates for AAPCS-VFP must have base types of float, 712992cb984SSergei Barannikov // double, or 64-bit or 128-bit vectors. 713992cb984SSergei Barannikov if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { 714992cb984SSergei Barannikov if (BT->getKind() == BuiltinType::Float || 715992cb984SSergei Barannikov BT->getKind() == BuiltinType::Double || 716992cb984SSergei Barannikov BT->getKind() == BuiltinType::LongDouble) 717992cb984SSergei Barannikov return true; 718992cb984SSergei Barannikov } else if (const VectorType *VT = Ty->getAs<VectorType>()) { 719992cb984SSergei Barannikov unsigned VecSize = getContext().getTypeSize(VT); 720992cb984SSergei Barannikov if (VecSize == 64 || VecSize == 128) 721992cb984SSergei Barannikov return true; 722992cb984SSergei Barannikov } 723992cb984SSergei Barannikov return false; 724992cb984SSergei Barannikov } 725992cb984SSergei Barannikov 726992cb984SSergei Barannikov bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, 727992cb984SSergei Barannikov uint64_t Members) const { 728992cb984SSergei Barannikov return Members <= 4; 729992cb984SSergei Barannikov } 730992cb984SSergei Barannikov 731992cb984SSergei Barannikov bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { 732992cb984SSergei Barannikov // AAPCS32 says that the rule for whether something is a homogeneous 733992cb984SSergei Barannikov // aggregate is applied to the output of the data layout decision. So 734992cb984SSergei Barannikov // anything that doesn't affect the data layout also does not affect 735992cb984SSergei Barannikov // homogeneity. In particular, zero-length bitfields don't stop a struct 736992cb984SSergei Barannikov // being homogeneous. 737992cb984SSergei Barannikov return true; 738992cb984SSergei Barannikov } 739992cb984SSergei Barannikov 740992cb984SSergei Barannikov bool ARMABIInfo::isEffectivelyAAPCS_VFP(unsigned callConvention, 741992cb984SSergei Barannikov bool acceptHalf) const { 742992cb984SSergei Barannikov // Give precedence to user-specified calling conventions. 743992cb984SSergei Barannikov if (callConvention != llvm::CallingConv::C) 744992cb984SSergei Barannikov return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP); 745992cb984SSergei Barannikov else 746992cb984SSergei Barannikov return (getABIKind() == ARMABIKind::AAPCS_VFP) || 747992cb984SSergei Barannikov (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP)); 748992cb984SSergei Barannikov } 749992cb984SSergei Barannikov 7506d973b45SMariya Podchishchaeva RValue ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 7516d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const { 752992cb984SSergei Barannikov CharUnits SlotSize = CharUnits::fromQuantity(4); 753992cb984SSergei Barannikov 754992cb984SSergei Barannikov // Empty records are ignored for parameter passing purposes. 7556d973b45SMariya Podchishchaeva if (isEmptyRecord(getContext(), Ty, true)) 7566d973b45SMariya Podchishchaeva return Slot.asRValue(); 757992cb984SSergei Barannikov 758992cb984SSergei Barannikov CharUnits TySize = getContext().getTypeSizeInChars(Ty); 759992cb984SSergei Barannikov CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty); 760992cb984SSergei Barannikov 761992cb984SSergei Barannikov // Use indirect if size of the illegal vector is bigger than 16 bytes. 762992cb984SSergei Barannikov bool IsIndirect = false; 763992cb984SSergei Barannikov const Type *Base = nullptr; 764992cb984SSergei Barannikov uint64_t Members = 0; 765992cb984SSergei Barannikov if (TySize > CharUnits::fromQuantity(16) && isIllegalVectorType(Ty)) { 766992cb984SSergei Barannikov IsIndirect = true; 767992cb984SSergei Barannikov 768992cb984SSergei Barannikov // ARMv7k passes structs bigger than 16 bytes indirectly, in space 769992cb984SSergei Barannikov // allocated by the caller. 770992cb984SSergei Barannikov } else if (TySize > CharUnits::fromQuantity(16) && 771992cb984SSergei Barannikov getABIKind() == ARMABIKind::AAPCS16_VFP && 772992cb984SSergei Barannikov !isHomogeneousAggregate(Ty, Base, Members)) { 773992cb984SSergei Barannikov IsIndirect = true; 774992cb984SSergei Barannikov 775992cb984SSergei Barannikov // Otherwise, bound the type's ABI alignment. 776992cb984SSergei Barannikov // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for 777992cb984SSergei Barannikov // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte. 778992cb984SSergei Barannikov // Our callers should be prepared to handle an under-aligned address. 779992cb984SSergei Barannikov } else if (getABIKind() == ARMABIKind::AAPCS_VFP || 780992cb984SSergei Barannikov getABIKind() == ARMABIKind::AAPCS) { 781992cb984SSergei Barannikov TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); 782992cb984SSergei Barannikov TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(8)); 783992cb984SSergei Barannikov } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { 784992cb984SSergei Barannikov // ARMv7k allows type alignment up to 16 bytes. 785992cb984SSergei Barannikov TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); 786992cb984SSergei Barannikov TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(16)); 787992cb984SSergei Barannikov } else { 788992cb984SSergei Barannikov TyAlignForABI = CharUnits::fromQuantity(4); 789992cb984SSergei Barannikov } 790992cb984SSergei Barannikov 791992cb984SSergei Barannikov TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None); 7926d973b45SMariya Podchishchaeva return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo, SlotSize, 7936d973b45SMariya Podchishchaeva /*AllowHigherAlign*/ true, Slot); 794992cb984SSergei Barannikov } 795992cb984SSergei Barannikov 796992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 797992cb984SSergei Barannikov CodeGen::createARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind Kind) { 798992cb984SSergei Barannikov return std::make_unique<ARMTargetCodeGenInfo>(CGM.getTypes(), Kind); 799992cb984SSergei Barannikov } 800992cb984SSergei Barannikov 801992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 802992cb984SSergei Barannikov CodeGen::createWindowsARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind K) { 803992cb984SSergei Barannikov return std::make_unique<WindowsARMTargetCodeGenInfo>(CGM.getTypes(), K); 804992cb984SSergei Barannikov } 805