Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -4037,16 +4037,24 @@ std::string ABI, CPU; + StringRef DefaultCPU; + StringRef CPUProfile; + StringRef CPUAttr; + enum { FP_Default, FP_VFP, FP_Neon } FPMath; + unsigned ArchISA; + unsigned ArchKind; + unsigned ArchProfile; + unsigned ArchVersion; + unsigned FPU : 5; unsigned IsAAPCS : 1; - unsigned IsThumb : 1; unsigned HWDiv : 2; // Initialized via features. @@ -4066,37 +4074,6 @@ static const Builtin::Info BuiltinInfo[]; - static bool shouldUseInlineAtomic(const llvm::Triple &T) { - StringRef ArchName = T.getArchName(); - if (T.getArch() == llvm::Triple::arm || - T.getArch() == llvm::Triple::armeb) { - StringRef VersionStr; - if (ArchName.startswith("armv")) - VersionStr = ArchName.substr(4, 1); - else if (ArchName.startswith("armebv")) - VersionStr = ArchName.substr(6, 1); - else - return false; - unsigned Version; - if (VersionStr.getAsInteger(10, Version)) - return false; - return Version >= 6; - } - assert(T.getArch() == llvm::Triple::thumb || - T.getArch() == llvm::Triple::thumbeb); - StringRef VersionStr; - if (ArchName.startswith("thumbv")) - VersionStr = ArchName.substr(6, 1); - else if (ArchName.startswith("thumbebv")) - VersionStr = ArchName.substr(8, 1); - else - return false; - unsigned Version; - if (VersionStr.getAsInteger(10, Version)) - return false; - return Version >= 7; - } - void setABIAAPCS() { IsAAPCS = true; @@ -4195,6 +4172,117 @@ // FIXME: Override "preferred align" for double and long long. } + void setArchInfo() { + StringRef ArchName = getTriple().getArchName(); + + ArchISA = llvm::ARMTargetParser::parseArchISA(ArchName); + DefaultCPU = getDefaultCPU(ArchName); + + // SubArch is specified by the target triple + if (!DefaultCPU.empty()) + setArchInfo(DefaultCPU); + else + // FIXME ArchInfo should be based on ArchName from triple, not on + // a hard-coded CPU name. Doing so currently causes regressions: + // test/Preprocessor/init.c: __ARM_ARCH_6J__ not defined + setArchInfo(CPU); + } + + void setArchInfo(StringRef CPU) { + StringRef SubArch; + + // cache TargetParser info + ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU); + SubArch = llvm::ARMTargetParser::getSubArch(ArchKind); + ArchProfile = llvm::ARMTargetParser::parseArchProfile(SubArch); + ArchVersion = llvm::ARMTargetParser::parseArchVersion(SubArch); + + // 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 = DefaultCPU.empty() ? + false : + (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; + } + + StringRef getDefaultCPU(StringRef ArchName) const { + const char *DefaultCPU = llvm::ARMTargetParser::getDefaultCPU(ArchName); + return DefaultCPU ? DefaultCPU : ""; + } + + StringRef getCPUAttr() const { + const char *CPUAttr; + // For most sub-arches, the build attribute CPU name is enough. + // For Cortex variants, it's slightly different. + switch(ArchKind) { + default: + CPUAttr = llvm::ARMTargetParser::getCPUAttr(ArchKind); + return CPUAttr ? CPUAttr : ""; + case llvm::ARM::AK_ARMV6M: + case llvm::ARM::AK_ARMV6SM: + case llvm::ARM::AK_ARMV6HL: + return "6M"; + case llvm::ARM::AK_ARMV7: + case llvm::ARM::AK_ARMV7A: + case llvm::ARM::AK_ARMV7S: + case llvm::ARM::AK_ARMV7L: + case llvm::ARM::AK_ARMV7HL: + 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_ARMV8A: + return "8A"; + case llvm::ARM::AK_ARMV8_1A: + return "8_1A"; + } + } + + 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 ""; + } + } + public: ARMTargetInfo(const llvm::Triple &Triple, bool IsBigEndian) : TargetInfo(Triple), CPU("arm1136j-s"), FPMath(FP_Default), @@ -4209,14 +4297,14 @@ PtrDiffType = SignedInt; break; } - + + // cache arch related info + setArchInfo(); + // {} in inline assembly are neon specifiers, not assembly variant // specifiers. NoAsmVariants = true; - // FIXME: Should we just treat this as a feature? - IsThumb = getTriple().getArchName().startswith("thumb"); - // 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. @@ -4261,9 +4349,7 @@ TheCXXABI.set(TargetCXXABI::GenericARM); // ARM has atomics up to 8 bytes - MaxAtomicPromoteWidth = 64; - if (shouldUseInlineAtomic(getTriple())) - MaxAtomicInlineWidth = 64; + setAtomic(); // Do force alignment of members that follow zero length bitfields. If // the alignment of the zero-length bitfield is greater than the member @@ -4294,11 +4380,6 @@ // FIXME: This should be based on Arch attributes, not CPU names. void getDefaultFeatures(llvm::StringMap &Features) const override { - StringRef ArchName = getTriple().getArchName(); - unsigned ArchKind = llvm::ARMTargetParser::parseArch(ArchName); - bool IsV8 = (ArchKind == llvm::ARM::AK_ARMV8A || - ArchKind == llvm::ARM::AK_ARMV8_1A); - if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") Features["vfp2"] = true; else if (CPU == "cortex-a8" || CPU == "cortex-a9") { @@ -4323,7 +4404,7 @@ Features["hwdiv-arm"] = true; Features["crc"] = true; Features["crypto"] = true; - } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || IsV8) { + } else if (CPU == "cortex-r5" || CPU == "cortex-r7" || ArchVersion == 8) { Features["hwdiv"] = true; Features["hwdiv-arm"] = true; } else if (CPU == "cortex-m3" || CPU == "cortex-m4" || CPU == "cortex-m7" || @@ -4400,106 +4481,25 @@ return llvm::StringSwitch(Feature) .Case("arm", true) .Case("softfloat", SoftFloat) - .Case("thumb", IsThumb) + .Case("thumb", isThumb()) .Case("neon", (FPU & NeonFPU) && !SoftFloat) .Case("hwdiv", HWDiv & HWDivThumb) .Case("hwdiv-arm", HWDiv & HWDivARM) .Default(false); } - const char *getCPUDefineSuffix(StringRef Name) const { - if(Name == "generic") { - auto subarch = getTriple().getSubArch(); - switch (subarch) { - case llvm::Triple::SubArchType::ARMSubArch_v8_1a: - return "8_1A"; - default: - break; - } - } + bool setCPU(const std::string &Name) override { unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(Name); if (ArchKind == llvm::ARM::AK_INVALID) - return ""; - - // For most sub-arches, the build attribute CPU name is enough. - // For Cortex variants, it's slightly different. - switch(ArchKind) { - default: - return llvm::ARMTargetParser::getCPUAttr(ArchKind); - case llvm::ARM::AK_ARMV6M: - case llvm::ARM::AK_ARMV6SM: - return "6M"; - case llvm::ARM::AK_ARMV7: - case llvm::ARM::AK_ARMV7A: - case llvm::ARM::AK_ARMV7S: - 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_ARMV8A: - return "8A"; - case llvm::ARM::AK_ARMV8_1A: - return "8_1A"; - } - } - const char *getCPUProfile(StringRef Name) const { - if(Name == "generic") { - auto subarch = getTriple().getSubArch(); - switch (subarch) { - case llvm::Triple::SubArchType::ARMSubArch_v8_1a: - return "A"; - default: - break; - } - } - - unsigned CPUArch = llvm::ARMTargetParser::parseCPUArch(Name); - if (CPUArch == llvm::ARM::AK_INVALID) - return ""; - - StringRef ArchName = llvm::ARMTargetParser::getArchName(CPUArch); - switch(llvm::ARMTargetParser::parseArchProfile(ArchName)) { - case llvm::ARM::PK_A: - return "A"; - case llvm::ARM::PK_R: - return "R"; - case llvm::ARM::PK_M: - return "M"; - default: - return ""; - } - } - bool setCPU(const std::string &Name) override { - if (!getCPUDefineSuffix(Name)) return false; - - // Cortex M does not support 8 byte atomics, while general Thumb2 does. - StringRef Profile = getCPUProfile(Name); - if (Profile == "M" && MaxAtomicInlineWidth) { - MaxAtomicPromoteWidth = 32; - MaxAtomicInlineWidth = 32; - } - + setArchInfo(Name); + setAtomic(); CPU = Name; return true; } + bool setFPMath(StringRef Name) override; - bool supportsThumb(StringRef ArchName, StringRef CPUArch, - unsigned CPUArchVer) const { - return CPUArchVer >= 7 || (CPUArch.find('T') != StringRef::npos) || - (CPUArch.find('M') != StringRef::npos); - } - bool supportsThumb2(StringRef ArchName, StringRef CPUArch, - unsigned CPUArchVer) const { - // We check both CPUArchVer and ArchName because when only triple is - // specified, the default CPU is arm1136j-s. - return ArchName.endswith("v6t2") || ArchName.endswith("v7") || - ArchName.endswith("v8.1a") || - ArchName.endswith("v8") || CPUArch == "6T2" || CPUArchVer >= 7; - } + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override { // Target identification. @@ -4508,20 +4508,13 @@ // Target properties. Builder.defineMacro("__REGISTER_PREFIX__", ""); - - StringRef CPUArch = getCPUDefineSuffix(CPU); - unsigned int CPUArchVer; - if (CPUArch.substr(0, 1).getAsInteger(10, CPUArchVer)) - llvm_unreachable("Invalid char for architecture version number"); - Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__"); + if (!CPUAttr.empty()) + Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); // ACLE 6.4.1 ARM/Thumb instruction set architecture - StringRef CPUProfile = getCPUProfile(CPU); - StringRef ArchName = getTriple().getArchName(); - // __ARM_ARCH is defined as an integer value indicating the current ARM ISA - Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1)); - if (CPUArch[0] >= '8') { + Builder.defineMacro("__ARM_ARCH", std::to_string(ArchVersion)); + if (ArchVersion >= 8) { Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN"); Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING"); } @@ -4535,9 +4528,9 @@ // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supporst the original // Thumb ISA (including v6-M). It is set to 2 if the core supports the // Thumb-2 ISA as found in the v6T2 architecture and all v7 architecture. - if (supportsThumb2(ArchName, CPUArch, CPUArchVer)) + if (supportsThumb2()) Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); - else if (supportsThumb(ArchName, CPUArch, CPUArchVer)) + else if (supportsThumb()) Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit @@ -4562,7 +4555,7 @@ // FIXME: It's more complicated than this and we don't really support // interworking. // Windows on ARM does not "support" interworking - if (5 <= CPUArchVer && CPUArchVer <= 8 && !getTriple().isOSWindows()) + if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows()) Builder.defineMacro("__THUMB_INTERWORK__"); if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { @@ -4582,13 +4575,13 @@ if (CPU == "xscale") Builder.defineMacro("__XSCALE__"); - if (IsThumb) { + if (isThumb()) { Builder.defineMacro("__THUMBEL__"); Builder.defineMacro("__thumb__"); - if (supportsThumb2(ArchName, CPUArch, CPUArchVer)) + if (supportsThumb2()) Builder.defineMacro("__thumb2__"); } - if (((HWDiv & HWDivThumb) && IsThumb) || ((HWDiv & HWDivARM) && !IsThumb)) + if (((HWDiv & HWDivThumb) && isThumb()) || ((HWDiv & HWDivARM) && !isThumb())) Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1"); // Note, this is always on in gcc, even though it doesn't make sense. @@ -4608,7 +4601,7 @@ // the VFP define, hence the soft float and arch check. This is subtly // different from gcc, we follow the intent which was that it should be set // when Neon instructions are actually available. - if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) { + if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) { Builder.defineMacro("__ARM_NEON"); Builder.defineMacro("__ARM_NEON__"); } @@ -4625,20 +4618,21 @@ if (Crypto) Builder.defineMacro("__ARM_FEATURE_CRYPTO"); - if (CPUArchVer >= 6 && CPUArch != "6M") { + if (ArchVersion >= 6 && CPUAttr != "6M") { 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"); } - bool is5EOrAbove = (CPUArchVer >= 6 || - (CPUArchVer == 5 && - CPUArch.find('E') != StringRef::npos)); - bool is32Bit = (!IsThumb || supportsThumb2(ArchName, CPUArch, CPUArchVer)); - if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUArch == "7EM")) + bool is5EOrAbove = (ArchVersion >= 6 || + (ArchVersion == 5 && CPUAttr.count('E'))); + // FIXME: We are not getting all 32-bit ARM architectures + bool is32Bit = (!isThumb() || supportsThumb2()); + if (is5EOrAbove && is32Bit && (CPUProfile != "M" || CPUAttr == "7EM")) Builder.defineMacro("__ARM_FEATURE_DSP"); } + void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const override { Records = BuiltinInfo;