| 1 | //===- ARM.cpp ------------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "ABIInfoImpl.h" |
| 10 | #include "TargetInfo.h" |
| 11 | |
| 12 | using namespace clang; |
| 13 | using namespace clang::CodeGen; |
| 14 | |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | // ARM ABI Implementation |
| 17 | //===----------------------------------------------------------------------===// |
| 18 | |
| 19 | namespace { |
| 20 | |
| 21 | class ARMABIInfo : public ABIInfo { |
| 22 | ARMABIKind Kind; |
| 23 | bool IsFloatABISoftFP; |
| 24 | |
| 25 | public: |
| 26 | ARMABIInfo(CodeGenTypes &CGT, ARMABIKind Kind) : ABIInfo(CGT), Kind(Kind) { |
| 27 | setCCs(); |
| 28 | IsFloatABISoftFP = CGT.getCodeGenOpts().FloatABI == "softfp" || |
| 29 | CGT.getCodeGenOpts().FloatABI == "" ; // default |
| 30 | } |
| 31 | |
| 32 | bool isEABI() const { |
| 33 | switch (getTarget().getTriple().getEnvironment()) { |
| 34 | case llvm::Triple::Android: |
| 35 | case llvm::Triple::EABI: |
| 36 | case llvm::Triple::EABIHF: |
| 37 | case llvm::Triple::GNUEABI: |
| 38 | case llvm::Triple::GNUEABIT64: |
| 39 | case llvm::Triple::GNUEABIHF: |
| 40 | case llvm::Triple::GNUEABIHFT64: |
| 41 | case llvm::Triple::MuslEABI: |
| 42 | case llvm::Triple::MuslEABIHF: |
| 43 | return true; |
| 44 | default: |
| 45 | return getTarget().getTriple().isOHOSFamily(); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | bool isEABIHF() const { |
| 50 | switch (getTarget().getTriple().getEnvironment()) { |
| 51 | case llvm::Triple::EABIHF: |
| 52 | case llvm::Triple::GNUEABIHF: |
| 53 | case llvm::Triple::GNUEABIHFT64: |
| 54 | case llvm::Triple::MuslEABIHF: |
| 55 | return true; |
| 56 | default: |
| 57 | return false; |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | ARMABIKind getABIKind() const { return Kind; } |
| 62 | |
| 63 | bool allowBFloatArgsAndRet() const override { |
| 64 | return !IsFloatABISoftFP && getTarget().hasBFloat16Type(); |
| 65 | } |
| 66 | |
| 67 | private: |
| 68 | ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic, |
| 69 | unsigned functionCallConv) const; |
| 70 | ABIArgInfo classifyArgumentType(QualType RetTy, bool isVariadic, |
| 71 | unsigned functionCallConv) const; |
| 72 | ABIArgInfo classifyHomogeneousAggregate(QualType Ty, const Type *Base, |
| 73 | uint64_t Members) const; |
| 74 | bool shouldIgnoreEmptyArg(QualType Ty) const; |
| 75 | ABIArgInfo coerceIllegalVector(QualType Ty) const; |
| 76 | bool isIllegalVectorType(QualType Ty) const; |
| 77 | bool containsAnyFP16Vectors(QualType Ty) const; |
| 78 | |
| 79 | bool isHomogeneousAggregateBaseType(QualType Ty) const override; |
| 80 | bool isHomogeneousAggregateSmallEnough(const Type *Ty, |
| 81 | uint64_t Members) const override; |
| 82 | bool isZeroLengthBitfieldPermittedInHomogeneousAggregate() const override; |
| 83 | |
| 84 | bool isEffectivelyAAPCS_VFP(unsigned callConvention, bool acceptHalf) const; |
| 85 | |
| 86 | void computeInfo(CGFunctionInfo &FI) const override; |
| 87 | |
| 88 | RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, |
| 89 | AggValueSlot Slot) const override; |
| 90 | |
| 91 | llvm::CallingConv::ID getLLVMDefaultCC() const; |
| 92 | llvm::CallingConv::ID getABIDefaultCC() const; |
| 93 | void setCCs(); |
| 94 | }; |
| 95 | |
| 96 | class ARMSwiftABIInfo : public SwiftABIInfo { |
| 97 | public: |
| 98 | explicit ARMSwiftABIInfo(CodeGenTypes &CGT) |
| 99 | : SwiftABIInfo(CGT, /*SwiftErrorInRegister=*/true) {} |
| 100 | |
| 101 | bool isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, |
| 102 | unsigned NumElts) const override; |
| 103 | }; |
| 104 | |
| 105 | class ARMTargetCodeGenInfo : public TargetCodeGenInfo { |
| 106 | public: |
| 107 | ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) |
| 108 | : TargetCodeGenInfo(std::make_unique<ARMABIInfo>(args&: CGT, args&: K)) { |
| 109 | SwiftInfo = std::make_unique<ARMSwiftABIInfo>(args&: CGT); |
| 110 | } |
| 111 | |
| 112 | int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { |
| 113 | return 13; |
| 114 | } |
| 115 | |
| 116 | StringRef getARCRetainAutoreleasedReturnValueMarker() const override { |
| 117 | return "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue" ; |
| 118 | } |
| 119 | |
| 120 | bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, |
| 121 | llvm::Value *Address) const override { |
| 122 | llvm::Value *Four8 = llvm::ConstantInt::get(Ty: CGF.Int8Ty, V: 4); |
| 123 | |
| 124 | // 0-15 are the 16 integer registers. |
| 125 | AssignToArrayRange(Builder&: CGF.Builder, Array: Address, Value: Four8, FirstIndex: 0, LastIndex: 15); |
| 126 | return false; |
| 127 | } |
| 128 | |
| 129 | unsigned getSizeOfUnwindException() const override { |
| 130 | if (getABIInfo<ARMABIInfo>().isEABI()) |
| 131 | return 88; |
| 132 | return TargetCodeGenInfo::getSizeOfUnwindException(); |
| 133 | } |
| 134 | |
| 135 | void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, |
| 136 | CodeGen::CodeGenModule &CGM) const override { |
| 137 | auto *Fn = dyn_cast<llvm::Function>(Val: GV); |
| 138 | if (!Fn) |
| 139 | return; |
| 140 | const auto *FD = dyn_cast_or_null<FunctionDecl>(Val: D); |
| 141 | |
| 142 | if (FD && FD->hasAttr<TargetAttr>()) { |
| 143 | const auto *TA = FD->getAttr<TargetAttr>(); |
| 144 | ParsedTargetAttr Attr = |
| 145 | CGM.getTarget().parseTargetAttr(Str: TA->getFeaturesStr()); |
| 146 | if (!Attr.BranchProtection.empty()) { |
| 147 | TargetInfo::BranchProtectionInfo BPI{}; |
| 148 | StringRef DiagMsg; |
| 149 | StringRef Arch = |
| 150 | Attr.CPU.empty() ? CGM.getTarget().getTargetOpts().CPU : Attr.CPU; |
| 151 | if (!CGM.getTarget().validateBranchProtection( |
| 152 | Spec: Attr.BranchProtection, Arch, BPI, LO: CGM.getLangOpts(), Err&: DiagMsg)) { |
| 153 | CGM.getDiags().Report( |
| 154 | Loc: D->getLocation(), |
| 155 | DiagID: diag::warn_target_unsupported_branch_protection_attribute) |
| 156 | << Arch; |
| 157 | } else |
| 158 | setBranchProtectionFnAttributes(BPI, F&: (*Fn)); |
| 159 | } else if (CGM.getLangOpts().BranchTargetEnforcement || |
| 160 | CGM.getLangOpts().hasSignReturnAddress()) { |
| 161 | // If the Branch Protection attribute is missing, validate the target |
| 162 | // Architecture attribute against Branch Protection command line |
| 163 | // settings. |
| 164 | if (!CGM.getTarget().isBranchProtectionSupportedArch(Arch: Attr.CPU)) |
| 165 | CGM.getDiags().Report( |
| 166 | Loc: D->getLocation(), |
| 167 | DiagID: diag::warn_target_unsupported_branch_protection_attribute) |
| 168 | << Attr.CPU; |
| 169 | } |
| 170 | } else if (CGM.getTarget().isBranchProtectionSupportedArch( |
| 171 | Arch: CGM.getTarget().getTargetOpts().CPU)) { |
| 172 | TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts()); |
| 173 | setBranchProtectionFnAttributes(BPI, F&: (*Fn)); |
| 174 | } |
| 175 | |
| 176 | if (!FD || !FD->hasAttr<ARMInterruptAttr>()) |
| 177 | return; |
| 178 | |
| 179 | const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); |
| 180 | const char *Kind; |
| 181 | switch (Attr->getInterrupt()) { |
| 182 | case ARMInterruptAttr::Generic: Kind = "" ; break; |
| 183 | case ARMInterruptAttr::IRQ: Kind = "IRQ" ; break; |
| 184 | case ARMInterruptAttr::FIQ: Kind = "FIQ" ; break; |
| 185 | case ARMInterruptAttr::SWI: Kind = "SWI" ; break; |
| 186 | case ARMInterruptAttr::ABORT: Kind = "ABORT" ; break; |
| 187 | case ARMInterruptAttr::UNDEF: Kind = "UNDEF" ; break; |
| 188 | } |
| 189 | |
| 190 | Fn->addFnAttr(Kind: "interrupt" , Val: Kind); |
| 191 | |
| 192 | // Note: the ARMSaveFPAttr can only exist if we also have an interrupt |
| 193 | // attribute |
| 194 | const ARMSaveFPAttr *SaveFPAttr = FD->getAttr<ARMSaveFPAttr>(); |
| 195 | if (SaveFPAttr) |
| 196 | Fn->addFnAttr(Kind: "save-fp" ); |
| 197 | |
| 198 | ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind(); |
| 199 | if (ABI == ARMABIKind::APCS) |
| 200 | return; |
| 201 | |
| 202 | // AAPCS guarantees that sp will be 8-byte aligned on any public interface, |
| 203 | // however this is not necessarily true on taking any interrupt. Instruct |
| 204 | // the backend to perform a realignment as part of the function prologue. |
| 205 | llvm::AttrBuilder B(Fn->getContext()); |
| 206 | B.addStackAlignmentAttr(Align: 8); |
| 207 | Fn->addFnAttrs(Attrs: B); |
| 208 | } |
| 209 | }; |
| 210 | |
| 211 | class WindowsARMTargetCodeGenInfo : public ARMTargetCodeGenInfo { |
| 212 | public: |
| 213 | WindowsARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIKind K) |
| 214 | : ARMTargetCodeGenInfo(CGT, K) {} |
| 215 | |
| 216 | void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, |
| 217 | CodeGen::CodeGenModule &CGM) const override; |
| 218 | |
| 219 | void getDependentLibraryOption(llvm::StringRef Lib, |
| 220 | llvm::SmallString<24> &Opt) const override { |
| 221 | Opt = "/DEFAULTLIB:" + qualifyWindowsLibrary(Lib); |
| 222 | } |
| 223 | |
| 224 | void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, |
| 225 | llvm::SmallString<32> &Opt) const override { |
| 226 | Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"" ; |
| 227 | } |
| 228 | }; |
| 229 | |
| 230 | void WindowsARMTargetCodeGenInfo::setTargetAttributes( |
| 231 | const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { |
| 232 | ARMTargetCodeGenInfo::setTargetAttributes(D, GV, CGM); |
| 233 | if (GV->isDeclaration()) |
| 234 | return; |
| 235 | addStackProbeTargetAttributes(D, GV, CGM); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { |
| 240 | if (!::classifyReturnType(CXXABI: getCXXABI(), FI, Info: *this)) |
| 241 | FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType(), isVariadic: FI.isVariadic(), |
| 242 | functionCallConv: FI.getCallingConvention()); |
| 243 | |
| 244 | for (auto &I : FI.arguments()) |
| 245 | I.info = classifyArgumentType(RetTy: I.type, isVariadic: FI.isVariadic(), |
| 246 | functionCallConv: FI.getCallingConvention()); |
| 247 | |
| 248 | |
| 249 | // Always honor user-specified calling convention. |
| 250 | if (FI.getCallingConvention() != llvm::CallingConv::C) |
| 251 | return; |
| 252 | |
| 253 | llvm::CallingConv::ID cc = getRuntimeCC(); |
| 254 | if (cc != llvm::CallingConv::C) |
| 255 | FI.setEffectiveCallingConvention(cc); |
| 256 | } |
| 257 | |
| 258 | /// Return the default calling convention that LLVM will use. |
| 259 | llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const { |
| 260 | // The default calling convention that LLVM will infer. |
| 261 | if (isEABIHF() || getTarget().getTriple().isWatchABI()) |
| 262 | return llvm::CallingConv::ARM_AAPCS_VFP; |
| 263 | else if (isEABI()) |
| 264 | return llvm::CallingConv::ARM_AAPCS; |
| 265 | else |
| 266 | return llvm::CallingConv::ARM_APCS; |
| 267 | } |
| 268 | |
| 269 | /// Return the calling convention that our ABI would like us to use |
| 270 | /// as the C calling convention. |
| 271 | llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const { |
| 272 | switch (getABIKind()) { |
| 273 | case ARMABIKind::APCS: |
| 274 | return llvm::CallingConv::ARM_APCS; |
| 275 | case ARMABIKind::AAPCS: |
| 276 | return llvm::CallingConv::ARM_AAPCS; |
| 277 | case ARMABIKind::AAPCS_VFP: |
| 278 | return llvm::CallingConv::ARM_AAPCS_VFP; |
| 279 | case ARMABIKind::AAPCS16_VFP: |
| 280 | return llvm::CallingConv::ARM_AAPCS_VFP; |
| 281 | } |
| 282 | llvm_unreachable("bad ABI kind" ); |
| 283 | } |
| 284 | |
| 285 | void ARMABIInfo::setCCs() { |
| 286 | assert(getRuntimeCC() == llvm::CallingConv::C); |
| 287 | |
| 288 | // Don't muddy up the IR with a ton of explicit annotations if |
| 289 | // they'd just match what LLVM will infer from the triple. |
| 290 | llvm::CallingConv::ID abiCC = getABIDefaultCC(); |
| 291 | if (abiCC != getLLVMDefaultCC()) |
| 292 | RuntimeCC = abiCC; |
| 293 | } |
| 294 | |
| 295 | ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const { |
| 296 | uint64_t Size = getContext().getTypeSize(T: Ty); |
| 297 | if (Size <= 32) { |
| 298 | llvm::Type *ResType = |
| 299 | llvm::Type::getInt32Ty(C&: getVMContext()); |
| 300 | return ABIArgInfo::getDirect(T: ResType); |
| 301 | } |
| 302 | if (Size == 64 || Size == 128) { |
| 303 | auto *ResType = llvm::FixedVectorType::get( |
| 304 | ElementType: llvm::Type::getInt32Ty(C&: getVMContext()), NumElts: Size / 32); |
| 305 | return ABIArgInfo::getDirect(T: ResType); |
| 306 | } |
| 307 | return getNaturalAlignIndirect( |
| 308 | Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), |
| 309 | /*ByVal=*/false); |
| 310 | } |
| 311 | |
| 312 | ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty, |
| 313 | const Type *Base, |
| 314 | uint64_t Members) const { |
| 315 | assert(Base && "Base class should be set for homogeneous aggregate" ); |
| 316 | // Base can be a floating-point or a vector. |
| 317 | if (const VectorType *VT = Base->getAs<VectorType>()) { |
| 318 | // FP16 vectors should be converted to integer vectors |
| 319 | if (!getTarget().hasLegalHalfType() && containsAnyFP16Vectors(Ty)) { |
| 320 | uint64_t Size = getContext().getTypeSize(T: VT); |
| 321 | auto *NewVecTy = llvm::FixedVectorType::get( |
| 322 | ElementType: llvm::Type::getInt32Ty(C&: getVMContext()), NumElts: Size / 32); |
| 323 | llvm::Type *Ty = llvm::ArrayType::get(ElementType: NewVecTy, NumElements: Members); |
| 324 | return ABIArgInfo::getDirect(T: Ty, Offset: 0, Padding: nullptr, CanBeFlattened: false); |
| 325 | } |
| 326 | } |
| 327 | unsigned Align = 0; |
| 328 | if (getABIKind() == ARMABIKind::AAPCS || |
| 329 | getABIKind() == ARMABIKind::AAPCS_VFP) { |
| 330 | // For alignment adjusted HFAs, cap the argument alignment to 8, leave it |
| 331 | // default otherwise. |
| 332 | Align = getContext().getTypeUnadjustedAlignInChars(T: Ty).getQuantity(); |
| 333 | unsigned BaseAlign = getContext().getTypeAlignInChars(T: Base).getQuantity(); |
| 334 | Align = (Align > BaseAlign && Align >= 8) ? 8 : 0; |
| 335 | } |
| 336 | return ABIArgInfo::getDirect(T: nullptr, Offset: 0, Padding: nullptr, CanBeFlattened: false, Align); |
| 337 | } |
| 338 | |
| 339 | bool ARMABIInfo::shouldIgnoreEmptyArg(QualType Ty) const { |
| 340 | uint64_t Size = getContext().getTypeSize(T: Ty); |
| 341 | assert((isEmptyRecord(getContext(), Ty, true) || Size == 0) && |
| 342 | "Arg is not empty" ); |
| 343 | |
| 344 | // Empty records are ignored in C mode, and in C++ on WatchOS. |
| 345 | if (!getContext().getLangOpts().CPlusPlus || |
| 346 | getABIKind() == ARMABIKind::AAPCS16_VFP) |
| 347 | return true; |
| 348 | |
| 349 | // In C++ mode, arguments which have sizeof() == 0 are ignored. This is not a |
| 350 | // situation which is defined by any C++ standard or ABI, but this matches |
| 351 | // GCC's de facto ABI. |
| 352 | if (Size == 0) |
| 353 | return true; |
| 354 | |
| 355 | // Clang 19.0 and earlier always ignored empty struct arguments in C++ mode. |
| 356 | if (getContext().getLangOpts().getClangABICompat() <= |
| 357 | LangOptions::ClangABI::Ver19) |
| 358 | return true; |
| 359 | |
| 360 | // Otherwise, they are passed as if they have a size of 1 byte. |
| 361 | return false; |
| 362 | } |
| 363 | |
| 364 | ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, |
| 365 | unsigned functionCallConv) const { |
| 366 | // 6.1.2.1 The following argument types are VFP CPRCs: |
| 367 | // A single-precision floating-point type (including promoted |
| 368 | // half-precision types); A double-precision floating-point type; |
| 369 | // A 64-bit or 128-bit containerized vector type; Homogeneous Aggregate |
| 370 | // with a Base Type of a single- or double-precision floating-point type, |
| 371 | // 64-bit containerized vectors or 128-bit containerized vectors with one |
| 372 | // to four Elements. |
| 373 | // Variadic functions should always marshal to the base standard. |
| 374 | bool IsAAPCS_VFP = |
| 375 | !isVariadic && isEffectivelyAAPCS_VFP(callConvention: functionCallConv, /* AAPCS16 */ acceptHalf: false); |
| 376 | |
| 377 | Ty = useFirstFieldIfTransparentUnion(Ty); |
| 378 | |
| 379 | // Handle illegal vector types here. |
| 380 | if (isIllegalVectorType(Ty)) |
| 381 | return coerceIllegalVector(Ty); |
| 382 | |
| 383 | if (!isAggregateTypeForABI(T: Ty)) { |
| 384 | // Treat an enum type as its underlying type. |
| 385 | if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { |
| 386 | Ty = EnumTy->getDecl()->getIntegerType(); |
| 387 | } |
| 388 | |
| 389 | if (const auto *EIT = Ty->getAs<BitIntType>()) |
| 390 | if (EIT->getNumBits() > 64) |
| 391 | return getNaturalAlignIndirect( |
| 392 | Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), |
| 393 | /*ByVal=*/true); |
| 394 | |
| 395 | return (isPromotableIntegerTypeForABI(Ty) |
| 396 | ? ABIArgInfo::getExtend(Ty, T: CGT.ConvertType(T: Ty)) |
| 397 | : ABIArgInfo::getDirect()); |
| 398 | } |
| 399 | |
| 400 | if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(T: Ty, CXXABI&: getCXXABI())) { |
| 401 | return getNaturalAlignIndirect(Ty, AddrSpace: getDataLayout().getAllocaAddrSpace(), |
| 402 | ByVal: RAA == CGCXXABI::RAA_DirectInMemory); |
| 403 | } |
| 404 | |
| 405 | // Empty records are either ignored completely or passed as if they were a |
| 406 | // 1-byte object, depending on the ABI and language standard. |
| 407 | if (isEmptyRecord(Context&: getContext(), T: Ty, AllowArrays: true) || |
| 408 | getContext().getTypeSize(T: Ty) == 0) { |
| 409 | if (shouldIgnoreEmptyArg(Ty)) |
| 410 | return ABIArgInfo::getIgnore(); |
| 411 | else |
| 412 | return ABIArgInfo::getDirect(T: llvm::Type::getInt8Ty(C&: getVMContext())); |
| 413 | } |
| 414 | |
| 415 | if (IsAAPCS_VFP) { |
| 416 | // Homogeneous Aggregates need to be expanded when we can fit the aggregate |
| 417 | // into VFP registers. |
| 418 | const Type *Base = nullptr; |
| 419 | uint64_t Members = 0; |
| 420 | if (isHomogeneousAggregate(Ty, Base, Members)) |
| 421 | return classifyHomogeneousAggregate(Ty, Base, Members); |
| 422 | } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { |
| 423 | // WatchOS does have homogeneous aggregates. Note that we intentionally use |
| 424 | // this convention even for a variadic function: the backend will use GPRs |
| 425 | // if needed. |
| 426 | const Type *Base = nullptr; |
| 427 | uint64_t Members = 0; |
| 428 | if (isHomogeneousAggregate(Ty, Base, Members)) { |
| 429 | assert(Base && Members <= 4 && "unexpected homogeneous aggregate" ); |
| 430 | llvm::Type *Ty = |
| 431 | llvm::ArrayType::get(ElementType: CGT.ConvertType(T: QualType(Base, 0)), NumElements: Members); |
| 432 | return ABIArgInfo::getDirect(T: Ty, Offset: 0, Padding: nullptr, CanBeFlattened: false); |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | if (getABIKind() == ARMABIKind::AAPCS16_VFP && |
| 437 | getContext().getTypeSizeInChars(T: Ty) > CharUnits::fromQuantity(Quantity: 16)) { |
| 438 | // WatchOS is adopting the 64-bit AAPCS rule on composite types: if they're |
| 439 | // bigger than 128-bits, they get placed in space allocated by the caller, |
| 440 | // and a pointer is passed. |
| 441 | return ABIArgInfo::getIndirect( |
| 442 | Alignment: CharUnits::fromQuantity(Quantity: getContext().getTypeAlign(T: Ty) / 8), |
| 443 | AddrSpace: getDataLayout().getAllocaAddrSpace(), ByVal: false); |
| 444 | } |
| 445 | |
| 446 | // Support byval for ARM. |
| 447 | // The ABI alignment for APCS is 4-byte and for AAPCS at least 4-byte and at |
| 448 | // most 8-byte. We realign the indirect argument if type alignment is bigger |
| 449 | // than ABI alignment. |
| 450 | uint64_t ABIAlign = 4; |
| 451 | uint64_t TyAlign; |
| 452 | if (getABIKind() == ARMABIKind::AAPCS_VFP || |
| 453 | getABIKind() == ARMABIKind::AAPCS) { |
| 454 | TyAlign = getContext().getTypeUnadjustedAlignInChars(T: Ty).getQuantity(); |
| 455 | ABIAlign = std::clamp(val: TyAlign, lo: (uint64_t)4, hi: (uint64_t)8); |
| 456 | } else { |
| 457 | TyAlign = getContext().getTypeAlignInChars(T: Ty).getQuantity(); |
| 458 | } |
| 459 | if (getContext().getTypeSizeInChars(T: Ty) > CharUnits::fromQuantity(Quantity: 64)) { |
| 460 | assert(getABIKind() != ARMABIKind::AAPCS16_VFP && "unexpected byval" ); |
| 461 | return ABIArgInfo::getIndirect( |
| 462 | Alignment: CharUnits::fromQuantity(Quantity: ABIAlign), |
| 463 | /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), |
| 464 | /*ByVal=*/true, /*Realign=*/TyAlign > ABIAlign); |
| 465 | } |
| 466 | |
| 467 | // Otherwise, pass by coercing to a structure of the appropriate size. |
| 468 | llvm::Type* ElemTy; |
| 469 | unsigned SizeRegs; |
| 470 | // FIXME: Try to match the types of the arguments more accurately where |
| 471 | // we can. |
| 472 | if (TyAlign <= 4) { |
| 473 | ElemTy = llvm::Type::getInt32Ty(C&: getVMContext()); |
| 474 | SizeRegs = (getContext().getTypeSize(T: Ty) + 31) / 32; |
| 475 | } else { |
| 476 | ElemTy = llvm::Type::getInt64Ty(C&: getVMContext()); |
| 477 | SizeRegs = (getContext().getTypeSize(T: Ty) + 63) / 64; |
| 478 | } |
| 479 | |
| 480 | return ABIArgInfo::getDirect(T: llvm::ArrayType::get(ElementType: ElemTy, NumElements: SizeRegs)); |
| 481 | } |
| 482 | |
| 483 | static bool isIntegerLikeType(QualType Ty, ASTContext &Context, |
| 484 | llvm::LLVMContext &VMContext) { |
| 485 | // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure |
| 486 | // is called integer-like if its size is less than or equal to one word, and |
| 487 | // the offset of each of its addressable sub-fields is zero. |
| 488 | |
| 489 | uint64_t Size = Context.getTypeSize(T: Ty); |
| 490 | |
| 491 | // Check that the type fits in a word. |
| 492 | if (Size > 32) |
| 493 | return false; |
| 494 | |
| 495 | // FIXME: Handle vector types! |
| 496 | if (Ty->isVectorType()) |
| 497 | return false; |
| 498 | |
| 499 | // Float types are never treated as "integer like". |
| 500 | if (Ty->isRealFloatingType()) |
| 501 | return false; |
| 502 | |
| 503 | // If this is a builtin or pointer type then it is ok. |
| 504 | if (Ty->getAs<BuiltinType>() || Ty->isPointerType()) |
| 505 | return true; |
| 506 | |
| 507 | // Small complex integer types are "integer like". |
| 508 | if (const ComplexType *CT = Ty->getAs<ComplexType>()) |
| 509 | return isIntegerLikeType(Ty: CT->getElementType(), Context, VMContext); |
| 510 | |
| 511 | // Single element and zero sized arrays should be allowed, by the definition |
| 512 | // above, but they are not. |
| 513 | |
| 514 | // Otherwise, it must be a record type. |
| 515 | const RecordType *RT = Ty->getAs<RecordType>(); |
| 516 | if (!RT) return false; |
| 517 | |
| 518 | // Ignore records with flexible arrays. |
| 519 | const RecordDecl *RD = RT->getDecl(); |
| 520 | if (RD->hasFlexibleArrayMember()) |
| 521 | return false; |
| 522 | |
| 523 | // Check that all sub-fields are at offset 0, and are themselves "integer |
| 524 | // like". |
| 525 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(D: RD); |
| 526 | |
| 527 | bool HadField = false; |
| 528 | unsigned idx = 0; |
| 529 | for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); |
| 530 | i != e; ++i, ++idx) { |
| 531 | const FieldDecl *FD = *i; |
| 532 | |
| 533 | // Bit-fields are not addressable, we only need to verify they are "integer |
| 534 | // like". We still have to disallow a subsequent non-bitfield, for example: |
| 535 | // struct { int : 0; int x } |
| 536 | // is non-integer like according to gcc. |
| 537 | if (FD->isBitField()) { |
| 538 | if (!RD->isUnion()) |
| 539 | HadField = true; |
| 540 | |
| 541 | if (!isIntegerLikeType(Ty: FD->getType(), Context, VMContext)) |
| 542 | return false; |
| 543 | |
| 544 | continue; |
| 545 | } |
| 546 | |
| 547 | // Check if this field is at offset 0. |
| 548 | if (Layout.getFieldOffset(FieldNo: idx) != 0) |
| 549 | return false; |
| 550 | |
| 551 | if (!isIntegerLikeType(Ty: FD->getType(), Context, VMContext)) |
| 552 | return false; |
| 553 | |
| 554 | // Only allow at most one field in a structure. This doesn't match the |
| 555 | // wording above, but follows gcc in situations with a field following an |
| 556 | // empty structure. |
| 557 | if (!RD->isUnion()) { |
| 558 | if (HadField) |
| 559 | return false; |
| 560 | |
| 561 | HadField = true; |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | return true; |
| 566 | } |
| 567 | |
| 568 | ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, |
| 569 | unsigned functionCallConv) const { |
| 570 | |
| 571 | // Variadic functions should always marshal to the base standard. |
| 572 | bool IsAAPCS_VFP = |
| 573 | !isVariadic && isEffectivelyAAPCS_VFP(callConvention: functionCallConv, /* AAPCS16 */ acceptHalf: true); |
| 574 | |
| 575 | if (RetTy->isVoidType()) |
| 576 | return ABIArgInfo::getIgnore(); |
| 577 | |
| 578 | if (const VectorType *VT = RetTy->getAs<VectorType>()) { |
| 579 | // Large vector types should be returned via memory. |
| 580 | if (getContext().getTypeSize(T: RetTy) > 128) |
| 581 | return getNaturalAlignIndirect(Ty: RetTy, |
| 582 | AddrSpace: getDataLayout().getAllocaAddrSpace()); |
| 583 | // TODO: FP16/BF16 vectors should be converted to integer vectors |
| 584 | // This check is similar to isIllegalVectorType - refactor? |
| 585 | if ((!getTarget().hasLegalHalfType() && |
| 586 | (VT->getElementType()->isFloat16Type() || |
| 587 | VT->getElementType()->isHalfType())) || |
| 588 | (IsFloatABISoftFP && |
| 589 | VT->getElementType()->isBFloat16Type())) |
| 590 | return coerceIllegalVector(Ty: RetTy); |
| 591 | } |
| 592 | |
| 593 | if (!isAggregateTypeForABI(T: RetTy)) { |
| 594 | // Treat an enum type as its underlying type. |
| 595 | if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) |
| 596 | RetTy = EnumTy->getDecl()->getIntegerType(); |
| 597 | |
| 598 | if (const auto *EIT = RetTy->getAs<BitIntType>()) |
| 599 | if (EIT->getNumBits() > 64) |
| 600 | return getNaturalAlignIndirect( |
| 601 | Ty: RetTy, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), |
| 602 | /*ByVal=*/false); |
| 603 | |
| 604 | return isPromotableIntegerTypeForABI(Ty: RetTy) ? ABIArgInfo::getExtend(Ty: RetTy) |
| 605 | : ABIArgInfo::getDirect(); |
| 606 | } |
| 607 | |
| 608 | // Are we following APCS? |
| 609 | if (getABIKind() == ARMABIKind::APCS) { |
| 610 | if (isEmptyRecord(Context&: getContext(), T: RetTy, AllowArrays: false)) |
| 611 | return ABIArgInfo::getIgnore(); |
| 612 | |
| 613 | // Complex types are all returned as packed integers. |
| 614 | // |
| 615 | // FIXME: Consider using 2 x vector types if the back end handles them |
| 616 | // correctly. |
| 617 | if (RetTy->isAnyComplexType()) |
| 618 | return ABIArgInfo::getDirect(T: llvm::IntegerType::get( |
| 619 | C&: getVMContext(), NumBits: getContext().getTypeSize(T: RetTy))); |
| 620 | |
| 621 | // Integer like structures are returned in r0. |
| 622 | if (isIntegerLikeType(Ty: RetTy, Context&: getContext(), VMContext&: getVMContext())) { |
| 623 | // Return in the smallest viable integer type. |
| 624 | uint64_t Size = getContext().getTypeSize(T: RetTy); |
| 625 | if (Size <= 8) |
| 626 | return ABIArgInfo::getDirect(T: llvm::Type::getInt8Ty(C&: getVMContext())); |
| 627 | if (Size <= 16) |
| 628 | return ABIArgInfo::getDirect(T: llvm::Type::getInt16Ty(C&: getVMContext())); |
| 629 | return ABIArgInfo::getDirect(T: llvm::Type::getInt32Ty(C&: getVMContext())); |
| 630 | } |
| 631 | |
| 632 | // Otherwise return in memory. |
| 633 | return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getDataLayout().getAllocaAddrSpace()); |
| 634 | } |
| 635 | |
| 636 | // Otherwise this is an AAPCS variant. |
| 637 | |
| 638 | if (isEmptyRecord(Context&: getContext(), T: RetTy, AllowArrays: true) || |
| 639 | getContext().getTypeSize(T: RetTy) == 0) |
| 640 | return ABIArgInfo::getIgnore(); |
| 641 | |
| 642 | // Check for homogeneous aggregates with AAPCS-VFP. |
| 643 | if (IsAAPCS_VFP) { |
| 644 | const Type *Base = nullptr; |
| 645 | uint64_t Members = 0; |
| 646 | if (isHomogeneousAggregate(Ty: RetTy, Base, Members)) |
| 647 | return classifyHomogeneousAggregate(Ty: RetTy, Base, Members); |
| 648 | } |
| 649 | |
| 650 | // Aggregates <= 4 bytes are returned in r0; other aggregates |
| 651 | // are returned indirectly. |
| 652 | uint64_t Size = getContext().getTypeSize(T: RetTy); |
| 653 | if (Size <= 32) { |
| 654 | if (getDataLayout().isBigEndian()) |
| 655 | // Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4) |
| 656 | return ABIArgInfo::getDirect(T: llvm::Type::getInt32Ty(C&: getVMContext())); |
| 657 | |
| 658 | // Return in the smallest viable integer type. |
| 659 | if (Size <= 8) |
| 660 | return ABIArgInfo::getDirect(T: llvm::Type::getInt8Ty(C&: getVMContext())); |
| 661 | if (Size <= 16) |
| 662 | return ABIArgInfo::getDirect(T: llvm::Type::getInt16Ty(C&: getVMContext())); |
| 663 | return ABIArgInfo::getDirect(T: llvm::Type::getInt32Ty(C&: getVMContext())); |
| 664 | } else if (Size <= 128 && getABIKind() == ARMABIKind::AAPCS16_VFP) { |
| 665 | llvm::Type *Int32Ty = llvm::Type::getInt32Ty(C&: getVMContext()); |
| 666 | llvm::Type *CoerceTy = |
| 667 | llvm::ArrayType::get(ElementType: Int32Ty, NumElements: llvm::alignTo(Value: Size, Align: 32) / 32); |
| 668 | return ABIArgInfo::getDirect(T: CoerceTy); |
| 669 | } |
| 670 | |
| 671 | return getNaturalAlignIndirect(Ty: RetTy, AddrSpace: getDataLayout().getAllocaAddrSpace()); |
| 672 | } |
| 673 | |
| 674 | /// isIllegalVector - check whether Ty is an illegal vector type. |
| 675 | bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { |
| 676 | if (const VectorType *VT = Ty->getAs<VectorType> ()) { |
| 677 | // On targets that don't support half, fp16 or bfloat, they are expanded |
| 678 | // into float, and we don't want the ABI to depend on whether or not they |
| 679 | // are supported in hardware. Thus return false to coerce vectors of these |
| 680 | // types into integer vectors. |
| 681 | // We do not depend on hasLegalHalfType for bfloat as it is a |
| 682 | // separate IR type. |
| 683 | if ((!getTarget().hasLegalHalfType() && |
| 684 | (VT->getElementType()->isFloat16Type() || |
| 685 | VT->getElementType()->isHalfType())) || |
| 686 | (IsFloatABISoftFP && |
| 687 | VT->getElementType()->isBFloat16Type())) |
| 688 | return true; |
| 689 | if (isAndroid()) { |
| 690 | // Android shipped using Clang 3.1, which supported a slightly different |
| 691 | // vector ABI. The primary differences were that 3-element vector types |
| 692 | // were legal, and so were sub 32-bit vectors (i.e. <2 x i8>). This path |
| 693 | // accepts that legacy behavior for Android only. |
| 694 | // Check whether VT is legal. |
| 695 | unsigned NumElements = VT->getNumElements(); |
| 696 | // NumElements should be power of 2 or equal to 3. |
| 697 | if (!llvm::isPowerOf2_32(Value: NumElements) && NumElements != 3) |
| 698 | return true; |
| 699 | } else { |
| 700 | // Check whether VT is legal. |
| 701 | unsigned NumElements = VT->getNumElements(); |
| 702 | uint64_t Size = getContext().getTypeSize(T: VT); |
| 703 | // NumElements should be power of 2. |
| 704 | if (!llvm::isPowerOf2_32(Value: NumElements)) |
| 705 | return true; |
| 706 | // Size should be greater than 32 bits. |
| 707 | return Size <= 32; |
| 708 | } |
| 709 | } |
| 710 | return false; |
| 711 | } |
| 712 | |
| 713 | /// Return true if a type contains any 16-bit floating point vectors |
| 714 | bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { |
| 715 | if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(T: Ty)) { |
| 716 | uint64_t NElements = AT->getZExtSize(); |
| 717 | if (NElements == 0) |
| 718 | return false; |
| 719 | return containsAnyFP16Vectors(Ty: AT->getElementType()); |
| 720 | } else if (const RecordType *RT = Ty->getAs<RecordType>()) { |
| 721 | const RecordDecl *RD = RT->getDecl(); |
| 722 | |
| 723 | // If this is a C++ record, check the bases first. |
| 724 | if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD)) |
| 725 | if (llvm::any_of(Range: CXXRD->bases(), P: [this](const CXXBaseSpecifier &B) { |
| 726 | return containsAnyFP16Vectors(Ty: B.getType()); |
| 727 | })) |
| 728 | return true; |
| 729 | |
| 730 | if (llvm::any_of(Range: RD->fields(), P: [this](FieldDecl *FD) { |
| 731 | return FD && containsAnyFP16Vectors(Ty: FD->getType()); |
| 732 | })) |
| 733 | return true; |
| 734 | |
| 735 | return false; |
| 736 | } else { |
| 737 | if (const VectorType *VT = Ty->getAs<VectorType>()) |
| 738 | return (VT->getElementType()->isFloat16Type() || |
| 739 | VT->getElementType()->isBFloat16Type() || |
| 740 | VT->getElementType()->isHalfType()); |
| 741 | return false; |
| 742 | } |
| 743 | } |
| 744 | |
| 745 | bool ARMSwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy, |
| 746 | unsigned NumElts) const { |
| 747 | if (!llvm::isPowerOf2_32(Value: NumElts)) |
| 748 | return false; |
| 749 | unsigned size = CGT.getDataLayout().getTypeStoreSizeInBits(Ty: EltTy); |
| 750 | if (size > 64) |
| 751 | return false; |
| 752 | if (VectorSize.getQuantity() != 8 && |
| 753 | (VectorSize.getQuantity() != 16 || NumElts == 1)) |
| 754 | return false; |
| 755 | return true; |
| 756 | } |
| 757 | |
| 758 | bool ARMABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { |
| 759 | // Homogeneous aggregates for AAPCS-VFP must have base types of float, |
| 760 | // double, or 64-bit or 128-bit vectors. |
| 761 | if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { |
| 762 | if (BT->getKind() == BuiltinType::Float || |
| 763 | BT->getKind() == BuiltinType::Double || |
| 764 | BT->getKind() == BuiltinType::LongDouble) |
| 765 | return true; |
| 766 | } else if (const VectorType *VT = Ty->getAs<VectorType>()) { |
| 767 | unsigned VecSize = getContext().getTypeSize(T: VT); |
| 768 | if (VecSize == 64 || VecSize == 128) |
| 769 | return true; |
| 770 | } |
| 771 | return false; |
| 772 | } |
| 773 | |
| 774 | bool ARMABIInfo::isHomogeneousAggregateSmallEnough(const Type *Base, |
| 775 | uint64_t Members) const { |
| 776 | return Members <= 4; |
| 777 | } |
| 778 | |
| 779 | bool ARMABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { |
| 780 | // AAPCS32 says that the rule for whether something is a homogeneous |
| 781 | // aggregate is applied to the output of the data layout decision. So |
| 782 | // anything that doesn't affect the data layout also does not affect |
| 783 | // homogeneity. In particular, zero-length bitfields don't stop a struct |
| 784 | // being homogeneous. |
| 785 | return true; |
| 786 | } |
| 787 | |
| 788 | bool ARMABIInfo::isEffectivelyAAPCS_VFP(unsigned callConvention, |
| 789 | bool acceptHalf) const { |
| 790 | // Give precedence to user-specified calling conventions. |
| 791 | if (callConvention != llvm::CallingConv::C) |
| 792 | return (callConvention == llvm::CallingConv::ARM_AAPCS_VFP); |
| 793 | else |
| 794 | return (getABIKind() == ARMABIKind::AAPCS_VFP) || |
| 795 | (acceptHalf && (getABIKind() == ARMABIKind::AAPCS16_VFP)); |
| 796 | } |
| 797 | |
| 798 | RValue ARMABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, |
| 799 | QualType Ty, AggValueSlot Slot) const { |
| 800 | CharUnits SlotSize = CharUnits::fromQuantity(Quantity: 4); |
| 801 | |
| 802 | // Empty records are ignored for parameter passing purposes. |
| 803 | uint64_t Size = getContext().getTypeSize(T: Ty); |
| 804 | bool IsEmpty = isEmptyRecord(Context&: getContext(), T: Ty, AllowArrays: true); |
| 805 | if ((IsEmpty || Size == 0) && shouldIgnoreEmptyArg(Ty)) |
| 806 | return Slot.asRValue(); |
| 807 | |
| 808 | CharUnits TySize = getContext().getTypeSizeInChars(T: Ty); |
| 809 | CharUnits TyAlignForABI = getContext().getTypeUnadjustedAlignInChars(T: Ty); |
| 810 | |
| 811 | // Use indirect if size of the illegal vector is bigger than 16 bytes. |
| 812 | bool IsIndirect = false; |
| 813 | const Type *Base = nullptr; |
| 814 | uint64_t Members = 0; |
| 815 | if (TySize > CharUnits::fromQuantity(Quantity: 16) && isIllegalVectorType(Ty)) { |
| 816 | IsIndirect = true; |
| 817 | |
| 818 | // ARMv7k passes structs bigger than 16 bytes indirectly, in space |
| 819 | // allocated by the caller. |
| 820 | } else if (TySize > CharUnits::fromQuantity(Quantity: 16) && |
| 821 | getABIKind() == ARMABIKind::AAPCS16_VFP && |
| 822 | !isHomogeneousAggregate(Ty, Base, Members)) { |
| 823 | IsIndirect = true; |
| 824 | |
| 825 | // Otherwise, bound the type's ABI alignment. |
| 826 | // The ABI alignment for 64-bit or 128-bit vectors is 8 for AAPCS and 4 for |
| 827 | // APCS. For AAPCS, the ABI alignment is at least 4-byte and at most 8-byte. |
| 828 | // Our callers should be prepared to handle an under-aligned address. |
| 829 | } else if (getABIKind() == ARMABIKind::AAPCS_VFP || |
| 830 | getABIKind() == ARMABIKind::AAPCS) { |
| 831 | TyAlignForABI = std::max(a: TyAlignForABI, b: CharUnits::fromQuantity(Quantity: 4)); |
| 832 | TyAlignForABI = std::min(a: TyAlignForABI, b: CharUnits::fromQuantity(Quantity: 8)); |
| 833 | } else if (getABIKind() == ARMABIKind::AAPCS16_VFP) { |
| 834 | // ARMv7k allows type alignment up to 16 bytes. |
| 835 | TyAlignForABI = std::max(a: TyAlignForABI, b: CharUnits::fromQuantity(Quantity: 4)); |
| 836 | TyAlignForABI = std::min(a: TyAlignForABI, b: CharUnits::fromQuantity(Quantity: 16)); |
| 837 | } else { |
| 838 | TyAlignForABI = CharUnits::fromQuantity(Quantity: 4); |
| 839 | } |
| 840 | |
| 841 | TypeInfoChars TyInfo(TySize, TyAlignForABI, AlignRequirementKind::None); |
| 842 | return emitVoidPtrVAArg(CGF, VAListAddr, ValueTy: Ty, IsIndirect, ValueInfo: TyInfo, SlotSizeAndAlign: SlotSize, |
| 843 | /*AllowHigherAlign*/ true, Slot); |
| 844 | } |
| 845 | |
| 846 | std::unique_ptr<TargetCodeGenInfo> |
| 847 | CodeGen::createARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind Kind) { |
| 848 | return std::make_unique<ARMTargetCodeGenInfo>(args&: CGM.getTypes(), args&: Kind); |
| 849 | } |
| 850 | |
| 851 | std::unique_ptr<TargetCodeGenInfo> |
| 852 | CodeGen::createWindowsARMTargetCodeGenInfo(CodeGenModule &CGM, ARMABIKind K) { |
| 853 | return std::make_unique<WindowsARMTargetCodeGenInfo>(args&: CGM.getTypes(), args&: K); |
| 854 | } |
| 855 | |