xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/ARM.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
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