106c3fb27SDimitry Andric //===- ARM.cpp ------------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "ABIInfoImpl.h" 1006c3fb27SDimitry Andric #include "TargetInfo.h" 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric using namespace clang; 1306c3fb27SDimitry Andric using namespace clang::CodeGen; 1406c3fb27SDimitry Andric 1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1606c3fb27SDimitry Andric // ARM ABI Implementation 1706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1806c3fb27SDimitry Andric 1906c3fb27SDimitry Andric namespace { 2006c3fb27SDimitry Andric 2106c3fb27SDimitry Andric class ARMABIInfo : public ABIInfo { 2206c3fb27SDimitry Andric ARMABIKind Kind; 2306c3fb27SDimitry Andric bool IsFloatABISoftFP; 2406c3fb27SDimitry Andric 2506c3fb27SDimitry Andric public: 2606c3fb27SDimitry Andric ARMABIInfo(CodeGenTypes &CGT, ARMABIKind Kind) : ABIInfo(CGT), Kind(Kind) { 2706c3fb27SDimitry Andric setCCs(); 2806c3fb27SDimitry Andric IsFloatABISoftFP = CGT.getCodeGenOpts().FloatABI == "softfp" || 2906c3fb27SDimitry Andric CGT.getCodeGenOpts().FloatABI == ""; // default 3006c3fb27SDimitry Andric } 3106c3fb27SDimitry Andric 3206c3fb27SDimitry Andric bool isEABI() const { 3306c3fb27SDimitry Andric switch (getTarget().getTriple().getEnvironment()) { 3406c3fb27SDimitry Andric case llvm::Triple::Android: 3506c3fb27SDimitry Andric case llvm::Triple::EABI: 3606c3fb27SDimitry Andric case llvm::Triple::EABIHF: 3706c3fb27SDimitry Andric case llvm::Triple::GNUEABI: 38*d686ce93SDimitry Andric case llvm::Triple::GNUEABIT64: 3906c3fb27SDimitry Andric case llvm::Triple::GNUEABIHF: 40*d686ce93SDimitry Andric case llvm::Triple::GNUEABIHFT64: 4106c3fb27SDimitry Andric case llvm::Triple::MuslEABI: 4206c3fb27SDimitry Andric case llvm::Triple::MuslEABIHF: 4306c3fb27SDimitry Andric return true; 4406c3fb27SDimitry Andric default: 4506c3fb27SDimitry Andric return getTarget().getTriple().isOHOSFamily(); 4606c3fb27SDimitry Andric } 4706c3fb27SDimitry Andric } 4806c3fb27SDimitry Andric 4906c3fb27SDimitry Andric bool isEABIHF() const { 5006c3fb27SDimitry Andric switch (getTarget().getTriple().getEnvironment()) { 5106c3fb27SDimitry Andric case llvm::Triple::EABIHF: 5206c3fb27SDimitry Andric case llvm::Triple::GNUEABIHF: 53*d686ce93SDimitry Andric case llvm::Triple::GNUEABIHFT64: 5406c3fb27SDimitry Andric case llvm::Triple::MuslEABIHF: 5506c3fb27SDimitry Andric return true; 5606c3fb27SDimitry Andric default: 5706c3fb27SDimitry Andric return false; 5806c3fb27SDimitry Andric } 5906c3fb27SDimitry Andric } 6006c3fb27SDimitry Andric 6106c3fb27SDimitry Andric ARMABIKind getABIKind() const { return Kind; } 6206c3fb27SDimitry Andric 6306c3fb27SDimitry Andric bool allowBFloatArgsAndRet() const override { 6406c3fb27SDimitry Andric return !IsFloatABISoftFP && getTarget().hasBFloat16Type(); 6506c3fb27SDimitry Andric } 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric private: 6806c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic, 6906c3fb27SDimitry Andric unsigned functionCallConv) const; 7006c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic, 7106c3fb27SDimitry Andric unsigned functionCallConv) const; 7206c3fb27SDimitry Andric ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base, 7306c3fb27SDimitry Andric uint64_t Members) const; 7406c3fb27SDimitry Andric ABIArgInfo coerceIllegalVector(QualType Ty) const; 7506c3fb27SDimitry Andric bool isIllegalVectorType(QualType Ty) const; 7606c3fb27SDimitry Andric bool containsAnyFP16Vectors(QualType Ty) const; 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric bool isHomogeneousAggregateBaseType(QualType Ty) const override; 7906c3fb27SDimitry Andric bool isHomogeneousAggregateSmallEnough(const Type *Ty, 8006c3fb27SDimitry Andric uint64_t Members) const override; 8106c3fb27SDimitry Andric bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; 8206c3fb27SDimitry Andric 8306c3fb27SDimitry Andric bool isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const; 8406c3fb27SDimitry Andric 8506c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 8606c3fb27SDimitry Andric 870fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 880fca6ea1SDimitry Andric AggValueSlot Slot) const override; 8906c3fb27SDimitry Andric 9006c3fb27SDimitry Andric llvm::CallingConv::ID getLLVMDefaultCC() const; 9106c3fb27SDimitry Andric llvm::CallingConv::ID getABIDefaultCC() const; 9206c3fb27SDimitry Andric void setCCs(); 9306c3fb27SDimitry Andric }; 9406c3fb27SDimitry Andric 9506c3fb27SDimitry Andric class ARMSwiftABIInfo : public SwiftABIInfo { 9606c3fb27SDimitry Andric public: 9706c3fb27SDimitry Andric explicit ARMSwiftABIInfo(CodeGenTypes &CGT) 9806c3fb27SDimitry Andric : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {} 9906c3fb27SDimitry Andric 10006c3fb27SDimitry Andric bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, 10106c3fb27SDimitry Andric unsigned NumElts) const override; 10206c3fb27SDimitry Andric }; 10306c3fb27SDimitry Andric 10406c3fb27SDimitry Andric class ARMTargetCodeGenInfo : public TargetCodeGenInfo { 10506c3fb27SDimitry Andric public: 10606c3fb27SDimitry Andric ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) 10706c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<ARMABIInfo>(CGT, K)) { 10806c3fb27SDimitry Andric SwiftInfo = std::make_unique<ARMSwiftABIInfo>(CGT); 10906c3fb27SDimitry Andric } 11006c3fb27SDimitry Andric 11106c3fb27SDimitry Andric int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 11206c3fb27SDimitry Andric return 13; 11306c3fb27SDimitry Andric } 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric StringRef getARCRetainAutoreleasedReturnValueMarker() const override { 11606c3fb27SDimitry Andric return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue"; 11706c3fb27SDimitry Andric } 11806c3fb27SDimitry Andric 11906c3fb27SDimitry Andric bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, 12006c3fb27SDimitry Andric llvm::Value *Address) const override { 12106c3fb27SDimitry Andric llvm::Value *Four8 = llvm::ConstantInt::get(CGF.Int8Ty, 4); 12206c3fb27SDimitry Andric 12306c3fb27SDimitry Andric // 0-15 are the 16 integer registers. 12406c3fb27SDimitry Andric AssignToArrayRange(CGF.Builder, Address, Four8, 0, 15); 12506c3fb27SDimitry Andric return false; 12606c3fb27SDimitry Andric } 12706c3fb27SDimitry Andric 12806c3fb27SDimitry Andric unsigned getSizeOfUnwindException() const override { 12906c3fb27SDimitry Andric if (getABIInfo<ARMABIInfo>().isEABI()) 13006c3fb27SDimitry Andric return 88; 13106c3fb27SDimitry Andric return TargetCodeGenInfo::getSizeOfUnwindException(); 13206c3fb27SDimitry Andric } 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 13506c3fb27SDimitry Andric CodeGen::CodeGenModule &CGM) const override { 13606c3fb27SDimitry Andric if (GV->isDeclaration()) 13706c3fb27SDimitry Andric return; 13806c3fb27SDimitry Andric const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 13906c3fb27SDimitry Andric if (!FD) 14006c3fb27SDimitry Andric return; 14106c3fb27SDimitry Andric auto *Fn = cast<llvm::Function>(GV); 14206c3fb27SDimitry Andric 14306c3fb27SDimitry Andric if (const auto *TA = FD->getAttr<TargetAttr>()) { 14406c3fb27SDimitry Andric ParsedTargetAttr Attr = 14506c3fb27SDimitry Andric CGM.getTarget().parseTargetAttr(TA->getFeaturesStr()); 14606c3fb27SDimitry Andric if (!Attr.BranchProtection.empty()) { 1470fca6ea1SDimitry Andric TargetInfo::BranchProtectionInfo BPI{}; 14806c3fb27SDimitry Andric StringRef DiagMsg; 14906c3fb27SDimitry Andric StringRef Arch = 15006c3fb27SDimitry Andric Attr.CPU.empty() ? CGM.getTarget().getTargetOpts().CPU : Attr.CPU; 15106c3fb27SDimitry Andric if (!CGM.getTarget().validateBranchProtection(Attr.BranchProtection, 15206c3fb27SDimitry Andric Arch, BPI, DiagMsg)) { 15306c3fb27SDimitry Andric CGM.getDiags().Report( 15406c3fb27SDimitry Andric D->getLocation(), 15506c3fb27SDimitry Andric diag::warn_target_unsupported_branch_protection_attribute) 15606c3fb27SDimitry Andric << Arch; 1570fca6ea1SDimitry Andric } else 1580fca6ea1SDimitry Andric setBranchProtectionFnAttributes(BPI, (*Fn)); 15906c3fb27SDimitry Andric } else if (CGM.getLangOpts().BranchTargetEnforcement || 16006c3fb27SDimitry Andric CGM.getLangOpts().hasSignReturnAddress()) { 16106c3fb27SDimitry Andric // If the Branch Protection attribute is missing, validate the target 16206c3fb27SDimitry Andric // Architecture attribute against Branch Protection command line 16306c3fb27SDimitry Andric // settings. 16406c3fb27SDimitry Andric if (!CGM.getTarget().isBranchProtectionSupportedArch(Attr.CPU)) 16506c3fb27SDimitry Andric CGM.getDiags().Report( 16606c3fb27SDimitry Andric D->getLocation(), 16706c3fb27SDimitry Andric diag::warn_target_unsupported_branch_protection_attribute) 16806c3fb27SDimitry Andric << Attr.CPU; 16906c3fb27SDimitry Andric } 1700fca6ea1SDimitry Andric } else if (CGM.getTarget().isBranchProtectionSupportedArch( 1710fca6ea1SDimitry Andric CGM.getTarget().getTargetOpts().CPU)) { 1720fca6ea1SDimitry Andric TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts()); 1730fca6ea1SDimitry Andric setBranchProtectionFnAttributes(BPI, (*Fn)); 17406c3fb27SDimitry Andric } 17506c3fb27SDimitry Andric 17606c3fb27SDimitry Andric const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); 17706c3fb27SDimitry Andric if (!Attr) 17806c3fb27SDimitry Andric return; 17906c3fb27SDimitry Andric 18006c3fb27SDimitry Andric const char *Kind; 18106c3fb27SDimitry Andric switch (Attr->getInterrupt()) { 18206c3fb27SDimitry Andric case ARMInterruptAttr::Generic: Kind = ""; break; 18306c3fb27SDimitry Andric case ARMInterruptAttr::IRQ: Kind = "IRQ"; break; 18406c3fb27SDimitry Andric case ARMInterruptAttr::FIQ: Kind = "FIQ"; break; 18506c3fb27SDimitry Andric case ARMInterruptAttr::SWI: Kind = "SWI"; break; 18606c3fb27SDimitry Andric case ARMInterruptAttr::ABORT: Kind = "ABORT"; break; 18706c3fb27SDimitry Andric case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break; 18806c3fb27SDimitry Andric } 18906c3fb27SDimitry Andric 19006c3fb27SDimitry Andric Fn->addFnAttr("interrupt", Kind); 19106c3fb27SDimitry Andric 19206c3fb27SDimitry Andric ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind(); 19306c3fb27SDimitry Andric if (ABI == ARMABIKind::APCS) 19406c3fb27SDimitry Andric return; 19506c3fb27SDimitry Andric 19606c3fb27SDimitry Andric // AAPCS guarantees that sp will be 8-byte aligned on any public interface, 19706c3fb27SDimitry Andric // however this is not necessarily true on taking any interrupt. Instruct 19806c3fb27SDimitry Andric // the backend to perform a realignment as part of the function prologue. 19906c3fb27SDimitry Andric llvm::AttrBuilder B(Fn->getContext()); 20006c3fb27SDimitry Andric B.addStackAlignmentAttr(8); 20106c3fb27SDimitry Andric Fn->addFnAttrs(B); 20206c3fb27SDimitry Andric } 20306c3fb27SDimitry Andric }; 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo { 20606c3fb27SDimitry Andric public: 20706c3fb27SDimitry Andric WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) 20806c3fb27SDimitry Andric : ARMTargetCodeGenInfo(CGT, K) {} 20906c3fb27SDimitry Andric 21006c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 21106c3fb27SDimitry Andric CodeGen::CodeGenModule &CGM) const override; 21206c3fb27SDimitry Andric 21306c3fb27SDimitry Andric void getDependentLibraryOption(llvm::StringRef Lib, 21406c3fb27SDimitry Andric llvm::SmallString<24> &Opt) const override { 21506c3fb27SDimitry Andric Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); 21606c3fb27SDimitry Andric } 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, 21906c3fb27SDimitry Andric llvm::SmallString<32> &Opt) const override { 22006c3fb27SDimitry Andric Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\""; 22106c3fb27SDimitry Andric } 22206c3fb27SDimitry Andric }; 22306c3fb27SDimitry Andric 22406c3fb27SDimitry Andric void WindowsARMTargetCodeGenInfo::setTargetAttributes( 22506c3fb27SDimitry Andric const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { 22606c3fb27SDimitry Andric ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM); 22706c3fb27SDimitry Andric if (GV->isDeclaration()) 22806c3fb27SDimitry Andric return; 22906c3fb27SDimitry Andric addStackProbeTargetAttributes(D, GV, CGM); 23006c3fb27SDimitry Andric } 23106c3fb27SDimitry Andric } 23206c3fb27SDimitry Andric 23306c3fb27SDimitry Andric void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { 23406c3fb27SDimitry Andric if (!::classifyReturnType(getCXXABI(), FI, *this)) 23506c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic(), 23606c3fb27SDimitry Andric FI.getCallingConvention()); 23706c3fb27SDimitry Andric 23806c3fb27SDimitry Andric for (auto &I : FI.arguments()) 23906c3fb27SDimitry Andric I.info = classifyArgumentType(I.type, FI.isVariadic(), 24006c3fb27SDimitry Andric FI.getCallingConvention()); 24106c3fb27SDimitry Andric 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric // Always honor user-specified calling convention. 24406c3fb27SDimitry Andric if (FI.getCallingConvention() != llvm::CallingConv::C) 24506c3fb27SDimitry Andric return; 24606c3fb27SDimitry Andric 24706c3fb27SDimitry Andric llvm::CallingConv::ID cc = getRuntimeCC(); 24806c3fb27SDimitry Andric if (cc != llvm::CallingConv::C) 24906c3fb27SDimitry Andric FI.setEffectiveCallingConvention(cc); 25006c3fb27SDimitry Andric } 25106c3fb27SDimitry Andric 25206c3fb27SDimitry Andric /// Return the default calling convention that LLVM will use. 25306c3fb27SDimitry Andric llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const { 25406c3fb27SDimitry Andric // The default calling convention that LLVM will infer. 25506c3fb27SDimitry Andric if (isEABIHF() || getTarget().getTriple().isWatchABI()) 25606c3fb27SDimitry Andric return llvm::CallingConv::ARM_AAPCS_VFP; 25706c3fb27SDimitry Andric else if (isEABI()) 25806c3fb27SDimitry Andric return llvm::CallingConv::ARM_AAPCS; 25906c3fb27SDimitry Andric else 26006c3fb27SDimitry Andric return llvm::CallingConv::ARM_APCS; 26106c3fb27SDimitry Andric } 26206c3fb27SDimitry Andric 26306c3fb27SDimitry Andric /// Return the calling convention that our ABI would like us to use 26406c3fb27SDimitry Andric /// as the C calling convention. 26506c3fb27SDimitry Andric llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const { 26606c3fb27SDimitry Andric switch (getABIKind()) { 26706c3fb27SDimitry Andric case ARMABIKind::APCS: 26806c3fb27SDimitry Andric return llvm::CallingConv::ARM_APCS; 26906c3fb27SDimitry Andric case ARMABIKind::AAPCS: 27006c3fb27SDimitry Andric return llvm::CallingConv::ARM_AAPCS; 27106c3fb27SDimitry Andric case ARMABIKind::AAPCS_VFP: 27206c3fb27SDimitry Andric return llvm::CallingConv::ARM_AAPCS_VFP; 27306c3fb27SDimitry Andric case ARMABIKind::AAPCS16_VFP: 27406c3fb27SDimitry Andric return llvm::CallingConv::ARM_AAPCS_VFP; 27506c3fb27SDimitry Andric } 27606c3fb27SDimitry Andric llvm_unreachable("bad ABI kind"); 27706c3fb27SDimitry Andric } 27806c3fb27SDimitry Andric 27906c3fb27SDimitry Andric void ARMABIInfo::setCCs() { 28006c3fb27SDimitry Andric assert(getRuntimeCC() == llvm::CallingConv::C); 28106c3fb27SDimitry Andric 28206c3fb27SDimitry Andric // Don't muddy up the IR with a ton of explicit annotations if 28306c3fb27SDimitry Andric // they'd just match what LLVM will infer from the triple. 28406c3fb27SDimitry Andric llvm::CallingConv::ID abiCC = getABIDefaultCC(); 28506c3fb27SDimitry Andric if (abiCC != getLLVMDefaultCC()) 28606c3fb27SDimitry Andric RuntimeCC = abiCC; 28706c3fb27SDimitry Andric } 28806c3fb27SDimitry Andric 28906c3fb27SDimitry Andric ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const { 29006c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 29106c3fb27SDimitry Andric if (Size <= 32) { 29206c3fb27SDimitry Andric llvm::Type *ResType = 29306c3fb27SDimitry Andric llvm::Type::getInt32Ty(getVMContext()); 29406c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType); 29506c3fb27SDimitry Andric } 29606c3fb27SDimitry Andric if (Size == 64 || Size == 128) { 29706c3fb27SDimitry Andric auto *ResType = llvm::FixedVectorType::get( 29806c3fb27SDimitry Andric llvm::Type::getInt32Ty(getVMContext()), Size / 32); 29906c3fb27SDimitry Andric return ABIArgInfo::getDirect(ResType); 30006c3fb27SDimitry Andric } 30106c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 30206c3fb27SDimitry Andric } 30306c3fb27SDimitry Andric 30406c3fb27SDimitry Andric ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty, 30506c3fb27SDimitry Andric const Type *Base, 30606c3fb27SDimitry Andric uint64_t Members) const { 30706c3fb27SDimitry Andric assert(Base && "Base class should be set for homogeneous aggregate"); 30806c3fb27SDimitry Andric // Base can be a floating-point or a vector. 30906c3fb27SDimitry Andric if (const VectorType *VT = Base->getAs<VectorType>()) { 31006c3fb27SDimitry Andric // FP16 vectors should be converted to integer vectors 31106c3fb27SDimitry Andric if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) { 31206c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(VT); 31306c3fb27SDimitry Andric auto *NewVecTy = llvm::FixedVectorType::get( 31406c3fb27SDimitry Andric llvm::Type::getInt32Ty(getVMContext()), Size / 32); 31506c3fb27SDimitry Andric llvm::Type *Ty = llvm::ArrayType::get(NewVecTy, Members); 31606c3fb27SDimitry Andric return ABIArgInfo::getDirect(Ty, 0, nullptr, false); 31706c3fb27SDimitry Andric } 31806c3fb27SDimitry Andric } 31906c3fb27SDimitry Andric unsigned Align = 0; 32006c3fb27SDimitry Andric if (getABIKind() == ARMABIKind::AAPCS || 32106c3fb27SDimitry Andric getABIKind() == ARMABIKind::AAPCS_VFP) { 32206c3fb27SDimitry Andric // For alignment adjusted HFAs, cap the argument alignment to 8, leave it 32306c3fb27SDimitry Andric // default otherwise. 32406c3fb27SDimitry Andric Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); 32506c3fb27SDimitry Andric unsigned BaseAlign = getContext().getTypeAlignInChars(Base).getQuantity(); 32606c3fb27SDimitry Andric Align = (Align > BaseAlign && Align >= 8) ? 8 : 0; 32706c3fb27SDimitry Andric } 32806c3fb27SDimitry Andric return ABIArgInfo::getDirect(nullptr, 0, nullptr, false, Align); 32906c3fb27SDimitry Andric } 33006c3fb27SDimitry Andric 33106c3fb27SDimitry Andric ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, 33206c3fb27SDimitry Andric unsigned functionCallConv) const { 33306c3fb27SDimitry Andric // 6.1.2.1 The following argument types are VFP CPRCs: 33406c3fb27SDimitry Andric // A single-precision floating-point type (including promoted 33506c3fb27SDimitry Andric // half-precision types); A double-precision floating-point type; 33606c3fb27SDimitry Andric // A 64-bit or 128-bit containerized vector type; Homogeneous Aggregate 33706c3fb27SDimitry Andric // with a Base Type of a single- or double-precision floating-point type, 33806c3fb27SDimitry Andric // 64-bit containerized vectors or 128-bit containerized vectors with one 33906c3fb27SDimitry Andric // to four Elements. 34006c3fb27SDimitry Andric // Variadic functions should always marshal to the base standard. 34106c3fb27SDimitry Andric bool IsAAPCS_VFP = 34206c3fb27SDimitry Andric !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ false); 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty); 34506c3fb27SDimitry Andric 34606c3fb27SDimitry Andric // Handle illegal vector types here. 34706c3fb27SDimitry Andric if (isIllegalVectorType(Ty)) 34806c3fb27SDimitry Andric return coerceIllegalVector(Ty); 34906c3fb27SDimitry Andric 35006c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty)) { 35106c3fb27SDimitry Andric // Treat an enum type as its underlying type. 35206c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { 35306c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 35406c3fb27SDimitry Andric } 35506c3fb27SDimitry Andric 35606c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 35706c3fb27SDimitry Andric if (EIT->getNumBits() > 64) 35806c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/true); 35906c3fb27SDimitry Andric 36006c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 36106c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 36206c3fb27SDimitry Andric } 36306c3fb27SDimitry Andric 36406c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 36506c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 36606c3fb27SDimitry Andric } 36706c3fb27SDimitry Andric 36806c3fb27SDimitry Andric // Ignore empty records. 36906c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 37006c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 37106c3fb27SDimitry Andric 37206c3fb27SDimitry Andric if (IsAAPCS_VFP) { 37306c3fb27SDimitry Andric // Homogeneous Aggregates need to be expanded when we can fit the aggregate 37406c3fb27SDimitry Andric // into VFP registers. 37506c3fb27SDimitry Andric const Type *Base = nullptr; 37606c3fb27SDimitry Andric uint64_t Members = 0; 37706c3fb27SDimitry Andric if (isHomogeneousAggregate(Ty, Base, Members)) 37806c3fb27SDimitry Andric return classifyHomogeneousAggregate(Ty, Base, Members); 37906c3fb27SDimitry Andric } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { 38006c3fb27SDimitry Andric // WatchOS does have homogeneous aggregates. Note that we intentionally use 38106c3fb27SDimitry Andric // this convention even for a variadic function: the backend will use GPRs 38206c3fb27SDimitry Andric // if needed. 38306c3fb27SDimitry Andric const Type *Base = nullptr; 38406c3fb27SDimitry Andric uint64_t Members = 0; 38506c3fb27SDimitry Andric if (isHomogeneousAggregate(Ty, Base, Members)) { 38606c3fb27SDimitry Andric assert(Base && Members <= 4 && "unexpected homogeneous aggregate"); 38706c3fb27SDimitry Andric llvm::Type *Ty = 38806c3fb27SDimitry Andric llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members); 38906c3fb27SDimitry Andric return ABIArgInfo::getDirect(Ty, 0, nullptr, false); 39006c3fb27SDimitry Andric } 39106c3fb27SDimitry Andric } 39206c3fb27SDimitry Andric 39306c3fb27SDimitry Andric if (getABIKind() == ARMABIKind::AAPCS16_VFP && 39406c3fb27SDimitry Andric getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(16)) { 39506c3fb27SDimitry Andric // WatchOS is adopting the 64-bit AAPCS rule on composite types: if they're 39606c3fb27SDimitry Andric // bigger than 128-bits, they get placed in space allocated by the caller, 39706c3fb27SDimitry Andric // and a pointer is passed. 39806c3fb27SDimitry Andric return ABIArgInfo::getIndirect( 39906c3fb27SDimitry Andric CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), false); 40006c3fb27SDimitry Andric } 40106c3fb27SDimitry Andric 40206c3fb27SDimitry Andric // Support byval for ARM. 40306c3fb27SDimitry Andric // The ABI alignment for APCS is 4-byte and for AAPCS at least 4-byte and at 40406c3fb27SDimitry Andric // most 8-byte. We realign the indirect argument if type alignment is bigger 40506c3fb27SDimitry Andric // than ABI alignment. 40606c3fb27SDimitry Andric uint64_t ABIAlign = 4; 40706c3fb27SDimitry Andric uint64_t TyAlign; 40806c3fb27SDimitry Andric if (getABIKind() == ARMABIKind::AAPCS_VFP || 40906c3fb27SDimitry Andric getABIKind() == ARMABIKind::AAPCS) { 41006c3fb27SDimitry Andric TyAlign = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity(); 41106c3fb27SDimitry Andric ABIAlign = std::clamp(TyAlign, (uint64_t)4, (uint64_t)8); 41206c3fb27SDimitry Andric } else { 41306c3fb27SDimitry Andric TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); 41406c3fb27SDimitry Andric } 41506c3fb27SDimitry Andric if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) { 41606c3fb27SDimitry Andric assert(getABIKind() != ARMABIKind::AAPCS16_VFP && "unexpected byval"); 41706c3fb27SDimitry Andric return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), 41806c3fb27SDimitry Andric /*ByVal=*/true, 41906c3fb27SDimitry Andric /*Realign=*/TyAlign > ABIAlign); 42006c3fb27SDimitry Andric } 42106c3fb27SDimitry Andric 42206c3fb27SDimitry Andric // On RenderScript, coerce Aggregates <= 64 bytes to an integer array of 42306c3fb27SDimitry Andric // same size and alignment. 42406c3fb27SDimitry Andric if (getTarget().isRenderScriptTarget()) { 42506c3fb27SDimitry Andric return coerceToIntArray(Ty, getContext(), getVMContext()); 42606c3fb27SDimitry Andric } 42706c3fb27SDimitry Andric 42806c3fb27SDimitry Andric // Otherwise, pass by coercing to a structure of the appropriate size. 42906c3fb27SDimitry Andric llvm::Type* ElemTy; 43006c3fb27SDimitry Andric unsigned SizeRegs; 43106c3fb27SDimitry Andric // FIXME: Try to match the types of the arguments more accurately where 43206c3fb27SDimitry Andric // we can. 43306c3fb27SDimitry Andric if (TyAlign <= 4) { 43406c3fb27SDimitry Andric ElemTy = llvm::Type::getInt32Ty(getVMContext()); 43506c3fb27SDimitry Andric SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32; 43606c3fb27SDimitry Andric } else { 43706c3fb27SDimitry Andric ElemTy = llvm::Type::getInt64Ty(getVMContext()); 43806c3fb27SDimitry Andric SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64; 43906c3fb27SDimitry Andric } 44006c3fb27SDimitry Andric 44106c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, SizeRegs)); 44206c3fb27SDimitry Andric } 44306c3fb27SDimitry Andric 44406c3fb27SDimitry Andric static bool isIntegerLikeType(QualType Ty, ASTContext &Context, 44506c3fb27SDimitry Andric llvm::LLVMContext &VMContext) { 44606c3fb27SDimitry Andric // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure 44706c3fb27SDimitry Andric // is called integer-like if its size is less than or equal to one word, and 44806c3fb27SDimitry Andric // the offset of each of its addressable sub-fields is zero. 44906c3fb27SDimitry Andric 45006c3fb27SDimitry Andric uint64_t Size = Context.getTypeSize(Ty); 45106c3fb27SDimitry Andric 45206c3fb27SDimitry Andric // Check that the type fits in a word. 45306c3fb27SDimitry Andric if (Size > 32) 45406c3fb27SDimitry Andric return false; 45506c3fb27SDimitry Andric 45606c3fb27SDimitry Andric // FIXME: Handle vector types! 45706c3fb27SDimitry Andric if (Ty->isVectorType()) 45806c3fb27SDimitry Andric return false; 45906c3fb27SDimitry Andric 46006c3fb27SDimitry Andric // Float types are never treated as "integer like". 46106c3fb27SDimitry Andric if (Ty->isRealFloatingType()) 46206c3fb27SDimitry Andric return false; 46306c3fb27SDimitry Andric 46406c3fb27SDimitry Andric // If this is a builtin or pointer type then it is ok. 46506c3fb27SDimitry Andric if (Ty->getAs<BuiltinType>() || Ty->isPointerType()) 46606c3fb27SDimitry Andric return true; 46706c3fb27SDimitry Andric 46806c3fb27SDimitry Andric // Small complex integer types are "integer like". 46906c3fb27SDimitry Andric if (const ComplexType *CT = Ty->getAs<ComplexType>()) 47006c3fb27SDimitry Andric return isIntegerLikeType(CT->getElementType(), Context, VMContext); 47106c3fb27SDimitry Andric 47206c3fb27SDimitry Andric // Single element and zero sized arrays should be allowed, by the definition 47306c3fb27SDimitry Andric // above, but they are not. 47406c3fb27SDimitry Andric 47506c3fb27SDimitry Andric // Otherwise, it must be a record type. 47606c3fb27SDimitry Andric const RecordType *RT = Ty->getAs<RecordType>(); 47706c3fb27SDimitry Andric if (!RT) return false; 47806c3fb27SDimitry Andric 47906c3fb27SDimitry Andric // Ignore records with flexible arrays. 48006c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 48106c3fb27SDimitry Andric if (RD->hasFlexibleArrayMember()) 48206c3fb27SDimitry Andric return false; 48306c3fb27SDimitry Andric 48406c3fb27SDimitry Andric // Check that all sub-fields are at offset 0, and are themselves "integer 48506c3fb27SDimitry Andric // like". 48606c3fb27SDimitry Andric const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); 48706c3fb27SDimitry Andric 48806c3fb27SDimitry Andric bool HadField = false; 48906c3fb27SDimitry Andric unsigned idx = 0; 49006c3fb27SDimitry Andric for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); 49106c3fb27SDimitry Andric i != e; ++i, ++idx) { 49206c3fb27SDimitry Andric const FieldDecl *FD = *i; 49306c3fb27SDimitry Andric 49406c3fb27SDimitry Andric // Bit-fields are not addressable, we only need to verify they are "integer 49506c3fb27SDimitry Andric // like". We still have to disallow a subsequent non-bitfield, for example: 49606c3fb27SDimitry Andric // struct { int : 0; int x } 49706c3fb27SDimitry Andric // is non-integer like according to gcc. 49806c3fb27SDimitry Andric if (FD->isBitField()) { 49906c3fb27SDimitry Andric if (!RD->isUnion()) 50006c3fb27SDimitry Andric HadField = true; 50106c3fb27SDimitry Andric 50206c3fb27SDimitry Andric if (!isIntegerLikeType(FD->getType(), Context, VMContext)) 50306c3fb27SDimitry Andric return false; 50406c3fb27SDimitry Andric 50506c3fb27SDimitry Andric continue; 50606c3fb27SDimitry Andric } 50706c3fb27SDimitry Andric 50806c3fb27SDimitry Andric // Check if this field is at offset 0. 50906c3fb27SDimitry Andric if (Layout.getFieldOffset(idx) != 0) 51006c3fb27SDimitry Andric return false; 51106c3fb27SDimitry Andric 51206c3fb27SDimitry Andric if (!isIntegerLikeType(FD->getType(), Context, VMContext)) 51306c3fb27SDimitry Andric return false; 51406c3fb27SDimitry Andric 51506c3fb27SDimitry Andric // Only allow at most one field in a structure. This doesn't match the 51606c3fb27SDimitry Andric // wording above, but follows gcc in situations with a field following an 51706c3fb27SDimitry Andric // empty structure. 51806c3fb27SDimitry Andric if (!RD->isUnion()) { 51906c3fb27SDimitry Andric if (HadField) 52006c3fb27SDimitry Andric return false; 52106c3fb27SDimitry Andric 52206c3fb27SDimitry Andric HadField = true; 52306c3fb27SDimitry Andric } 52406c3fb27SDimitry Andric } 52506c3fb27SDimitry Andric 52606c3fb27SDimitry Andric return true; 52706c3fb27SDimitry Andric } 52806c3fb27SDimitry Andric 52906c3fb27SDimitry Andric ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, 53006c3fb27SDimitry Andric unsigned functionCallConv) const { 53106c3fb27SDimitry Andric 53206c3fb27SDimitry Andric // Variadic functions should always marshal to the base standard. 53306c3fb27SDimitry Andric bool IsAAPCS_VFP = 53406c3fb27SDimitry Andric !isVariadic && isEffectivelyAAPCS_VFP(functionCallConv, /* AAPCS16 */ true); 53506c3fb27SDimitry Andric 53606c3fb27SDimitry Andric if (RetTy->isVoidType()) 53706c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 53806c3fb27SDimitry Andric 53906c3fb27SDimitry Andric if (const VectorType *VT = RetTy->getAs<VectorType>()) { 54006c3fb27SDimitry Andric // Large vector types should be returned via memory. 54106c3fb27SDimitry Andric if (getContext().getTypeSize(RetTy) > 128) 54206c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 54306c3fb27SDimitry Andric // TODO: FP16/BF16 vectors should be converted to integer vectors 54406c3fb27SDimitry Andric // This check is similar to isIllegalVectorType - refactor? 54506c3fb27SDimitry Andric if ((!getTarget().hasLegalHalfType() && 54606c3fb27SDimitry Andric (VT->getElementType()->isFloat16Type() || 54706c3fb27SDimitry Andric VT->getElementType()->isHalfType())) || 54806c3fb27SDimitry Andric (IsFloatABISoftFP && 54906c3fb27SDimitry Andric VT->getElementType()->isBFloat16Type())) 55006c3fb27SDimitry Andric return coerceIllegalVector(RetTy); 55106c3fb27SDimitry Andric } 55206c3fb27SDimitry Andric 55306c3fb27SDimitry Andric if (!isAggregateTypeForABI(RetTy)) { 55406c3fb27SDimitry Andric // Treat an enum type as its underlying type. 55506c3fb27SDimitry Andric if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 55606c3fb27SDimitry Andric RetTy = EnumTy->getDecl()->getIntegerType(); 55706c3fb27SDimitry Andric 55806c3fb27SDimitry Andric if (const auto *EIT = RetTy->getAs<BitIntType>()) 55906c3fb27SDimitry Andric if (EIT->getNumBits() > 64) 56006c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); 56106c3fb27SDimitry Andric 56206c3fb27SDimitry Andric return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 56306c3fb27SDimitry Andric : ABIArgInfo::getDirect(); 56406c3fb27SDimitry Andric } 56506c3fb27SDimitry Andric 56606c3fb27SDimitry Andric // Are we following APCS? 56706c3fb27SDimitry Andric if (getABIKind() == ARMABIKind::APCS) { 56806c3fb27SDimitry Andric if (isEmptyRecord(getContext(), RetTy, false)) 56906c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 57006c3fb27SDimitry Andric 57106c3fb27SDimitry Andric // Complex types are all returned as packed integers. 57206c3fb27SDimitry Andric // 57306c3fb27SDimitry Andric // FIXME: Consider using 2 x vector types if the back end handles them 57406c3fb27SDimitry Andric // correctly. 57506c3fb27SDimitry Andric if (RetTy->isAnyComplexType()) 57606c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::IntegerType::get( 57706c3fb27SDimitry Andric getVMContext(), getContext().getTypeSize(RetTy))); 57806c3fb27SDimitry Andric 57906c3fb27SDimitry Andric // Integer like structures are returned in r0. 58006c3fb27SDimitry Andric if (isIntegerLikeType(RetTy, getContext(), getVMContext())) { 58106c3fb27SDimitry Andric // Return in the smallest viable integer type. 58206c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(RetTy); 58306c3fb27SDimitry Andric if (Size <= 8) 58406c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); 58506c3fb27SDimitry Andric if (Size <= 16) 58606c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); 58706c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 58806c3fb27SDimitry Andric } 58906c3fb27SDimitry Andric 59006c3fb27SDimitry Andric // Otherwise return in memory. 59106c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 59206c3fb27SDimitry Andric } 59306c3fb27SDimitry Andric 59406c3fb27SDimitry Andric // Otherwise this is an AAPCS variant. 59506c3fb27SDimitry Andric 59606c3fb27SDimitry Andric if (isEmptyRecord(getContext(), RetTy, true)) 59706c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 59806c3fb27SDimitry Andric 59906c3fb27SDimitry Andric // Check for homogeneous aggregates with AAPCS-VFP. 60006c3fb27SDimitry Andric if (IsAAPCS_VFP) { 60106c3fb27SDimitry Andric const Type *Base = nullptr; 60206c3fb27SDimitry Andric uint64_t Members = 0; 60306c3fb27SDimitry Andric if (isHomogeneousAggregate(RetTy, Base, Members)) 60406c3fb27SDimitry Andric return classifyHomogeneousAggregate(RetTy, Base, Members); 60506c3fb27SDimitry Andric } 60606c3fb27SDimitry Andric 60706c3fb27SDimitry Andric // Aggregates <= 4 bytes are returned in r0; other aggregates 60806c3fb27SDimitry Andric // are returned indirectly. 60906c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(RetTy); 61006c3fb27SDimitry Andric if (Size <= 32) { 61106c3fb27SDimitry Andric // On RenderScript, coerce Aggregates <= 4 bytes to an integer array of 61206c3fb27SDimitry Andric // same size and alignment. 61306c3fb27SDimitry Andric if (getTarget().isRenderScriptTarget()) { 61406c3fb27SDimitry Andric return coerceToIntArray(RetTy, getContext(), getVMContext()); 61506c3fb27SDimitry Andric } 61606c3fb27SDimitry Andric if (getDataLayout().isBigEndian()) 61706c3fb27SDimitry Andric // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) 61806c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 61906c3fb27SDimitry Andric 62006c3fb27SDimitry Andric // Return in the smallest viable integer type. 62106c3fb27SDimitry Andric if (Size <= 8) 62206c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext())); 62306c3fb27SDimitry Andric if (Size <= 16) 62406c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext())); 62506c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext())); 62606c3fb27SDimitry Andric } else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) { 62706c3fb27SDimitry Andric llvm::Type *Int32Ty = llvm::Type::getInt32Ty(getVMContext()); 62806c3fb27SDimitry Andric llvm::Type *CoerceTy = 62906c3fb27SDimitry Andric llvm::ArrayType::get(Int32Ty, llvm::alignTo(Size, 32) / 32); 63006c3fb27SDimitry Andric return ABIArgInfo::getDirect(CoerceTy); 63106c3fb27SDimitry Andric } 63206c3fb27SDimitry Andric 63306c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 63406c3fb27SDimitry Andric } 63506c3fb27SDimitry Andric 63606c3fb27SDimitry Andric /// isIllegalVector - check whether Ty is an illegal vector type. 63706c3fb27SDimitry Andric bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { 63806c3fb27SDimitry Andric if (const VectorType *VT = Ty->getAs<VectorType> ()) { 63906c3fb27SDimitry Andric // On targets that don't support half, fp16 or bfloat, they are expanded 64006c3fb27SDimitry Andric // into float, and we don't want the ABI to depend on whether or not they 64106c3fb27SDimitry Andric // are supported in hardware. Thus return false to coerce vectors of these 64206c3fb27SDimitry Andric // types into integer vectors. 64306c3fb27SDimitry Andric // We do not depend on hasLegalHalfType for bfloat as it is a 64406c3fb27SDimitry Andric // separate IR type. 64506c3fb27SDimitry Andric if ((!getTarget().hasLegalHalfType() && 64606c3fb27SDimitry Andric (VT->getElementType()->isFloat16Type() || 64706c3fb27SDimitry Andric VT->getElementType()->isHalfType())) || 64806c3fb27SDimitry Andric (IsFloatABISoftFP && 64906c3fb27SDimitry Andric VT->getElementType()->isBFloat16Type())) 65006c3fb27SDimitry Andric return true; 65106c3fb27SDimitry Andric if (isAndroid()) { 65206c3fb27SDimitry Andric // Android shipped using Clang 3.1, which supported a slightly different 65306c3fb27SDimitry Andric // vector ABI. The primary differences were that 3-element vector types 65406c3fb27SDimitry Andric // were legal, and so were sub 32-bit vectors (i.e. <2 x i8>). This path 65506c3fb27SDimitry Andric // accepts that legacy behavior for Android only. 65606c3fb27SDimitry Andric // Check whether VT is legal. 65706c3fb27SDimitry Andric unsigned NumElements = VT->getNumElements(); 65806c3fb27SDimitry Andric // NumElements should be power of 2 or equal to 3. 65906c3fb27SDimitry Andric if (!llvm::isPowerOf2_32(NumElements) && NumElements != 3) 66006c3fb27SDimitry Andric return true; 66106c3fb27SDimitry Andric } else { 66206c3fb27SDimitry Andric // Check whether VT is legal. 66306c3fb27SDimitry Andric unsigned NumElements = VT->getNumElements(); 66406c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(VT); 66506c3fb27SDimitry Andric // NumElements should be power of 2. 66606c3fb27SDimitry Andric if (!llvm::isPowerOf2_32(NumElements)) 66706c3fb27SDimitry Andric return true; 66806c3fb27SDimitry Andric // Size should be greater than 32 bits. 66906c3fb27SDimitry Andric return Size <= 32; 67006c3fb27SDimitry Andric } 67106c3fb27SDimitry Andric } 67206c3fb27SDimitry Andric return false; 67306c3fb27SDimitry Andric } 67406c3fb27SDimitry Andric 67506c3fb27SDimitry Andric /// Return true if a type contains any 16-bit floating point vectors 67606c3fb27SDimitry Andric bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { 67706c3fb27SDimitry Andric if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { 6780fca6ea1SDimitry Andric uint64_t NElements = AT->getZExtSize(); 67906c3fb27SDimitry Andric if (NElements == 0) 68006c3fb27SDimitry Andric return false; 68106c3fb27SDimitry Andric return containsAnyFP16Vectors(AT->getElementType()); 68206c3fb27SDimitry Andric } else if (const RecordType *RT = Ty->getAs<RecordType>()) { 68306c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 68406c3fb27SDimitry Andric 68506c3fb27SDimitry Andric // If this is a C++ record, check the bases first. 68606c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 68706c3fb27SDimitry Andric if (llvm::any_of(CXXRD->bases(), [this](const CXXBaseSpecifier &B) { 68806c3fb27SDimitry Andric return containsAnyFP16Vectors(B.getType()); 68906c3fb27SDimitry Andric })) 69006c3fb27SDimitry Andric return true; 69106c3fb27SDimitry Andric 69206c3fb27SDimitry Andric if (llvm::any_of(RD->fields(), [this](FieldDecl *FD) { 69306c3fb27SDimitry Andric return FD && containsAnyFP16Vectors(FD->getType()); 69406c3fb27SDimitry Andric })) 69506c3fb27SDimitry Andric return true; 69606c3fb27SDimitry Andric 69706c3fb27SDimitry Andric return false; 69806c3fb27SDimitry Andric } else { 69906c3fb27SDimitry Andric if (const VectorType *VT = Ty->getAs<VectorType>()) 70006c3fb27SDimitry Andric return (VT->getElementType()->isFloat16Type() || 70106c3fb27SDimitry Andric VT->getElementType()->isBFloat16Type() || 70206c3fb27SDimitry Andric VT->getElementType()->isHalfType()); 70306c3fb27SDimitry Andric return false; 70406c3fb27SDimitry Andric } 70506c3fb27SDimitry Andric } 70606c3fb27SDimitry Andric 70706c3fb27SDimitry Andric bool ARMSwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, 70806c3fb27SDimitry Andric unsigned NumElts) const { 70906c3fb27SDimitry Andric if (!llvm::isPowerOf2_32(NumElts)) 71006c3fb27SDimitry Andric return false; 71106c3fb27SDimitry Andric unsigned size = CGT.getDataLayout().getTypeStoreSizeInBits(EltTy); 71206c3fb27SDimitry Andric if (size > 64) 71306c3fb27SDimitry Andric return false; 71406c3fb27SDimitry Andric if (VectorSize.getQuantity() != 8 && 71506c3fb27SDimitry Andric (VectorSize.getQuantity() != 16 || NumElts == 1)) 71606c3fb27SDimitry Andric return false; 71706c3fb27SDimitry Andric return true; 71806c3fb27SDimitry Andric } 71906c3fb27SDimitry Andric 72006c3fb27SDimitry Andric bool ARMABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { 72106c3fb27SDimitry Andric // Homogeneous aggregates for AAPCS-VFP must have base types of float, 72206c3fb27SDimitry Andric // double, or 64-bit or 128-bit vectors. 72306c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { 72406c3fb27SDimitry Andric if (BT->getKind() == BuiltinType::Float || 72506c3fb27SDimitry Andric BT->getKind() == BuiltinType::Double || 72606c3fb27SDimitry Andric BT->getKind() == BuiltinType::LongDouble) 72706c3fb27SDimitry Andric return true; 72806c3fb27SDimitry Andric } else if (const VectorType *VT = Ty->getAs<VectorType>()) { 72906c3fb27SDimitry Andric unsigned VecSize = getContext().getTypeSize(VT); 73006c3fb27SDimitry Andric if (VecSize == 64 || VecSize == 128) 73106c3fb27SDimitry Andric return true; 73206c3fb27SDimitry Andric } 73306c3fb27SDimitry Andric return false; 73406c3fb27SDimitry Andric } 73506c3fb27SDimitry Andric 73606c3fb27SDimitry Andric bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, 73706c3fb27SDimitry Andric uint64_t Members) const { 73806c3fb27SDimitry Andric return Members <= 4; 73906c3fb27SDimitry Andric } 74006c3fb27SDimitry Andric 74106c3fb27SDimitry Andric bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { 74206c3fb27SDimitry Andric // AAPCS32 says that the rule for whether something is a homogeneous 74306c3fb27SDimitry Andric // aggregate is applied to the output of the data layout decision. So 74406c3fb27SDimitry Andric // anything that doesn't affect the data layout also does not affect 74506c3fb27SDimitry Andric // homogeneity. In particular, zero-length bitfields don't stop a struct 74606c3fb27SDimitry Andric // being homogeneous. 74706c3fb27SDimitry Andric return true; 74806c3fb27SDimitry Andric } 74906c3fb27SDimitry Andric 75006c3fb27SDimitry Andric bool ARMABIInfo::isEffectivelyAAPCS_VFP(unsigned callConvention, 75106c3fb27SDimitry Andric bool acceptHalf) const { 75206c3fb27SDimitry Andric // Give precedence to user-specified calling conventions. 75306c3fb27SDimitry Andric if (callConvention != llvm::CallingConv::C) 75406c3fb27SDimitry Andric return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP); 75506c3fb27SDimitry Andric else 75606c3fb27SDimitry Andric return (getABIKind() == ARMABIKind::AAPCS_VFP) || 75706c3fb27SDimitry Andric (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP)); 75806c3fb27SDimitry Andric } 75906c3fb27SDimitry Andric 7600fca6ea1SDimitry Andric RValue ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 7610fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const { 76206c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(4); 76306c3fb27SDimitry Andric 76406c3fb27SDimitry Andric // Empty records are ignored for parameter passing purposes. 7650fca6ea1SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 7660fca6ea1SDimitry Andric return Slot.asRValue(); 76706c3fb27SDimitry Andric 76806c3fb27SDimitry Andric CharUnits TySize = getContext().getTypeSizeInChars(Ty); 76906c3fb27SDimitry Andric CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(Ty); 77006c3fb27SDimitry Andric 77106c3fb27SDimitry Andric // Use indirect if size of the illegal vector is bigger than 16 bytes. 77206c3fb27SDimitry Andric bool IsIndirect = false; 77306c3fb27SDimitry Andric const Type *Base = nullptr; 77406c3fb27SDimitry Andric uint64_t Members = 0; 77506c3fb27SDimitry Andric if (TySize > CharUnits::fromQuantity(16) && isIllegalVectorType(Ty)) { 77606c3fb27SDimitry Andric IsIndirect = true; 77706c3fb27SDimitry Andric 77806c3fb27SDimitry Andric // ARMv7k passes structs bigger than 16 bytes indirectly, in space 77906c3fb27SDimitry Andric // allocated by the caller. 78006c3fb27SDimitry Andric } else if (TySize > CharUnits::fromQuantity(16) && 78106c3fb27SDimitry Andric getABIKind() == ARMABIKind::AAPCS16_VFP && 78206c3fb27SDimitry Andric !isHomogeneousAggregate(Ty, Base, Members)) { 78306c3fb27SDimitry Andric IsIndirect = true; 78406c3fb27SDimitry Andric 78506c3fb27SDimitry Andric // Otherwise, bound the type's ABI alignment. 78606c3fb27SDimitry Andric // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for 78706c3fb27SDimitry Andric // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte. 78806c3fb27SDimitry Andric // Our callers should be prepared to handle an under-aligned address. 78906c3fb27SDimitry Andric } else if (getABIKind() == ARMABIKind::AAPCS_VFP || 79006c3fb27SDimitry Andric getABIKind() == ARMABIKind::AAPCS) { 79106c3fb27SDimitry Andric TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); 79206c3fb27SDimitry Andric TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(8)); 79306c3fb27SDimitry Andric } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { 79406c3fb27SDimitry Andric // ARMv7k allows type alignment up to 16 bytes. 79506c3fb27SDimitry Andric TyAlignForABI = std::max(TyAlignForABI, CharUnits::fromQuantity(4)); 79606c3fb27SDimitry Andric TyAlignForABI = std::min(TyAlignForABI, CharUnits::fromQuantity(16)); 79706c3fb27SDimitry Andric } else { 79806c3fb27SDimitry Andric TyAlignForABI = CharUnits::fromQuantity(4); 79906c3fb27SDimitry Andric } 80006c3fb27SDimitry Andric 80106c3fb27SDimitry Andric TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None); 8020fca6ea1SDimitry Andric return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect, TyInfo, SlotSize, 8030fca6ea1SDimitry Andric /*AllowHigherAlign*/ true, Slot); 80406c3fb27SDimitry Andric } 80506c3fb27SDimitry Andric 80606c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 80706c3fb27SDimitry Andric CodeGen::createARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind Kind) { 80806c3fb27SDimitry Andric return std::make_unique<ARMTargetCodeGenInfo>(CGM.getTypes(), Kind); 80906c3fb27SDimitry Andric } 81006c3fb27SDimitry Andric 81106c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 81206c3fb27SDimitry Andric CodeGen::createWindowsARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind K) { 81306c3fb27SDimitry Andric return std::make_unique<WindowsARMTargetCodeGenInfo>(CGM.getTypes(), K); 81406c3fb27SDimitry Andric } 815