| //===--- AArch64.cpp - Implement AArch64 target feature support -----------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements AArch64 TargetInfo objects. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "AArch64.h" |
| #include "clang/Basic/TargetBuiltins.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringExtras.h" |
| |
| using namespace clang; |
| using namespace clang::targets; |
| |
| const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, |
| #include "clang/Basic/BuiltinsNEON.def" |
| |
| #define BUILTIN(ID, TYPE, ATTRS) \ |
| {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, |
| #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ |
| {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, |
| #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ |
| {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, |
| #include "clang/Basic/BuiltinsAArch64.def" |
| }; |
| |
| AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : TargetInfo(Triple), ABI("aapcs") { |
| if (getTriple().isOSOpenBSD()) { |
| Int64Type = SignedLongLong; |
| IntMaxType = SignedLongLong; |
| } else { |
| if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD()) |
| WCharType = UnsignedInt; |
| |
| Int64Type = SignedLong; |
| IntMaxType = SignedLong; |
| } |
| |
| // All AArch64 implementations support ARMv8 FP, which makes half a legal type. |
| HasLegalHalfType = true; |
| HasFloat16 = true; |
| |
| LongWidth = LongAlign = PointerWidth = PointerAlign = 64; |
| MaxVectorAlign = 128; |
| MaxAtomicInlineWidth = 128; |
| MaxAtomicPromoteWidth = 128; |
| |
| LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128; |
| LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
| |
| // Make __builtin_ms_va_list available. |
| HasBuiltinMSVaList = true; |
| |
| // Make the SVE types available. Note that this deliberately doesn't |
| // depend on SveMode, since in principle it should be possible to turn |
| // SVE on and off within a translation unit. It should also be possible |
| // to compile the global declaration: |
| // |
| // __SVInt8_t *ptr; |
| // |
| // even without SVE. |
| HasAArch64SVETypes = true; |
| |
| // {} in inline assembly are neon specifiers, not assembly variant |
| // specifiers. |
| NoAsmVariants = true; |
| |
| // AAPCS gives rules for bitfields. 7.1.7 says: "The container type |
| // contributes to the alignment of the containing aggregate in the same way |
| // a plain (non bit-field) member of that type would, without exception for |
| // zero-sized or anonymous bit-fields." |
| assert(UseBitFieldTypeAlignment && "bitfields affect type alignment"); |
| UseZeroLengthBitfieldAlignment = true; |
| |
| // AArch64 targets default to using the ARM C++ ABI. |
| TheCXXABI.set(TargetCXXABI::GenericAArch64); |
| |
| if (Triple.getOS() == llvm::Triple::Linux) |
| this->MCountName = "\01_mcount"; |
| else if (Triple.getOS() == llvm::Triple::UnknownOS) |
| this->MCountName = |
| Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount"; |
| } |
| |
| StringRef AArch64TargetInfo::getABI() const { return ABI; } |
| |
| bool AArch64TargetInfo::setABI(const std::string &Name) { |
| if (Name != "aapcs" && Name != "darwinpcs") |
| return false; |
| |
| ABI = Name; |
| return true; |
| } |
| |
| bool AArch64TargetInfo::isValidCPUName(StringRef Name) const { |
| return Name == "generic" || |
| llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID; |
| } |
| |
| bool AArch64TargetInfo::setCPU(const std::string &Name) { |
| return isValidCPUName(Name); |
| } |
| |
| void AArch64TargetInfo::fillValidCPUList( |
| SmallVectorImpl<StringRef> &Values) const { |
| llvm::AArch64::fillValidCPUArchList(Values); |
| } |
| |
| void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); |
| } |
| |
| void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| // Also include the ARMv8.1 defines |
| getTargetDefinesARMV81A(Opts, Builder); |
| } |
| |
| void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__ARM_FEATURE_JCVT", "1"); |
| // Also include the Armv8.2 defines |
| getTargetDefinesARMV82A(Opts, Builder); |
| } |
| |
| void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| // Also include the Armv8.3 defines |
| // FIXME: Armv8.4 makes some extensions mandatory. Handle them here. |
| getTargetDefinesARMV83A(Opts, Builder); |
| } |
| |
| void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| // Also include the Armv8.4 defines |
| // FIXME: Armv8.5 makes some extensions mandatory. Handle them here. |
| getTargetDefinesARMV84A(Opts, Builder); |
| } |
| |
| |
| void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| // Target identification. |
| Builder.defineMacro("__aarch64__"); |
| // For bare-metal. |
| if (getTriple().getOS() == llvm::Triple::UnknownOS && |
| getTriple().isOSBinFormatELF()) |
| Builder.defineMacro("__ELF__"); |
| |
| // Target properties. |
| if (!getTriple().isOSWindows()) { |
| Builder.defineMacro("_LP64"); |
| Builder.defineMacro("__LP64__"); |
| } |
| |
| // ACLE predefines. Many can only have one possible value on v8 AArch64. |
| Builder.defineMacro("__ARM_ACLE", "200"); |
| Builder.defineMacro("__ARM_ARCH", "8"); |
| Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); |
| |
| Builder.defineMacro("__ARM_64BIT_STATE", "1"); |
| Builder.defineMacro("__ARM_PCS_AAPCS64", "1"); |
| Builder.defineMacro("__ARM_ARCH_ISA_A64", "1"); |
| |
| Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); |
| Builder.defineMacro("__ARM_FEATURE_FMA", "1"); |
| Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF"); |
| Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE |
| Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility |
| Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); |
| Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); |
| |
| Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); |
| |
| // 0xe implies support for half, single and double precision operations. |
| Builder.defineMacro("__ARM_FP", "0xE"); |
| |
| // PCS specifies this for SysV variants, which is all we support. Other ABIs |
| // may choose __ARM_FP16_FORMAT_ALTERNATIVE. |
| Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); |
| Builder.defineMacro("__ARM_FP16_ARGS", "1"); |
| |
| if (Opts.UnsafeFPMath) |
| Builder.defineMacro("__ARM_FP_FAST", "1"); |
| |
| Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", |
| Twine(Opts.WCharSize ? Opts.WCharSize : 4)); |
| |
| Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4"); |
| |
| if (FPU & NeonMode) { |
| Builder.defineMacro("__ARM_NEON", "1"); |
| // 64-bit NEON supports half, single and double precision operations. |
| Builder.defineMacro("__ARM_NEON_FP", "0xE"); |
| } |
| |
| if (HasCRC) |
| Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); |
| |
| if (HasCrypto) |
| Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); |
| |
| if (HasUnaligned) |
| Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); |
| |
| if ((FPU & NeonMode) && HasFullFP16) |
| Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1"); |
| if (HasFullFP16) |
| Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1"); |
| |
| if (HasDotProd) |
| Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1"); |
| |
| if (HasMTE) |
| Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1"); |
| |
| if (HasTME) |
| Builder.defineMacro("__ARM_FEATURE_TME", "1"); |
| |
| if ((FPU & NeonMode) && HasFP16FML) |
| Builder.defineMacro("__ARM_FEATURE_FP16FML", "1"); |
| |
| switch (ArchKind) { |
| default: |
| break; |
| case llvm::AArch64::ArchKind::ARMV8_1A: |
| getTargetDefinesARMV81A(Opts, Builder); |
| break; |
| case llvm::AArch64::ArchKind::ARMV8_2A: |
| getTargetDefinesARMV82A(Opts, Builder); |
| break; |
| case llvm::AArch64::ArchKind::ARMV8_3A: |
| getTargetDefinesARMV83A(Opts, Builder); |
| break; |
| case llvm::AArch64::ArchKind::ARMV8_4A: |
| getTargetDefinesARMV84A(Opts, Builder); |
| break; |
| case llvm::AArch64::ArchKind::ARMV8_5A: |
| getTargetDefinesARMV85A(Opts, Builder); |
| break; |
| } |
| |
| // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
| Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
| } |
| |
| ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const { |
| return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - |
| Builtin::FirstTSBuiltin); |
| } |
| |
| bool AArch64TargetInfo::hasFeature(StringRef Feature) const { |
| return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || |
| (Feature == "neon" && (FPU & NeonMode)) || |
| (Feature == "sve" && (FPU & SveMode)); |
| } |
| |
| bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, |
| DiagnosticsEngine &Diags) { |
| FPU = FPUMode; |
| HasCRC = false; |
| HasCrypto = false; |
| HasUnaligned = true; |
| HasFullFP16 = false; |
| HasDotProd = false; |
| HasFP16FML = false; |
| HasMTE = false; |
| HasTME = false; |
| ArchKind = llvm::AArch64::ArchKind::ARMV8A; |
| |
| for (const auto &Feature : Features) { |
| if (Feature == "+neon") |
| FPU |= NeonMode; |
| if (Feature == "+sve") |
| FPU |= SveMode; |
| if (Feature == "+crc") |
| HasCRC = true; |
| if (Feature == "+crypto") |
| HasCrypto = true; |
| if (Feature == "+strict-align") |
| HasUnaligned = false; |
| if (Feature == "+v8.1a") |
| ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; |
| if (Feature == "+v8.2a") |
| ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; |
| if (Feature == "+v8.3a") |
| ArchKind = llvm::AArch64::ArchKind::ARMV8_3A; |
| if (Feature == "+v8.4a") |
| ArchKind = llvm::AArch64::ArchKind::ARMV8_4A; |
| if (Feature == "+v8.5a") |
| ArchKind = llvm::AArch64::ArchKind::ARMV8_5A; |
| if (Feature == "+fullfp16") |
| HasFullFP16 = true; |
| if (Feature == "+dotprod") |
| HasDotProd = true; |
| if (Feature == "+fp16fml") |
| HasFP16FML = true; |
| if (Feature == "+mte") |
| HasMTE = true; |
| if (Feature == "+tme") |
| HasTME = true; |
| } |
| |
| setDataLayout(); |
| |
| return true; |
| } |
| |
| TargetInfo::CallingConvCheckResult |
| AArch64TargetInfo::checkCallingConvention(CallingConv CC) const { |
| switch (CC) { |
| case CC_C: |
| case CC_Swift: |
| case CC_PreserveMost: |
| case CC_PreserveAll: |
| case CC_OpenCLKernel: |
| case CC_AArch64VectorCall: |
| case CC_Win64: |
| return CCCR_OK; |
| default: |
| return CCCR_Warning; |
| } |
| } |
| |
| bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; } |
| |
| TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const { |
| return TargetInfo::AArch64ABIBuiltinVaList; |
| } |
| |
| const char *const AArch64TargetInfo::GCCRegNames[] = { |
| // 32-bit Integer registers |
| "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11", |
| "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22", |
| "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp", |
| |
| // 64-bit Integer registers |
| "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", |
| "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", |
| "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp", |
| |
| // 32-bit floating point regsisters |
| "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", |
| "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", |
| "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", |
| |
| // 64-bit floating point regsisters |
| "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", |
| "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", |
| "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", |
| |
| // Neon vector registers |
| "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", |
| "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", |
| "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", |
| |
| // SVE vector registers |
| "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", |
| "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", |
| "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", |
| |
| // SVE predicate registers |
| "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", |
| "p11", "p12", "p13", "p14", "p15" |
| }; |
| |
| ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const { |
| return llvm::makeArrayRef(GCCRegNames); |
| } |
| |
| const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = { |
| {{"w31"}, "wsp"}, |
| {{"x31"}, "sp"}, |
| // GCC rN registers are aliases of xN registers. |
| {{"r0"}, "x0"}, |
| {{"r1"}, "x1"}, |
| {{"r2"}, "x2"}, |
| {{"r3"}, "x3"}, |
| {{"r4"}, "x4"}, |
| {{"r5"}, "x5"}, |
| {{"r6"}, "x6"}, |
| {{"r7"}, "x7"}, |
| {{"r8"}, "x8"}, |
| {{"r9"}, "x9"}, |
| {{"r10"}, "x10"}, |
| {{"r11"}, "x11"}, |
| {{"r12"}, "x12"}, |
| {{"r13"}, "x13"}, |
| {{"r14"}, "x14"}, |
| {{"r15"}, "x15"}, |
| {{"r16"}, "x16"}, |
| {{"r17"}, "x17"}, |
| {{"r18"}, "x18"}, |
| {{"r19"}, "x19"}, |
| {{"r20"}, "x20"}, |
| {{"r21"}, "x21"}, |
| {{"r22"}, "x22"}, |
| {{"r23"}, "x23"}, |
| {{"r24"}, "x24"}, |
| {{"r25"}, "x25"}, |
| {{"r26"}, "x26"}, |
| {{"r27"}, "x27"}, |
| {{"r28"}, "x28"}, |
| {{"r29", "x29"}, "fp"}, |
| {{"r30", "x30"}, "lr"}, |
| // The S/D/Q and W/X registers overlap, but aren't really aliases; we |
| // don't want to substitute one of these for a different-sized one. |
| }; |
| |
| ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const { |
| return llvm::makeArrayRef(GCCRegAliases); |
| } |
| |
| bool AArch64TargetInfo::validateAsmConstraint( |
| const char *&Name, TargetInfo::ConstraintInfo &Info) const { |
| switch (*Name) { |
| default: |
| return false; |
| case 'w': // Floating point and SIMD registers (V0-V31) |
| Info.setAllowsRegister(); |
| return true; |
| case 'I': // Constant that can be used with an ADD instruction |
| case 'J': // Constant that can be used with a SUB instruction |
| case 'K': // Constant that can be used with a 32-bit logical instruction |
| case 'L': // Constant that can be used with a 64-bit logical instruction |
| case 'M': // Constant that can be used as a 32-bit MOV immediate |
| case 'N': // Constant that can be used as a 64-bit MOV immediate |
| case 'Y': // Floating point constant zero |
| case 'Z': // Integer constant zero |
| return true; |
| case 'Q': // A memory reference with base register and no offset |
| Info.setAllowsMemory(); |
| return true; |
| case 'S': // A symbolic address |
| Info.setAllowsRegister(); |
| return true; |
| case 'U': |
| // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes. |
| // Utf: A memory address suitable for ldp/stp in TF mode. |
| // Usa: An absolute symbolic address. |
| // Ush: The high part (bits 32:12) of a pc-relative symbolic address. |
| llvm_unreachable("FIXME: Unimplemented support for U* constraints."); |
| case 'z': // Zero register, wzr or xzr |
| Info.setAllowsRegister(); |
| return true; |
| case 'x': // Floating point and SIMD registers (V0-V15) |
| Info.setAllowsRegister(); |
| return true; |
| } |
| return false; |
| } |
| |
| bool AArch64TargetInfo::validateConstraintModifier( |
| StringRef Constraint, char Modifier, unsigned Size, |
| std::string &SuggestedModifier) const { |
| // Strip off constraint modifiers. |
| while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') |
| Constraint = Constraint.substr(1); |
| |
| switch (Constraint[0]) { |
| default: |
| return true; |
| case 'z': |
| case 'r': { |
| switch (Modifier) { |
| case 'x': |
| case 'w': |
| // For now assume that the person knows what they're |
| // doing with the modifier. |
| return true; |
| default: |
| // By default an 'r' constraint will be in the 'x' |
| // registers. |
| if (Size == 64) |
| return true; |
| |
| SuggestedModifier = "w"; |
| return false; |
| } |
| } |
| } |
| } |
| |
| const char *AArch64TargetInfo::getClobbers() const { return ""; } |
| |
| int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { |
| if (RegNo == 0) |
| return 0; |
| if (RegNo == 1) |
| return 1; |
| return -1; |
| } |
| |
| AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : AArch64TargetInfo(Triple, Opts) {} |
| |
| void AArch64leTargetInfo::setDataLayout() { |
| if (getTriple().isOSBinFormatMachO()) |
| resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128"); |
| else |
| resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); |
| } |
| |
| void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__AARCH64EL__"); |
| AArch64TargetInfo::getTargetDefines(Opts, Builder); |
| } |
| |
| AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : AArch64TargetInfo(Triple, Opts) {} |
| |
| void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__AARCH64EB__"); |
| Builder.defineMacro("__AARCH_BIG_ENDIAN"); |
| Builder.defineMacro("__ARM_BIG_ENDIAN"); |
| AArch64TargetInfo::getTargetDefines(Opts, Builder); |
| } |
| |
| void AArch64beTargetInfo::setDataLayout() { |
| assert(!getTriple().isOSBinFormatMachO()); |
| resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); |
| } |
| |
| WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) { |
| |
| // This is an LLP64 platform. |
| // int:4, long:4, long long:8, long double:8. |
| IntWidth = IntAlign = 32; |
| LongWidth = LongAlign = 32; |
| DoubleAlign = LongLongAlign = 64; |
| LongDoubleWidth = LongDoubleAlign = 64; |
| LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
| IntMaxType = SignedLongLong; |
| Int64Type = SignedLongLong; |
| SizeType = UnsignedLongLong; |
| PtrDiffType = SignedLongLong; |
| IntPtrType = SignedLongLong; |
| } |
| |
| void WindowsARM64TargetInfo::setDataLayout() { |
| resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); |
| } |
| |
| TargetInfo::BuiltinVaListKind |
| WindowsARM64TargetInfo::getBuiltinVaListKind() const { |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| |
| TargetInfo::CallingConvCheckResult |
| WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const { |
| switch (CC) { |
| case CC_X86StdCall: |
| case CC_X86ThisCall: |
| case CC_X86FastCall: |
| case CC_X86VectorCall: |
| return CCCR_Ignore; |
| case CC_C: |
| case CC_OpenCLKernel: |
| case CC_PreserveMost: |
| case CC_PreserveAll: |
| case CC_Swift: |
| case CC_Win64: |
| return CCCR_OK; |
| default: |
| return CCCR_Warning; |
| } |
| } |
| |
| MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : WindowsARM64TargetInfo(Triple, Opts) { |
| TheCXXABI.set(TargetCXXABI::Microsoft); |
| } |
| |
| void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| WindowsARM64TargetInfo::getTargetDefines(Opts, Builder); |
| Builder.defineMacro("_M_ARM64", "1"); |
| } |
| |
| TargetInfo::CallingConvKind |
| MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { |
| return CCK_MicrosoftWin64; |
| } |
| |
| unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { |
| unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); |
| |
| // MSVC does size based alignment for arm64 based on alignment section in |
| // below document, replicate that to keep alignment consistent with object |
| // files compiled by MSVC. |
| // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions |
| if (TypeSize >= 512) { // TypeSize >= 64 bytes |
| Align = std::max(Align, 128u); // align type at least 16 bytes |
| } else if (TypeSize >= 64) { // TypeSize >= 8 bytes |
| Align = std::max(Align, 64u); // align type at least 8 butes |
| } else if (TypeSize >= 16) { // TypeSize >= 2 bytes |
| Align = std::max(Align, 32u); // align type at least 4 bytes |
| } |
| return Align; |
| } |
| |
| MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : WindowsARM64TargetInfo(Triple, Opts) { |
| TheCXXABI.set(TargetCXXABI::GenericAArch64); |
| } |
| |
| DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) { |
| Int64Type = SignedLongLong; |
| UseSignedCharForObjCBool = false; |
| |
| LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; |
| LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
| |
| TheCXXABI.set(TargetCXXABI::iOS64); |
| } |
| |
| void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts, |
| const llvm::Triple &Triple, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__AARCH64_SIMD__"); |
| Builder.defineMacro("__ARM64_ARCH_8__"); |
| Builder.defineMacro("__ARM_NEON__"); |
| Builder.defineMacro("__LITTLE_ENDIAN__"); |
| Builder.defineMacro("__REGISTER_PREFIX__", ""); |
| Builder.defineMacro("__arm64", "1"); |
| Builder.defineMacro("__arm64__", "1"); |
| |
| getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); |
| } |
| |
| TargetInfo::BuiltinVaListKind |
| DarwinAArch64TargetInfo::getBuiltinVaListKind() const { |
| return TargetInfo::CharPtrBuiltinVaList; |
| } |
| |
| // 64-bit RenderScript is aarch64 |
| RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple, |
| const TargetOptions &Opts) |
| : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), |
| Triple.getOSName(), |
| Triple.getEnvironmentName()), |
| Opts) { |
| IsRenderScriptTarget = true; |
| } |
| |
| void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts, |
| MacroBuilder &Builder) const { |
| Builder.defineMacro("__RENDERSCRIPT__"); |
| AArch64leTargetInfo::getTargetDefines(Opts, Builder); |
| } |