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.
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;
// 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),
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.
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
// FIXME: This should be based on Arch attributes, not CPU names.
void getDefaultFeatures(llvm::StringMap<bool> &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") {
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" ||
return llvm::StringSwitch<bool>(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.
// Target properties.
Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- StringRef CPUArch = getCPUDefineSuffix(CPU);
- unsigned int CPUArchVer;
- if (CPUArch.substr(0, 1).getAsInteger<unsigned int>(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");
}
// __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
// 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") {
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.
// 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__");
}
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;