-Refactored ARMTargetInfo in order to use the API of TargetParser

for extracting target specific information.
-Patches commit r241343: case 'armv7l' was unhandled in
 ARMTargetInfo::getCPUAttr(), and thus it was returning invalid
 characters for macro definition.

Change-Id: I1a0972e5ff5529cd17376c6562047bab8b4da32c
Phabricator: http://reviews.llvm.org/D10839
llvm-svn: 242514
This commit is contained in:
Alexandros Lamprineas 2015-07-17 09:08:37 +00:00
parent 7a94f98bea
commit 65bc306345
1 changed files with 150 additions and 156 deletions

View File

@ -4041,16 +4041,24 @@ class ARMTargetInfo : public TargetInfo {
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.
@ -4070,37 +4078,6 @@ class ARMTargetInfo : public TargetInfo {
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;
@ -4199,6 +4176,117 @@ class ARMTargetInfo : public TargetInfo {
// 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),
@ -4213,14 +4301,14 @@ public:
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.
@ -4265,9 +4353,7 @@ public:
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
@ -4298,11 +4384,6 @@ public:
// 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") {
@ -4327,7 +4408,7 @@ public:
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" ||
@ -4404,106 +4485,25 @@ public:
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.
@ -4512,20 +4512,13 @@ public:
// 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");
}
@ -4539,9 +4532,9 @@ public:
// __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
@ -4566,7 +4559,7 @@ public:
// 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") {
@ -4586,13 +4579,13 @@ public:
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.
@ -4612,7 +4605,7 @@ public:
// 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__");
}
@ -4629,20 +4622,21 @@ public:
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;