From 115ab5283cd14e15de06e5cfd976e4c6f2f7c236 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 24 Jul 2017 17:06:23 +0000 Subject: [PATCH] AArch64 & ARM: move TargetInfo functions from .h to .cpp file. NFC. Most of them are virtual anyway, and the few remaining ones can move to the .cpp for consistency. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@308898 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Basic/Targets/AArch64.cpp | 451 ++++++++++++++++- lib/Basic/Targets/AArch64.h | 447 ++--------------- lib/Basic/Targets/ARM.cpp | 889 ++++++++++++++++++++++++++++------ lib/Basic/Targets/ARM.h | 607 ++--------------------- 4 files changed, 1294 insertions(+), 1100 deletions(-) diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp index 3582ec5777..b65a44928f 100644 --- a/lib/Basic/Targets/AArch64.cpp +++ b/lib/Basic/Targets/AArch64.cpp @@ -19,6 +19,245 @@ 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}, +#include "clang/Basic/BuiltinsAArch64.def" +}; + +AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : TargetInfo(Triple), ABI("aapcs") { + if (getTriple().getOS() == llvm::Triple::NetBSD || + getTriple().getOS() == llvm::Triple::OpenBSD) { + WCharType = SignedInt; + + // NetBSD apparently prefers consistency across ARM targets to + // consistency across 64-bit targets. + Int64Type = SignedLongLong; + IntMaxType = SignedLongLong; + } else { + WCharType = UnsignedInt; + Int64Type = SignedLong; + IntMaxType = SignedLong; + } + + 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; + + // {} 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) != + static_cast(llvm::AArch64::ArchKind::AK_INVALID); +} + +bool AArch64TargetInfo::setCPU(const std::string &Name) { + return isValidCPUName(Name); +} + +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::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Target identification. + Builder.defineMacro("__aarch64__"); + // For bare-metal none-eabi. + if (getTriple().getOS() == llvm::Triple::UnknownOS && + (getTriple().getEnvironment() == llvm::Triple::EABI || + getTriple().getEnvironment() == llvm::Triple::EABIHF)) + Builder.defineMacro("__ELF__"); + + // Target properties. + 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", Opts.ShortWChar ? "2" : "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 (FPU & SveMode) + Builder.defineMacro("__ARM_FEATURE_SVE", "1"); + + if (CRC) + Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); + + if (Crypto) + Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); + + if (Unaligned) + Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); + + switch (ArchKind) { + default: + break; + case llvm::AArch64::ArchKind::AK_ARMV8_1A: + getTargetDefinesARMV81A(Opts, Builder); + break; + case llvm::AArch64::ArchKind::AK_ARMV8_2A: + getTargetDefinesARMV82A(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 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 &Features, + DiagnosticsEngine &Diags) { + FPU = FPUMode; + CRC = 0; + Crypto = 0; + Unaligned = 1; + HasFullFP16 = 0; + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A; + + for (const auto &Feature : Features) { + if (Feature == "+neon") + FPU |= NeonMode; + if (Feature == "+sve") + FPU |= SveMode; + if (Feature == "+crc") + CRC = 1; + if (Feature == "+crypto") + Crypto = 1; + if (Feature == "+strict-align") + Unaligned = 0; + if (Feature == "+v8.1a") + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A; + if (Feature == "+v8.2a") + ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A; + if (Feature == "+fullfp16") + HasFullFP16 = 1; + } + + 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_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", @@ -60,12 +299,208 @@ ArrayRef AArch64TargetInfo::getGCCRegAliases() const { return llvm::makeArrayRef(GCCRegAliases); } -const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, -#include "clang/Basic/BuiltinsNEON.def" +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; +} -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, -#include "clang/Basic/BuiltinsAArch64.def" -}; +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"); +} + +MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsTargetInfo(Triple, Opts), Triple(Triple) { + + // This is an LLP64 platform. + // int:4, long:4, long long:8, long double:8. + WCharType = UnsignedShort; + 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; + + TheCXXABI.set(TargetCXXABI::Microsoft); +} + +void MicrosoftARM64TargetInfo::setDataLayout() { + resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); +} + +void MicrosoftARM64TargetInfo::getVisualStudioDefines( + const LangOptions &Opts, MacroBuilder &Builder) const { + WindowsTargetInfo::getVisualStudioDefines(Opts, Builder); + Builder.defineMacro("_WIN32", "1"); + Builder.defineMacro("_WIN64", "1"); + Builder.defineMacro("_M_ARM64", "1"); +} + +void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + WindowsTargetInfo::getTargetDefines(Opts, Builder); + getVisualStudioDefines(Opts, Builder); +} + +TargetInfo::BuiltinVaListKind +MicrosoftARM64TargetInfo::getBuiltinVaListKind() const { + return TargetInfo::CharPtrBuiltinVaList; +} + +DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : DarwinTargetInfo(Triple, Opts) { + Int64Type = SignedLongLong; + WCharType = SignedInt; + 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); +} diff --git a/lib/Basic/Targets/AArch64.h b/lib/Basic/Targets/AArch64.h index 16e85d3cb6..237586850c 100644 --- a/lib/Basic/Targets/AArch64.h +++ b/lib/Basic/Targets/AArch64.h @@ -40,331 +40,53 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { std::string ABI; public: - AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : TargetInfo(Triple), ABI("aapcs") { - if (getTriple().getOS() == llvm::Triple::NetBSD || - getTriple().getOS() == llvm::Triple::OpenBSD) { - WCharType = SignedInt; - - // NetBSD apparently prefers consistency across ARM targets to consistency - // across 64-bit targets. - Int64Type = SignedLongLong; - IntMaxType = SignedLongLong; - } else { - WCharType = UnsignedInt; - Int64Type = SignedLong; - IntMaxType = SignedLong; - } - - 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; - - // {} 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 getABI() const override { return ABI; } - bool setABI(const std::string &Name) override { - if (Name != "aapcs" && Name != "darwinpcs") - return false; - - ABI = Name; - return true; - } - - bool isValidCPUName(StringRef Name) const override { - return Name == "generic" || - llvm::AArch64::parseCPUArch(Name) != - static_cast(llvm::AArch64::ArchKind::AK_INVALID); - } - - bool setCPU(const std::string &Name) override { return isValidCPUName(Name); } + AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); - void getTargetDefinesARMV81A(const LangOptions &Opts, - MacroBuilder &Builder) const { - Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); - } + StringRef getABI() const override; + bool setABI(const std::string &Name) override; - void getTargetDefinesARMV82A(const LangOptions &Opts, - MacroBuilder &Builder) const { - // Also include the ARMv8.1 defines - getTargetDefinesARMV81A(Opts, Builder); - } + bool isValidCPUName(StringRef Name) const override; + bool setCPU(const std::string &Name) override; + void getTargetDefinesARMV81A(const LangOptions &Opts, + MacroBuilder &Builder) const; + void getTargetDefinesARMV82A(const LangOptions &Opts, + MacroBuilder &Builder) const; void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - // Target identification. - Builder.defineMacro("__aarch64__"); - // For bare-metal none-eabi. - if (getTriple().getOS() == llvm::Triple::UnknownOS && - (getTriple().getEnvironment() == llvm::Triple::EABI || - getTriple().getEnvironment() == llvm::Triple::EABIHF)) - Builder.defineMacro("__ELF__"); - - // Target properties. - 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", Opts.ShortWChar ? "2" : "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 (FPU & SveMode) - Builder.defineMacro("__ARM_FEATURE_SVE", "1"); - - if (CRC) - Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); - - if (Crypto) - Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); - - if (Unaligned) - Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); - - switch (ArchKind) { - default: - break; - case llvm::AArch64::ArchKind::AK_ARMV8_1A: - getTargetDefinesARMV81A(Opts, Builder); - break; - case llvm::AArch64::ArchKind::AK_ARMV8_2A: - getTargetDefinesARMV82A(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 getTargetBuiltins() const override { - return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin - - Builtin::FirstTSBuiltin); - } - - bool hasFeature(StringRef Feature) const override { - return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" || - (Feature == "neon" && (FPU & NeonMode)) || - (Feature == "sve" && (FPU & SveMode)); - } + MacroBuilder &Builder) const override; + + ArrayRef getTargetBuiltins() const override; + bool hasFeature(StringRef Feature) const override; bool handleTargetFeatures(std::vector &Features, - DiagnosticsEngine &Diags) override { - FPU = FPUMode; - CRC = 0; - Crypto = 0; - Unaligned = 1; - HasFullFP16 = 0; - ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A; - - for (const auto &Feature : Features) { - if (Feature == "+neon") - FPU |= NeonMode; - if (Feature == "+sve") - FPU |= SveMode; - if (Feature == "+crc") - CRC = 1; - if (Feature == "+crypto") - Crypto = 1; - if (Feature == "+strict-align") - Unaligned = 0; - if (Feature == "+v8.1a") - ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A; - if (Feature == "+v8.2a") - ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A; - if (Feature == "+fullfp16") - HasFullFP16 = 1; - } - - setDataLayout(); - - return true; - } - - CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - switch (CC) { - case CC_C: - case CC_Swift: - case CC_PreserveMost: - case CC_PreserveAll: - case CC_OpenCLKernel: - case CC_Win64: - return CCCR_OK; - default: - return CCCR_Warning; - } - } - - bool isCLZForZeroUndef() const override { return false; } - - BuiltinVaListKind getBuiltinVaListKind() const override { - return TargetInfo::AArch64ABIBuiltinVaList; - } + DiagnosticsEngine &Diags) override; + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; + + bool isCLZForZeroUndef() const override; + + BuiltinVaListKind getBuiltinVaListKind() const override; ArrayRef getGCCRegNames() const override; ArrayRef getGCCRegAliases() const override; - bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const override { - 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; - } - + TargetInfo::ConstraintInfo &Info) const override; bool validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size, - std::string &SuggestedModifier) const override { - // 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 *getClobbers() const override { return ""; } - - int getEHDataRegisterNumber(unsigned RegNo) const override { - if (RegNo == 0) - return 0; - if (RegNo == 1) - return 1; - return -1; - } + std::string &SuggestedModifier) const override; + const char *getClobbers() const override; + + int getEHDataRegisterNumber(unsigned RegNo) const override; }; class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo { - void setDataLayout() override { - 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"); - } - public: - AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : AArch64TargetInfo(Triple, Opts) {} + AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); + void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - Builder.defineMacro("__AARCH64EL__"); - AArch64TargetInfo::getTargetDefines(Opts, Builder); - } + MacroBuilder &Builder) const override; +private: + void setDataLayout() override; }; class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo @@ -373,100 +95,38 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo public: MicrosoftARM64TargetInfo(const llvm::Triple &Triple, - const TargetOptions &Opts) - : WindowsTargetInfo(Triple, Opts), Triple(Triple) { - - // This is an LLP64 platform. - // int:4, long:4, long long:8, long double:8. - WCharType = UnsignedShort; - 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; - - TheCXXABI.set(TargetCXXABI::Microsoft); - } - - void setDataLayout() override { - resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"); - } + const TargetOptions &Opts); - void getVisualStudioDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - WindowsTargetInfo::getVisualStudioDefines(Opts, - Builder); - Builder.defineMacro("_WIN32", "1"); - Builder.defineMacro("_WIN64", "1"); - Builder.defineMacro("_M_ARM64", "1"); - } + void setDataLayout() override; + void getVisualStudioDefines(const LangOptions &Opts, + MacroBuilder &Builder) const; void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - WindowsTargetInfo::getTargetDefines(Opts, Builder); - getVisualStudioDefines(Opts, Builder); - } - - BuiltinVaListKind getBuiltinVaListKind() const override { - return TargetInfo::CharPtrBuiltinVaList; - } + MacroBuilder &Builder) const override; + + BuiltinVaListKind getBuiltinVaListKind() const override; }; class LLVM_LIBRARY_VISIBILITY AArch64beTargetInfo : public AArch64TargetInfo { - void setDataLayout() override { - assert(!getTriple().isOSBinFormatMachO()); - resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"); - } - public: - AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : AArch64TargetInfo(Triple, Opts) {} + AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - Builder.defineMacro("__AARCH64EB__"); - Builder.defineMacro("__AARCH_BIG_ENDIAN"); - Builder.defineMacro("__ARM_BIG_ENDIAN"); - AArch64TargetInfo::getTargetDefines(Opts, Builder); - } + MacroBuilder &Builder) const override; + +private: + void setDataLayout() override; }; class LLVM_LIBRARY_VISIBILITY DarwinAArch64TargetInfo : public DarwinTargetInfo { -protected: - void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const override { - 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); - } - public: - DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : DarwinTargetInfo(Triple, Opts) { - Int64Type = SignedLongLong; - WCharType = SignedInt; - UseSignedCharForObjCBool = false; + DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); - LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64; - LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + BuiltinVaListKind getBuiltinVaListKind() const override; - TheCXXABI.set(TargetCXXABI::iOS64); - } - - BuiltinVaListKind getBuiltinVaListKind() const override { - return TargetInfo::CharPtrBuiltinVaList; - } + protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override; }; // 64-bit RenderScript is aarch64 @@ -474,19 +134,10 @@ class LLVM_LIBRARY_VISIBILITY RenderScript64TargetInfo : public AArch64leTargetInfo { public: RenderScript64TargetInfo(const llvm::Triple &Triple, - const TargetOptions &Opts) - : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(), - Triple.getOSName(), - Triple.getEnvironmentName()), - Opts) { - IsRenderScriptTarget = true; - } + const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - Builder.defineMacro("__RENDERSCRIPT__"); - AArch64leTargetInfo::getTargetDefines(Opts, Builder); - } + MacroBuilder &Builder) const override; }; } // namespace targets diff --git a/lib/Basic/Targets/ARM.cpp b/lib/Basic/Targets/ARM.cpp index ede1eead65..2f828b7f1d 100644 --- a/lib/Basic/Targets/ARM.cpp +++ b/lib/Basic/Targets/ARM.cpp @@ -22,72 +22,455 @@ using namespace clang; using namespace clang::targets; -bool ARMTargetInfo::setFPMath(StringRef Name) { - if (Name == "neon") { - FPMath = FP_Neon; +void ARMTargetInfo::setABIAAPCS() { + IsAAPCS = true; + + DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; + const llvm::Triple &T = getTriple(); + + // size_t is unsigned long on MachO-derived environments, NetBSD, and + // OpenBSD. + if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD || + T.getOS() == llvm::Triple::OpenBSD) + SizeType = UnsignedLong; + else + SizeType = UnsignedInt; + + switch (T.getOS()) { + case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: + WCharType = SignedInt; + break; + case llvm::Triple::Win32: + WCharType = UnsignedShort; + break; + case llvm::Triple::Linux: + default: + // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. + WCharType = UnsignedInt; + break; + } + + UseBitFieldTypeAlignment = true; + + ZeroLengthBitfieldBoundary = 0; + + // Thumb1 add sp, #imm requires the immediate value be multiple of 4, + // so set preferred for small types to 32. + if (T.isOSBinFormatMachO()) { + resetDataLayout(BigEndian + ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); + } else if (T.isOSWindows()) { + assert(!BigEndian && "Windows on ARM does not support big endian"); + resetDataLayout("e" + "-m:w" + "-p:32:32" + "-i64:64" + "-v128:64:128" + "-a:0:32" + "-n32" + "-S64"); + } else if (T.isOSNaCl()) { + assert(!BigEndian && "NaCl on ARM does not support big endian"); + resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"); + } else { + resetDataLayout(BigEndian + ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" + : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); + } + + // FIXME: Enumerated types are variable width in straight AAPCS. +} + +void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) { + const llvm::Triple &T = getTriple(); + + IsAAPCS = false; + + if (IsAAPCS16) + DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; + else + DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; + + // size_t is unsigned int on FreeBSD. + if (T.getOS() == llvm::Triple::FreeBSD) + SizeType = UnsignedInt; + else + SizeType = UnsignedLong; + + // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. + WCharType = SignedInt; + + // Do not respect the alignment of bit-field types when laying out + // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. + UseBitFieldTypeAlignment = false; + + /// gcc forces the alignment to 4 bytes, regardless of the type of the + /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in + /// gcc. + ZeroLengthBitfieldBoundary = 32; + + if (T.isOSBinFormatMachO() && IsAAPCS16) { + assert(!BigEndian && "AAPCS16 does not support big-endian"); + resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128"); + } else if (T.isOSBinFormatMachO()) + resetDataLayout( + BigEndian + ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); + else + resetDataLayout( + BigEndian + ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); + + // FIXME: Override "preferred align" for double and long long. +} + +void ARMTargetInfo::setArchInfo() { + StringRef ArchName = getTriple().getArchName(); + + ArchISA = llvm::ARM::parseArchISA(ArchName); + CPU = llvm::ARM::getDefaultCPU(ArchName); + unsigned AK = llvm::ARM::parseArch(ArchName); + if (AK != llvm::ARM::AK_INVALID) + ArchKind = AK; + setArchInfo(ArchKind); +} + +void ARMTargetInfo::setArchInfo(unsigned Kind) { + StringRef SubArch; + + // cache TargetParser info + ArchKind = Kind; + SubArch = llvm::ARM::getSubArch(ArchKind); + ArchProfile = llvm::ARM::parseArchProfile(SubArch); + ArchVersion = llvm::ARM::parseArchVersion(SubArch); + + // cache CPU related strings + CPUAttr = getCPUAttr(); + CPUProfile = getCPUProfile(); +} + +void ARMTargetInfo::setAtomic() { + // when triple does not specify a sub arch, + // then we are not using inline atomics + bool ShouldUseInlineAtomic = + (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) || + (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7); + // Cortex M does not support 8 byte atomics, while general Thumb2 does. + if (ArchProfile == llvm::ARM::PK_M) { + MaxAtomicPromoteWidth = 32; + if (ShouldUseInlineAtomic) + MaxAtomicInlineWidth = 32; + } else { + MaxAtomicPromoteWidth = 64; + if (ShouldUseInlineAtomic) + MaxAtomicInlineWidth = 64; + } +} + +bool ARMTargetInfo::isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); } + +bool ARMTargetInfo::supportsThumb() const { + return CPUAttr.count('T') || ArchVersion >= 6; +} + +bool ARMTargetInfo::supportsThumb2() const { + return CPUAttr.equals("6T2") || + (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE")); +} + +StringRef ARMTargetInfo::getCPUAttr() const { + // For most sub-arches, the build attribute CPU name is enough. + // For Cortex variants, it's slightly different. + switch (ArchKind) { + default: + return llvm::ARM::getCPUAttr(ArchKind); + case llvm::ARM::AK_ARMV6M: + return "6M"; + case llvm::ARM::AK_ARMV7S: + return "7S"; + case llvm::ARM::AK_ARMV7A: + return "7A"; + case llvm::ARM::AK_ARMV7R: + return "7R"; + case llvm::ARM::AK_ARMV7M: + return "7M"; + case llvm::ARM::AK_ARMV7EM: + return "7EM"; + case llvm::ARM::AK_ARMV7VE: + return "7VE"; + case llvm::ARM::AK_ARMV8A: + return "8A"; + case llvm::ARM::AK_ARMV8_1A: + return "8_1A"; + case llvm::ARM::AK_ARMV8_2A: + return "8_2A"; + case llvm::ARM::AK_ARMV8MBaseline: + return "8M_BASE"; + case llvm::ARM::AK_ARMV8MMainline: + return "8M_MAIN"; + case llvm::ARM::AK_ARMV8R: + return "8R"; + } +} + +StringRef ARMTargetInfo::getCPUProfile() const { + switch (ArchProfile) { + case llvm::ARM::PK_A: + return "A"; + case llvm::ARM::PK_R: + return "R"; + case llvm::ARM::PK_M: + return "M"; + default: + return ""; + } +} + +ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), + HW_FP(0) { + + switch (getTriple().getOS()) { + case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: + PtrDiffType = SignedLong; + break; + default: + PtrDiffType = SignedInt; + break; + } + + // Cache arch related info. + setArchInfo(); + + // {} in inline assembly are neon specifiers, not assembly variant + // specifiers. + NoAsmVariants = true; + + // FIXME: This duplicates code from the driver that sets the -target-abi + // option - this code is used if -target-abi isn't passed and should + // be unified in some way. + if (Triple.isOSBinFormatMachO()) { + // The backend is hardwired to assume AAPCS for M-class processors, ensure + // the frontend matches that. + if (Triple.getEnvironment() == llvm::Triple::EABI || + Triple.getOS() == llvm::Triple::UnknownOS || + ArchProfile == llvm::ARM::PK_M) { + setABI("aapcs"); + } else if (Triple.isWatchABI()) { + setABI("aapcs16"); + } else { + setABI("apcs-gnu"); + } + } else if (Triple.isOSWindows()) { + // FIXME: this is invalid for WindowsCE + setABI("aapcs"); + } else { + // Select the default based on the platform. + switch (Triple.getEnvironment()) { + case llvm::Triple::Android: + case llvm::Triple::GNUEABI: + case llvm::Triple::GNUEABIHF: + case llvm::Triple::MuslEABI: + case llvm::Triple::MuslEABIHF: + setABI("aapcs-linux"); + break; + case llvm::Triple::EABIHF: + case llvm::Triple::EABI: + setABI("aapcs"); + break; + case llvm::Triple::GNU: + setABI("apcs-gnu"); + break; + default: + if (Triple.getOS() == llvm::Triple::NetBSD) + setABI("apcs-gnu"); + else if (Triple.getOS() == llvm::Triple::OpenBSD) + setABI("aapcs-linux"); + else + setABI("aapcs"); + break; + } + } + + // ARM targets default to using the ARM C++ ABI. + TheCXXABI.set(TargetCXXABI::GenericARM); + + // ARM has atomics up to 8 bytes + setAtomic(); + + // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) + if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) + MaxVectorAlign = 64; + + // Do force alignment of members that follow zero length bitfields. If + // the alignment of the zero-length bitfield is greater than the member + // that follows it, `bar', `bar' will be aligned as the type of the + // zero length bitfield. + UseZeroLengthBitfieldAlignment = true; + + if (Triple.getOS() == llvm::Triple::Linux || + Triple.getOS() == llvm::Triple::UnknownOS) + this->MCountName = Opts.EABIVersion == llvm::EABI::GNU + ? "\01__gnu_mcount_nc" + : "\01mcount"; +} + +StringRef ARMTargetInfo::getABI() const { return ABI; } + +bool ARMTargetInfo::setABI(const std::string &Name) { + ABI = Name; + + // The defaults (above) are for AAPCS, check if we need to change them. + // + // FIXME: We need support for -meabi... we could just mangle it into the + // name. + if (Name == "apcs-gnu" || Name == "aapcs16") { + setABIAPCS(Name == "aapcs16"); return true; - } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || - Name == "vfp4") { - FPMath = FP_VFP; + } + if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") { + setABIAAPCS(); return true; } return false; } -const char *const ARMTargetInfo::GCCRegNames[] = { - // Integer registers - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", - "r12", "sp", "lr", "pc", +// FIXME: This should be based on Arch attributes, not CPU names. +bool ARMTargetInfo::initFeatureMap( + llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, + const std::vector &FeaturesVec) const { + + std::vector TargetFeatures; + unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName()); + + // get default FPU features + unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch); + llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures); + + // get default Extension features + unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch); + llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures); + + for (auto Feature : TargetFeatures) + if (Feature[0] == '+') + Features[Feature.drop_front(1)] = true; + + // Enable or disable thumb-mode explicitly per function to enable mixed + // ARM and Thumb code generation. + if (isThumb()) + Features["thumb-mode"] = true; + else + Features["thumb-mode"] = false; + + // Convert user-provided arm and thumb GNU target attributes to + // [-|+]thumb-mode target features respectively. + std::vector UpdatedFeaturesVec(FeaturesVec); + for (auto &Feature : UpdatedFeaturesVec) { + if (Feature.compare("+arm") == 0) + Feature = "-thumb-mode"; + else if (Feature.compare("+thumb") == 0) + Feature = "+thumb-mode"; + } - // Float registers - "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", + return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); +} - // Double registers - "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", - // Quad registers - "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", - "q12", "q13", "q14", "q15" -}; +bool ARMTargetInfo::handleTargetFeatures(std::vector &Features, + DiagnosticsEngine &Diags) { + FPU = 0; + CRC = 0; + Crypto = 0; + DSP = 0; + Unaligned = 1; + SoftFloat = SoftFloatABI = false; + HWDiv = 0; -ArrayRef ARMTargetInfo::getGCCRegNames() const { - return llvm::makeArrayRef(GCCRegNames); -} + // This does not diagnose illegal cases like having both + // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". + uint32_t HW_FP_remove = 0; + for (const auto &Feature : Features) { + if (Feature == "+soft-float") { + SoftFloat = true; + } else if (Feature == "+soft-float-abi") { + SoftFloatABI = true; + } else if (Feature == "+vfp2") { + FPU |= VFP2FPU; + HW_FP |= HW_FP_SP | HW_FP_DP; + } else if (Feature == "+vfp3") { + FPU |= VFP3FPU; + HW_FP |= HW_FP_SP | HW_FP_DP; + } else if (Feature == "+vfp4") { + FPU |= VFP4FPU; + HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; + } else if (Feature == "+fp-armv8") { + FPU |= FPARMV8; + HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; + } else if (Feature == "+neon") { + FPU |= NeonFPU; + HW_FP |= HW_FP_SP | HW_FP_DP; + } else if (Feature == "+hwdiv") { + HWDiv |= HWDivThumb; + } else if (Feature == "+hwdiv-arm") { + HWDiv |= HWDivARM; + } else if (Feature == "+crc") { + CRC = 1; + } else if (Feature == "+crypto") { + Crypto = 1; + } else if (Feature == "+dsp") { + DSP = 1; + } else if (Feature == "+fp-only-sp") { + HW_FP_remove |= HW_FP_DP; + } else if (Feature == "+strict-align") { + Unaligned = 0; + } else if (Feature == "+fp16") { + HW_FP |= HW_FP_HP; + } + } + HW_FP &= ~HW_FP_remove; -const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { - {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, - {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, - {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, - {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, - // The S, D and Q registers overlap, but aren't really aliases; we - // don't want to substitute one of these for a different-sized one. -}; + switch (ArchVersion) { + case 6: + if (ArchProfile == llvm::ARM::PK_M) + LDREX = 0; + else if (ArchKind == llvm::ARM::AK_ARMV6K) + LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; + else + LDREX = LDREX_W; + break; + case 7: + if (ArchProfile == llvm::ARM::PK_M) + LDREX = LDREX_W | LDREX_H | LDREX_B; + else + LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; + break; + case 8: + LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; + } -ArrayRef ARMTargetInfo::getGCCRegAliases() const { - return llvm::makeArrayRef(GCCRegAliases); -} + if (!(FPU & NeonFPU) && FPMath == FP_Neon) { + Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; + return false; + } -const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { -#define BUILTIN(ID, TYPE, ATTRS) \ - {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, -#include "clang/Basic/BuiltinsNEON.def" + if (FPMath == FP_Neon) + Features.push_back("+neonfp"); + else if (FPMath == FP_VFP) + Features.push_back("-neonfp"); -#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 LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, -#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ - {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, -#include "clang/Basic/BuiltinsARM.def" -}; + // Remove front-end specific options which the backend handles differently. + auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi"); + if (Feature != Features.end()) + Features.erase(Feature); + + return true; +} bool ARMTargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch(Feature) @@ -102,6 +485,45 @@ bool ARMTargetInfo::hasFeature(StringRef Feature) const { .Default(false); } +bool ARMTargetInfo::isValidCPUName(StringRef Name) const { + return Name == "generic" || + llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID; +} + +bool ARMTargetInfo::setCPU(const std::string &Name) { + if (Name != "generic") + setArchInfo(llvm::ARM::parseCPUArch(Name)); + + if (ArchKind == llvm::ARM::AK_INVALID) + return false; + setAtomic(); + CPU = Name; + return true; +} + +bool ARMTargetInfo::setFPMath(StringRef Name) { + if (Name == "neon") { + FPMath = FP_Neon; + return true; + } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || + Name == "vfp4") { + FPMath = FP_VFP; + return true; + } + return false; +} + +void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); +} + +void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the ARMv8.1-A defines + getTargetDefinesARMV81A(Opts, Builder); +} + void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. @@ -307,107 +729,197 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, } } -bool ARMTargetInfo::handleTargetFeatures(std::vector &Features, - DiagnosticsEngine &Diags) { - FPU = 0; - CRC = 0; - Crypto = 0; - DSP = 0; - Unaligned = 1; - SoftFloat = SoftFloatABI = false; - HWDiv = 0; +const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ + {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, +#include "clang/Basic/BuiltinsNEON.def" - // This does not diagnose illegal cases like having both - // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". - uint32_t HW_FP_remove = 0; - for (const auto &Feature : Features) { - if (Feature == "+soft-float") { - SoftFloat = true; - } else if (Feature == "+soft-float-abi") { - SoftFloatABI = true; - } else if (Feature == "+vfp2") { - FPU |= VFP2FPU; - HW_FP |= HW_FP_SP | HW_FP_DP; - } else if (Feature == "+vfp3") { - FPU |= VFP3FPU; - HW_FP |= HW_FP_SP | HW_FP_DP; - } else if (Feature == "+vfp4") { - FPU |= VFP4FPU; - HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; - } else if (Feature == "+fp-armv8") { - FPU |= FPARMV8; - HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; - } else if (Feature == "+neon") { - FPU |= NeonFPU; - HW_FP |= HW_FP_SP | HW_FP_DP; - } else if (Feature == "+hwdiv") { - HWDiv |= HWDivThumb; - } else if (Feature == "+hwdiv-arm") { - HWDiv |= HWDivARM; - } else if (Feature == "+crc") { - CRC = 1; - } else if (Feature == "+crypto") { - Crypto = 1; - } else if (Feature == "+dsp") { - DSP = 1; - } else if (Feature == "+fp-only-sp") { - HW_FP_remove |= HW_FP_DP; - } else if (Feature == "+strict-align") { - Unaligned = 0; - } else if (Feature == "+fp16") { - HW_FP |= HW_FP_HP; +#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 LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ + {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, +#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ + {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, +#include "clang/Basic/BuiltinsARM.def" +}; + +ArrayRef ARMTargetInfo::getTargetBuiltins() const { + return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - + Builtin::FirstTSBuiltin); +} + +bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } +TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const { + return IsAAPCS + ? AAPCSABIBuiltinVaList + : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList + : TargetInfo::VoidPtrBuiltinVaList); +} + +const char *const ARMTargetInfo::GCCRegNames[] = { + // Integer registers + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", + "r12", "sp", "lr", "pc", + + // Float registers + "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", + + // Double registers + "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", + + // Quad registers + "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", + "q12", "q13", "q14", "q15"}; + +ArrayRef ARMTargetInfo::getGCCRegNames() const { + return llvm::makeArrayRef(GCCRegNames); +} + +const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { + {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, + {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, + {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, + {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, + // The S, D and Q registers overlap, but aren't really aliases; we + // don't want to substitute one of these for a different-sized one. +}; + +ArrayRef ARMTargetInfo::getGCCRegAliases() const { + return llvm::makeArrayRef(GCCRegAliases); +} + +bool ARMTargetInfo::validateAsmConstraint( + const char *&Name, TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: + break; + case 'l': // r0-r7 + case 'h': // r8-r15 + case 't': // VFP Floating point register single precision + case 'w': // VFP Floating point register double precision + Info.setAllowsRegister(); + return true; + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + // FIXME + return true; + case 'Q': // A memory address that is a single base register. + Info.setAllowsMemory(); + return true; + case 'U': // a memory reference... + switch (Name[1]) { + case 'q': // ...ARMV4 ldrsb + case 'v': // ...VFP load/store (reg+constant offset) + case 'y': // ...iWMMXt load/store + case 't': // address valid for load/store opaque types wider + // than 128-bits + case 'n': // valid address for Neon doubleword vector load/store + case 'm': // valid address for Neon element and structure load/store + case 's': // valid address for non-offset loads/stores of quad-word + // values in four ARM registers + Info.setAllowsMemory(); + Name++; + return true; } } - HW_FP &= ~HW_FP_remove; + return false; +} - switch (ArchVersion) { - case 6: - if (ArchProfile == llvm::ARM::PK_M) - LDREX = 0; - else if (ArchKind == llvm::ARM::AK_ARMV6K) - LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; - else - LDREX = LDREX_W; +std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const { + std::string R; + switch (*Constraint) { + case 'U': // Two-character constraint; add "^" hint for later parsing. + R = std::string("^") + std::string(Constraint, 2); + Constraint++; break; - case 7: - if (ArchProfile == llvm::ARM::PK_M) - LDREX = LDREX_W | LDREX_H | LDREX_B; - else - LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; + case 'p': // 'p' should be translated to 'r' by default. + R = std::string("r"); break; - case 8: - LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; + default: + return std::string(1, *Constraint); } + return R; +} - if (!(FPU & NeonFPU) && FPMath == FP_Neon) { - Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; - return false; - } +bool ARMTargetInfo::validateConstraintModifier( + StringRef Constraint, char Modifier, unsigned Size, + std::string &SuggestedModifier) const { + bool isOutput = (Constraint[0] == '='); + bool isInOut = (Constraint[0] == '+'); - if (FPMath == FP_Neon) - Features.push_back("+neonfp"); - else if (FPMath == FP_VFP) - Features.push_back("-neonfp"); + // Strip off constraint modifiers. + while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') + Constraint = Constraint.substr(1); - // Remove front-end specific options which the backend handles differently. - auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi"); - if (Feature != Features.end()) - Features.erase(Feature); + switch (Constraint[0]) { + default: + break; + case 'r': { + switch (Modifier) { + default: + return (isInOut || isOutput || Size <= 64); + case 'q': + // A register of size 32 cannot fit a vector type. + return false; + } + } + } return true; } +const char *ARMTargetInfo::getClobbers() const { + // FIXME: Is this really right? + return ""; +} -void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, - MacroBuilder &Builder) const { - Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); +TargetInfo::CallingConvCheckResult +ARMTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + case CC_AAPCS: + case CC_AAPCS_VFP: + case CC_Swift: + case CC_OpenCLKernel: + return CCCR_OK; + default: + return CCCR_Warning; + } +} + +int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) + return 0; + if (RegNo == 1) + return 1; + return -1; } +bool ARMTargetInfo::hasSjLjLowering() const { return true; } + +ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : ARMTargetInfo(Triple, Opts) {} + void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARMEL__"); ARMTargetInfo::getTargetDefines(Opts, Builder); } +ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : ARMTargetInfo(Triple, Opts) {} + void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARMEB__"); @@ -415,6 +927,13 @@ void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, ARMTargetInfo::getTargetDefines(Opts, Builder); } +WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsTargetInfo(Triple, Opts), Triple(Triple) { + WCharType = UnsignedShort; + SizeType = UnsignedInt; +} + void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, MacroBuilder &Builder) const { WindowsTargetInfo::getVisualStudioDefines(Opts, Builder); @@ -435,6 +954,61 @@ void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, Builder.defineMacro("_M_ARM_FP", "31"); } +TargetInfo::BuiltinVaListKind +WindowsARMTargetInfo::getBuiltinVaListKind() const { + return TargetInfo::CharPtrBuiltinVaList; +} + +TargetInfo::CallingConvCheckResult +WindowsARMTargetInfo::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: + return CCCR_OK; + default: + return CCCR_Warning; + } +} + +// Windows ARM + Itanium C++ ABI Target +ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo( + const llvm::Triple &Triple, const TargetOptions &Opts) + : WindowsARMTargetInfo(Triple, Opts) { + TheCXXABI.set(TargetCXXABI::GenericARM); +} + +void ItaniumWindowsARMleTargetInfo::getTargetDefines( + const LangOptions &Opts, MacroBuilder &Builder) const { + WindowsARMTargetInfo::getTargetDefines(Opts, Builder); + + if (Opts.MSVCCompat) + WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); +} + +// Windows ARM, MS (C++) ABI +MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsARMTargetInfo(Triple, Opts) { + TheCXXABI.set(TargetCXXABI::Microsoft); +} + +void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + WindowsARMTargetInfo::getTargetDefines(Opts, Builder); + WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); +} + +MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : WindowsARMTargetInfo(Triple, Opts) { + TheCXXABI.set(TargetCXXABI::GenericARM); +} + void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { WindowsARMTargetInfo::getTargetDefines(Opts, Builder); @@ -444,6 +1018,15 @@ void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, addMinGWDefines(Opts, Builder); } +CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : ARMleTargetInfo(Triple, Opts) { + TLSSupported = false; + WCharType = UnsignedShort; + DoubleAlign = LongLongAlign = 64; + resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); +} + void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { ARMleTargetInfo::getTargetDefines(Opts, Builder); @@ -455,13 +1038,47 @@ void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("_GNU_SOURCE"); } +DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : DarwinTargetInfo(Triple, Opts) { + HasAlignMac68kSupport = true; + // iOS always has 64-bit atomic instructions. + // FIXME: This should be based off of the target features in + // ARMleTargetInfo. + MaxAtomicInlineWidth = 64; + + if (Triple.isWatchABI()) { + // Darwin on iOS uses a variant of the ARM C++ ABI. + TheCXXABI.set(TargetCXXABI::WatchOS); + + // The 32-bit ABI is silent on what ptrdiff_t should be, but given that + // size_t is long, it's a bit weird for it to be int. + PtrDiffType = SignedLong; + + // BOOL should be a real boolean on the new ABI + UseSignedCharForObjCBool = false; + } else + TheCXXABI.set(TargetCXXABI::iOS); +} + +void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, + const llvm::Triple &Triple, + MacroBuilder &Builder) const { + getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); +} + +RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(), + Triple.getOSName(), + Triple.getEnvironmentName()), + Opts) { + IsRenderScriptTarget = true; + LongWidth = LongAlign = 64; +} + void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__RENDERSCRIPT__"); ARMleTargetInfo::getTargetDefines(Opts, Builder); } - -ArrayRef ARMTargetInfo::getTargetBuiltins() const { - return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - - Builtin::FirstTSBuiltin); -} diff --git a/lib/Basic/Targets/ARM.h b/lib/Basic/Targets/ARM.h index 03b6028201..2f52df776c 100644 --- a/lib/Basic/Targets/ARM.h +++ b/lib/Basic/Targets/ARM.h @@ -89,383 +89,40 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { static const Builtin::Info BuiltinInfo[]; - void setABIAAPCS() { - IsAAPCS = true; - - DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; - const llvm::Triple &T = getTriple(); - - // size_t is unsigned long on MachO-derived environments, NetBSD, and - // OpenBSD. - if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD || - T.getOS() == llvm::Triple::OpenBSD) - SizeType = UnsignedLong; - else - SizeType = UnsignedInt; - - switch (T.getOS()) { - case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: - WCharType = SignedInt; - break; - case llvm::Triple::Win32: - WCharType = UnsignedShort; - break; - case llvm::Triple::Linux: - default: - // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. - WCharType = UnsignedInt; - break; - } - - UseBitFieldTypeAlignment = true; - - ZeroLengthBitfieldBoundary = 0; - - // Thumb1 add sp, #imm requires the immediate value be multiple of 4, - // so set preferred for small types to 32. - if (T.isOSBinFormatMachO()) { - resetDataLayout(BigEndian - ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" - : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); - } else if (T.isOSWindows()) { - assert(!BigEndian && "Windows on ARM does not support big endian"); - resetDataLayout("e" - "-m:w" - "-p:32:32" - "-i64:64" - "-v128:64:128" - "-a:0:32" - "-n32" - "-S64"); - } else if (T.isOSNaCl()) { - assert(!BigEndian && "NaCl on ARM does not support big endian"); - resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"); - } else { - resetDataLayout(BigEndian - ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" - : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); - } - - // FIXME: Enumerated types are variable width in straight AAPCS. - } - - void setABIAPCS(bool IsAAPCS16) { - const llvm::Triple &T = getTriple(); - - IsAAPCS = false; - - if (IsAAPCS16) - DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; - else - DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; - - // size_t is unsigned int on FreeBSD. - if (T.getOS() == llvm::Triple::FreeBSD) - SizeType = UnsignedInt; - else - SizeType = UnsignedLong; - - // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. - WCharType = SignedInt; - - // Do not respect the alignment of bit-field types when laying out - // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. - UseBitFieldTypeAlignment = false; - - /// gcc forces the alignment to 4 bytes, regardless of the type of the - /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in - /// gcc. - ZeroLengthBitfieldBoundary = 32; - - if (T.isOSBinFormatMachO() && IsAAPCS16) { - assert(!BigEndian && "AAPCS16 does not support big-endian"); - resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128"); - } else if (T.isOSBinFormatMachO()) - resetDataLayout( - BigEndian - ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" - : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); - else - resetDataLayout( - BigEndian - ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" - : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); - - // FIXME: Override "preferred align" for double and long long. - } - - void setArchInfo() { - StringRef ArchName = getTriple().getArchName(); - - ArchISA = llvm::ARM::parseArchISA(ArchName); - CPU = llvm::ARM::getDefaultCPU(ArchName); - unsigned AK = llvm::ARM::parseArch(ArchName); - if (AK != llvm::ARM::AK_INVALID) - ArchKind = AK; - setArchInfo(ArchKind); - } - - void setArchInfo(unsigned Kind) { - StringRef SubArch; + void setABIAAPCS(); + void setABIAPCS(bool IsAAPCS16); - // cache TargetParser info - ArchKind = Kind; - SubArch = llvm::ARM::getSubArch(ArchKind); - ArchProfile = llvm::ARM::parseArchProfile(SubArch); - ArchVersion = llvm::ARM::parseArchVersion(SubArch); + void setArchInfo(); + void setArchInfo(unsigned Kind); - // cache CPU related strings - CPUAttr = getCPUAttr(); - CPUProfile = getCPUProfile(); - } - - void setAtomic() { - // when triple does not specify a sub arch, - // then we are not using inline atomics - bool ShouldUseInlineAtomic = - (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) || - (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7); - // Cortex M does not support 8 byte atomics, while general Thumb2 does. - if (ArchProfile == llvm::ARM::PK_M) { - MaxAtomicPromoteWidth = 32; - if (ShouldUseInlineAtomic) - MaxAtomicInlineWidth = 32; - } else { - MaxAtomicPromoteWidth = 64; - if (ShouldUseInlineAtomic) - MaxAtomicInlineWidth = 64; - } - } - - bool isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); } - - bool supportsThumb() const { return CPUAttr.count('T') || ArchVersion >= 6; } - - bool supportsThumb2() const { - return CPUAttr.equals("6T2") || - (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE")); - } + void setAtomic(); - StringRef getCPUAttr() const { - // For most sub-arches, the build attribute CPU name is enough. - // For Cortex variants, it's slightly different. - switch (ArchKind) { - default: - return llvm::ARM::getCPUAttr(ArchKind); - case llvm::ARM::AK_ARMV6M: - return "6M"; - case llvm::ARM::AK_ARMV7S: - return "7S"; - case llvm::ARM::AK_ARMV7A: - return "7A"; - case llvm::ARM::AK_ARMV7R: - return "7R"; - case llvm::ARM::AK_ARMV7M: - return "7M"; - case llvm::ARM::AK_ARMV7EM: - return "7EM"; - case llvm::ARM::AK_ARMV7VE: - return "7VE"; - case llvm::ARM::AK_ARMV8A: - return "8A"; - case llvm::ARM::AK_ARMV8_1A: - return "8_1A"; - case llvm::ARM::AK_ARMV8_2A: - return "8_2A"; - case llvm::ARM::AK_ARMV8MBaseline: - return "8M_BASE"; - case llvm::ARM::AK_ARMV8MMainline: - return "8M_MAIN"; - case llvm::ARM::AK_ARMV8R: - return "8R"; - } - } + bool isThumb() const; + bool supportsThumb() const; + bool supportsThumb2() const; - StringRef getCPUProfile() const { - switch (ArchProfile) { - case llvm::ARM::PK_A: - return "A"; - case llvm::ARM::PK_R: - return "R"; - case llvm::ARM::PK_M: - return "M"; - default: - return ""; - } - } + StringRef getCPUAttr() const; + StringRef getCPUProfile() const; public: - ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), - HW_FP(0) { - - switch (getTriple().getOS()) { - case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: - PtrDiffType = SignedLong; - break; - default: - PtrDiffType = SignedInt; - break; - } - - // Cache arch related info. - setArchInfo(); - - // {} in inline assembly are neon specifiers, not assembly variant - // specifiers. - NoAsmVariants = true; - - // FIXME: This duplicates code from the driver that sets the -target-abi - // option - this code is used if -target-abi isn't passed and should - // be unified in some way. - if (Triple.isOSBinFormatMachO()) { - // The backend is hardwired to assume AAPCS for M-class processors, ensure - // the frontend matches that. - if (Triple.getEnvironment() == llvm::Triple::EABI || - Triple.getOS() == llvm::Triple::UnknownOS || - ArchProfile == llvm::ARM::PK_M) { - setABI("aapcs"); - } else if (Triple.isWatchABI()) { - setABI("aapcs16"); - } else { - setABI("apcs-gnu"); - } - } else if (Triple.isOSWindows()) { - // FIXME: this is invalid for WindowsCE - setABI("aapcs"); - } else { - // Select the default based on the platform. - switch (Triple.getEnvironment()) { - case llvm::Triple::Android: - case llvm::Triple::GNUEABI: - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABI: - case llvm::Triple::MuslEABIHF: - setABI("aapcs-linux"); - break; - case llvm::Triple::EABIHF: - case llvm::Triple::EABI: - setABI("aapcs"); - break; - case llvm::Triple::GNU: - setABI("apcs-gnu"); - break; - default: - if (Triple.getOS() == llvm::Triple::NetBSD) - setABI("apcs-gnu"); - else if (Triple.getOS() == llvm::Triple::OpenBSD) - setABI("aapcs-linux"); - else - setABI("aapcs"); - break; - } - } - - // ARM targets default to using the ARM C++ ABI. - TheCXXABI.set(TargetCXXABI::GenericARM); - - // ARM has atomics up to 8 bytes - setAtomic(); - - // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) - if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android)) - MaxVectorAlign = 64; - - // Do force alignment of members that follow zero length bitfields. If - // the alignment of the zero-length bitfield is greater than the member - // that follows it, `bar', `bar' will be aligned as the type of the - // zero length bitfield. - UseZeroLengthBitfieldAlignment = true; - - if (Triple.getOS() == llvm::Triple::Linux || - Triple.getOS() == llvm::Triple::UnknownOS) - this->MCountName = Opts.EABIVersion == llvm::EABI::GNU - ? "\01__gnu_mcount_nc" - : "\01mcount"; - } + ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); - StringRef getABI() const override { return ABI; } - - bool setABI(const std::string &Name) override { - ABI = Name; - - // The defaults (above) are for AAPCS, check if we need to change them. - // - // FIXME: We need support for -meabi... we could just mangle it into the - // name. - if (Name == "apcs-gnu" || Name == "aapcs16") { - setABIAPCS(Name == "aapcs16"); - return true; - } - if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") { - setABIAAPCS(); - return true; - } - return false; - } + StringRef getABI() const override; + bool setABI(const std::string &Name) override; // FIXME: This should be based on Arch attributes, not CPU names. bool initFeatureMap(llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, - const std::vector &FeaturesVec) const override { - - std::vector TargetFeatures; - unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName()); - - // get default FPU features - unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch); - llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures); - - // get default Extension features - unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch); - llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures); - - for (auto Feature : TargetFeatures) - if (Feature[0] == '+') - Features[Feature.drop_front(1)] = true; - - // Enable or disable thumb-mode explicitly per function to enable mixed - // ARM and Thumb code generation. - if (isThumb()) - Features["thumb-mode"] = true; - else - Features["thumb-mode"] = false; - - // Convert user-provided arm and thumb GNU target attributes to - // [-|+]thumb-mode target features respectively. - std::vector UpdatedFeaturesVec(FeaturesVec); - for (auto &Feature : UpdatedFeaturesVec) { - if (Feature.compare("+arm") == 0) - Feature = "-thumb-mode"; - else if (Feature.compare("+thumb") == 0) - Feature = "+thumb-mode"; - } - - return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); - } + const std::vector &FeaturesVec) const override; bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override; bool hasFeature(StringRef Feature) const override; - bool isValidCPUName(StringRef Name) const override { - return Name == "generic" || - llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID; - } - - bool setCPU(const std::string &Name) override { - if (Name != "generic") - setArchInfo(llvm::ARM::parseCPUArch(Name)); - if (ArchKind == llvm::ARM::AK_INVALID) - return false; - setAtomic(); - CPU = Name; - return true; - } + bool isValidCPUName(StringRef Name) const override; + bool setCPU(const std::string &Name) override; bool setFPMath(StringRef Name) override; @@ -473,143 +130,42 @@ public: MacroBuilder &Builder) const; void getTargetDefinesARMV82A(const LangOptions &Opts, - MacroBuilder &Builder) const { - // Also include the ARMv8.1-A defines - getTargetDefinesARMV81A(Opts, Builder); - } - + MacroBuilder &Builder) const; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; + ArrayRef getTargetBuiltins() const override; - bool isCLZForZeroUndef() const override { return false; } - BuiltinVaListKind getBuiltinVaListKind() const override { - return IsAAPCS - ? AAPCSABIBuiltinVaList - : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList - : TargetInfo::VoidPtrBuiltinVaList); - } + + bool isCLZForZeroUndef() const override; + BuiltinVaListKind getBuiltinVaListKind() const override; + ArrayRef getGCCRegNames() const override; ArrayRef getGCCRegAliases() const override; bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const override { - switch (*Name) { - default: - break; - case 'l': // r0-r7 - case 'h': // r8-r15 - case 't': // VFP Floating point register single precision - case 'w': // VFP Floating point register double precision - Info.setAllowsRegister(); - return true; - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - // FIXME - return true; - case 'Q': // A memory address that is a single base register. - Info.setAllowsMemory(); - return true; - case 'U': // a memory reference... - switch (Name[1]) { - case 'q': // ...ARMV4 ldrsb - case 'v': // ...VFP load/store (reg+constant offset) - case 'y': // ...iWMMXt load/store - case 't': // address valid for load/store opaque types wider - // than 128-bits - case 'n': // valid address for Neon doubleword vector load/store - case 'm': // valid address for Neon element and structure load/store - case 's': // valid address for non-offset loads/stores of quad-word - // values in four ARM registers - Info.setAllowsMemory(); - Name++; - return true; - } - } - return false; - } - std::string convertConstraint(const char *&Constraint) const override { - std::string R; - switch (*Constraint) { - case 'U': // Two-character constraint; add "^" hint for later parsing. - R = std::string("^") + std::string(Constraint, 2); - Constraint++; - break; - case 'p': // 'p' should be translated to 'r' by default. - R = std::string("r"); - break; - default: - return std::string(1, *Constraint); - } - return R; - } + TargetInfo::ConstraintInfo &Info) const override; + std::string convertConstraint(const char *&Constraint) const override; bool validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size, - std::string &SuggestedModifier) const override { - bool isOutput = (Constraint[0] == '='); - bool isInOut = (Constraint[0] == '+'); - - // Strip off constraint modifiers. - while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&') - Constraint = Constraint.substr(1); - - switch (Constraint[0]) { - default: - break; - case 'r': { - switch (Modifier) { - default: - return (isInOut || isOutput || Size <= 64); - case 'q': - // A register of size 32 cannot fit a vector type. - return false; - } - } - } - - return true; - } - const char *getClobbers() const override { - // FIXME: Is this really right? - return ""; - } + std::string &SuggestedModifier) const override; + const char *getClobbers() const override; - CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - switch (CC) { - case CC_AAPCS: - case CC_AAPCS_VFP: - case CC_Swift: - case CC_OpenCLKernel: - return CCCR_OK; - default: - return CCCR_Warning; - } - } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; - int getEHDataRegisterNumber(unsigned RegNo) const override { - if (RegNo == 0) - return 0; - if (RegNo == 1) - return 1; - return -1; - } + int getEHDataRegisterNumber(unsigned RegNo) const override; - bool hasSjLjLowering() const override { return true; } + bool hasSjLjLowering() const override; }; class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo { public: - ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : ARMTargetInfo(Triple, Opts) {} + ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; }; class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo { public: - ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : ARMTargetInfo(Triple, Opts) {} + ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; }; @@ -619,30 +175,14 @@ class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo const llvm::Triple Triple; public: - WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : WindowsTargetInfo(Triple, Opts), Triple(Triple) { - WCharType = UnsignedShort; - SizeType = UnsignedInt; - } + WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); + void getVisualStudioDefines(const LangOptions &Opts, MacroBuilder &Builder) const; - BuiltinVaListKind getBuiltinVaListKind() const override { - return TargetInfo::CharPtrBuiltinVaList; - } - CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { - switch (CC) { - case CC_X86StdCall: - case CC_X86ThisCall: - case CC_X86FastCall: - case CC_X86VectorCall: - return CCCR_Ignore; - case CC_C: - case CC_OpenCLKernel: - return CCCR_OK; - default: - return CCCR_Warning; - } - } + + BuiltinVaListKind getBuiltinVaListKind() const override; + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; }; // Windows ARM + Itanium C++ ABI Target @@ -650,18 +190,10 @@ class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo : public WindowsARMTargetInfo { public: ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple, - const TargetOptions &Opts) - : WindowsARMTargetInfo(Triple, Opts) { - TheCXXABI.set(TargetCXXABI::GenericARM); - } + const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - WindowsARMTargetInfo::getTargetDefines(Opts, Builder); - - if (Opts.MSVCCompat) - WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); - } + MacroBuilder &Builder) const override; }; // Windows ARM, MS (C++) ABI @@ -669,25 +201,16 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo : public WindowsARMTargetInfo { public: MicrosoftARMleTargetInfo(const llvm::Triple &Triple, - const TargetOptions &Opts) - : WindowsARMTargetInfo(Triple, Opts) { - TheCXXABI.set(TargetCXXABI::Microsoft); - } + const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const override { - WindowsARMTargetInfo::getTargetDefines(Opts, Builder); - WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); - } + MacroBuilder &Builder) const override; }; // ARM MinGW target class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo { public: - MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : WindowsARMTargetInfo(Triple, Opts) { - TheCXXABI.set(TargetCXXABI::GenericARM); - } + MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; @@ -696,13 +219,8 @@ public: // ARM Cygwin target class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo { public: - CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : ARMleTargetInfo(Triple, Opts) { - TLSSupported = false; - WCharType = UnsignedShort; - DoubleAlign = LongLongAlign = 64; - resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); - } + CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; }; @@ -711,46 +229,19 @@ class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo : public DarwinTargetInfo { protected: void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const override { - getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); - } + MacroBuilder &Builder) const override; public: - DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : DarwinTargetInfo(Triple, Opts) { - HasAlignMac68kSupport = true; - // iOS always has 64-bit atomic instructions. - // FIXME: This should be based off of the target features in - // ARMleTargetInfo. - MaxAtomicInlineWidth = 64; - - if (Triple.isWatchABI()) { - // Darwin on iOS uses a variant of the ARM C++ ABI. - TheCXXABI.set(TargetCXXABI::WatchOS); - - // The 32-bit ABI is silent on what ptrdiff_t should be, but given that - // size_t is long, it's a bit weird for it to be int. - PtrDiffType = SignedLong; - - // BOOL should be a real boolean on the new ABI - UseSignedCharForObjCBool = false; - } else - TheCXXABI.set(TargetCXXABI::iOS); - } + DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); }; + // 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo : public ARMleTargetInfo { public: RenderScript32TargetInfo(const llvm::Triple &Triple, - const TargetOptions &Opts) - : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(), - Triple.getOSName(), - Triple.getEnvironmentName()), - Opts) { - IsRenderScriptTarget = true; - LongWidth = LongAlign = 64; - } + const TargetOptions &Opts); + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; }; -- 2.40.0