summaryrefslogtreecommitdiffstats
path: root/lib/Basic/Targets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/Targets.cpp')
-rw-r--r--lib/Basic/Targets.cpp306
1 files changed, 265 insertions, 41 deletions
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 3eda9d8..a622a11 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -621,7 +621,7 @@ class NaClTargetInfo : public OSTargetInfo<Target> {
this->SizeType = TargetInfo::UnsignedInt;
this->PtrDiffType = TargetInfo::SignedInt;
this->IntPtrType = TargetInfo::SignedInt;
- this->RegParmMax = 2;
+ // RegParmMax is inherited from the underlying architecture
this->LongDoubleFormat = &llvm::APFloat::IEEEdouble;
this->DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"
"f32:32:32-f64:64:64-p:32:32:32-v128:32:32";
@@ -1835,6 +1835,7 @@ class X86TargetInfo : public TargetInfo {
/// Bobcat architecture processors.
//@{
CK_BTVER1,
+ CK_BTVER2,
//@}
/// \name Bulldozer
@@ -1959,6 +1960,7 @@ public:
.Case("opteron-sse3", CK_OpteronSSE3)
.Case("amdfam10", CK_AMDFAM10)
.Case("btver1", CK_BTVER1)
+ .Case("btver2", CK_BTVER2)
.Case("bdver1", CK_BDVER1)
.Case("bdver2", CK_BDVER2)
.Case("x86-64", CK_x86_64)
@@ -2024,6 +2026,7 @@ public:
case CK_OpteronSSE3:
case CK_AMDFAM10:
case CK_BTVER1:
+ case CK_BTVER2:
case CK_BDVER1:
case CK_BDVER2:
case CK_x86_64:
@@ -2193,6 +2196,15 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
setFeatureEnabled(Features, "lzcnt", true);
setFeatureEnabled(Features, "popcnt", true);
break;
+ case CK_BTVER2:
+ setFeatureEnabled(Features, "avx", true);
+ setFeatureEnabled(Features, "sse4a", true);
+ setFeatureEnabled(Features, "lzcnt", true);
+ setFeatureEnabled(Features, "aes", true);
+ setFeatureEnabled(Features, "pclmul", true);
+ setFeatureEnabled(Features, "bmi", true);
+ setFeatureEnabled(Features, "f16c", true);
+ break;
case CK_BDVER1:
setFeatureEnabled(Features, "xop", true);
setFeatureEnabled(Features, "lzcnt", true);
@@ -2611,6 +2623,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
case CK_BTVER1:
defineCPUMacros(Builder, "btver1");
break;
+ case CK_BTVER2:
+ defineCPUMacros(Builder, "btver2");
+ break;
case CK_BDVER1:
defineCPUMacros(Builder, "bdver1");
break;
@@ -3292,6 +3307,8 @@ namespace {
class AArch64TargetInfo : public TargetInfo {
static const char * const GCCRegNames[];
static const TargetInfo::GCCRegAlias GCCRegAliases[];
+
+ static const Builtin::Info BuiltinInfo[];
public:
AArch64TargetInfo(const std::string& triple) : TargetInfo(triple) {
BigEndian = false;
@@ -3323,45 +3340,45 @@ public:
// FIXME: these were written based on an unreleased version of a 32-bit ACLE
// which was intended to be compatible with a 64-bit implementation. They
// will need updating when a real 64-bit ACLE exists. Particularly pressing
- // instances are: __AARCH_ISA_A32, __AARCH_ISA_T32, __ARCH_PCS.
- Builder.defineMacro("__AARCH_ACLE", "101");
- Builder.defineMacro("__AARCH", "8");
- Builder.defineMacro("__AARCH_PROFILE", "'A'");
+ // instances are: __ARM_ARCH_ISA_ARM, __ARM_ARCH_ISA_THUMB, __ARM_PCS.
+ Builder.defineMacro("__ARM_ACLE", "101");
+ Builder.defineMacro("__ARM_ARCH", "8");
+ Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
- Builder.defineMacro("__AARCH_FEATURE_UNALIGNED");
- Builder.defineMacro("__AARCH_FEATURE_CLZ");
- Builder.defineMacro("__AARCH_FEATURE_FMA");
+ Builder.defineMacro("__ARM_FEATURE_UNALIGNED");
+ Builder.defineMacro("__ARM_FEATURE_CLZ");
+ Builder.defineMacro("__ARM_FEATURE_FMA");
// FIXME: ACLE 1.1 reserves bit 4. Will almost certainly come to mean
// 128-bit LDXP present, at which point this becomes 0x1f.
- Builder.defineMacro("__AARCH_FEATURE_LDREX", "0xf");
+ Builder.defineMacro("__ARM_FEATURE_LDREX", "0xf");
// 0xe implies support for half, single and double precision operations.
- Builder.defineMacro("__AARCH_FP", "0xe");
+ Builder.defineMacro("__ARM_FP", "0xe");
// PCS specifies this for SysV variants, which is all we support. Other ABIs
- // may choose __AARCH_FP16_FORMAT_ALTERNATIVE.
- Builder.defineMacro("__AARCH_FP16_FORMAT_IEEE");
+ // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
+ Builder.defineMacro("__ARM_FP16_FORMAT_IEEE");
if (Opts.FastMath || Opts.FiniteMathOnly)
- Builder.defineMacro("__AARCH_FP_FAST");
+ Builder.defineMacro("__ARM_FP_FAST");
if ((Opts.C99 || Opts.C11) && !Opts.Freestanding)
- Builder.defineMacro("__AARCH_FP_FENV_ROUNDING");
+ Builder.defineMacro("__ARM_FP_FENV_ROUNDING");
- Builder.defineMacro("__AARCH_SIZEOF_WCHAR_T",
+ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
Opts.ShortWChar ? "2" : "4");
- Builder.defineMacro("__AARCH_SIZEOF_MINIMAL_ENUM",
+ Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
Opts.ShortEnums ? "1" : "4");
if (BigEndian)
- Builder.defineMacro("__AARCH_BIG_ENDIAN");
+ Builder.defineMacro("__ARM_BIG_ENDIAN");
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const {
- Records = 0;
- NumRecords = 0;
+ Records = BuiltinInfo;
+ NumRecords = clang::AArch64::LastTSBuiltin-Builtin::FirstTSBuiltin;
}
virtual bool hasFeature(StringRef Feature) const {
return Feature == "aarch64";
@@ -3470,6 +3487,14 @@ void AArch64TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
NumAliases = llvm::array_lengthof(GCCRegAliases);
}
+
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES },
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER,\
+ ALL_LANGUAGES },
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
} // end anonymous namespace
namespace {
@@ -3502,6 +3527,34 @@ class ARMTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
+ static bool shouldUseInlineAtomic(const llvm::Triple &T) {
+ // On linux, binaries targeting old cpus call functions in libgcc to
+ // perform atomic operations. The implementation in libgcc then calls into
+ // the kernel which on armv6 and newer uses ldrex and strex. The net result
+ // is that if we assume the kernel is at least as recent as the hardware,
+ // it is safe to use atomic instructions on armv6 and newer.
+ if (T.getOS() != llvm::Triple::Linux)
+ return false;
+ StringRef ArchName = T.getArchName();
+ if (T.getArch() == llvm::Triple::arm) {
+ if (!ArchName.startswith("armv"))
+ return false;
+ StringRef VersionStr = ArchName.substr(4);
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 6;
+ }
+ assert(T.getArch() == llvm::Triple::thumb);
+ if (!ArchName.startswith("thumbv"))
+ return false;
+ StringRef VersionStr = ArchName.substr(6);
+ unsigned Version;
+ if (VersionStr.getAsInteger(10, Version))
+ return false;
+ return Version >= 7;
+ }
+
public:
ARMTargetInfo(const std::string &TripleStr)
: TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s"), IsAAPCS(true)
@@ -3534,8 +3587,9 @@ public:
TheCXXABI.set(TargetCXXABI::GenericARM);
// ARM has atomics up to 8 bytes
- // FIXME: Set MaxAtomicInlineWidth if we have the feature v6e
MaxAtomicPromoteWidth = 64;
+ if (shouldUseInlineAtomic(getTriple()))
+ MaxAtomicInlineWidth = 64;
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
@@ -4111,16 +4165,14 @@ const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
namespace {
-class SparcV8TargetInfo : public TargetInfo {
+// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
+class SparcTargetInfo : public TargetInfo {
static const TargetInfo::GCCRegAlias GCCRegAliases[];
static const char * const GCCRegNames[];
bool SoftFloat;
public:
- SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) {
- // FIXME: Support Sparc quad-precision long double?
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32";
- }
+ SparcTargetInfo(const std::string &triple) : TargetInfo(triple) {}
+
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
@@ -4140,7 +4192,6 @@ public:
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
DefineStd(Builder, "sparc", Opts);
- Builder.defineMacro("__sparcv8");
Builder.defineMacro("__REGISTER_PREFIX__", "");
if (SoftFloat)
@@ -4176,20 +4227,20 @@ public:
}
};
-const char * const SparcV8TargetInfo::GCCRegNames[] = {
+const char * const SparcTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
};
-void SparcV8TargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
+void SparcTargetInfo::getGCCRegNames(const char * const *&Names,
+ unsigned &NumNames) const {
Names = GCCRegNames;
NumNames = llvm::array_lengthof(GCCRegNames);
}
-const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = {
+const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
{ { "g0" }, "r0" },
{ { "g1" }, "r1" },
{ { "g2" }, "r2" },
@@ -4224,11 +4275,53 @@ const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = {
{ { "i7" }, "r31" },
};
-void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
+void SparcTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
Aliases = GCCRegAliases;
NumAliases = llvm::array_lengthof(GCCRegAliases);
}
+
+// SPARC v8 is the 32-bit mode selected by Triple::sparc.
+class SparcV8TargetInfo : public SparcTargetInfo {
+public:
+ SparcV8TargetInfo(const std::string& triple) : SparcTargetInfo(triple) {
+ // FIXME: Support Sparc quad-precision long double?
+ DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__sparcv8");
+ }
+};
+
+// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
+class SparcV9TargetInfo : public SparcTargetInfo {
+public:
+ SparcV9TargetInfo(const std::string& triple) : SparcTargetInfo(triple) {
+ // FIXME: Support Sparc quad-precision long double?
+ DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32:64-S128";
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ SparcTargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("__sparcv9");
+ Builder.defineMacro("__arch64__");
+ // Solaris and its derivative AuroraUX don't need these variants, but the
+ // BSDs do.
+ if (getTriple().getOS() != llvm::Triple::Solaris &&
+ getTriple().getOS() != llvm::Triple::AuroraUX) {
+ Builder.defineMacro("__sparc64__");
+ Builder.defineMacro("__sparc_v9__");
+ Builder.defineMacro("__sparcv9__");
+ }
+ }
+};
+
} // end anonymous namespace.
namespace {
@@ -4251,6 +4344,100 @@ public:
} // end anonymous namespace.
namespace {
+ class SystemZTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+
+ public:
+ SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) {
+ TLSSupported = true;
+ IntWidth = IntAlign = 32;
+ LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
+ PointerWidth = PointerAlign = 64;
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ MinGlobalAlign = 16;
+ DescriptionString = "E-p:64:64:64-i1:8:16-i8:8:16-i16:16-i32:32-i64:64"
+ "-f32:32-f64:64-f128:64-a0:8:16-n32:64";
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ }
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ Builder.defineMacro("__s390__");
+ Builder.defineMacro("__s390x__");
+ Builder.defineMacro("__zarch__");
+ Builder.defineMacro("__LONG_DOUBLE_128__");
+ }
+ virtual void getTargetBuiltins(const Builtin::Info *&Records,
+ unsigned &NumRecords) const {
+ // FIXME: Implement.
+ Records = 0;
+ NumRecords = 0;
+ }
+
+ virtual void getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const;
+ virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
+ unsigned &NumAliases) const {
+ // No aliases.
+ Aliases = 0;
+ NumAliases = 0;
+ }
+ virtual bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const;
+ virtual const char *getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+ }
+ virtual BuiltinVaListKind getBuiltinVaListKind() const {
+ return TargetInfo::SystemZBuiltinVaList;
+ }
+ };
+
+ const char *const SystemZTargetInfo::GCCRegNames[] = {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "f0", "f2", "f4", "f6", "f1", "f3", "f5", "f7",
+ "f8", "f10", "f12", "f14", "f9", "f11", "f13", "f15"
+ };
+
+ void SystemZTargetInfo::getGCCRegNames(const char *const *&Names,
+ unsigned &NumNames) const {
+ Names = GCCRegNames;
+ NumNames = llvm::array_lengthof(GCCRegNames);
+ }
+
+ bool SystemZTargetInfo::
+ validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &Info) const {
+ switch (*Name) {
+ default:
+ return false;
+
+ case 'a': // Address register
+ case 'd': // Data register (equivalent to 'r')
+ case 'f': // Floating-point register
+ Info.setAllowsRegister();
+ return true;
+
+ case 'I': // Unsigned 8-bit constant
+ case 'J': // Unsigned 12-bit constant
+ case 'K': // Signed 16-bit constant
+ case 'L': // Signed 20-bit displacement (on all targets we support)
+ case 'M': // 0x7fffffff
+ return true;
+
+ case 'Q': // Memory with base and unsigned 12-bit displacement
+ case 'R': // Likewise, plus an index
+ case 'S': // Memory with base and signed 20-bit displacement
+ case 'T': // Likewise, plus an index
+ Info.setAllowsMemory();
+ return true;
+ }
+ }
+}
+
+namespace {
class MSP430TargetInfo : public TargetInfo {
static const char * const GCCRegNames[];
public:
@@ -4405,8 +4592,10 @@ class MipsTargetInfoBase : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
std::string CPU;
bool IsMips16;
+ bool IsMicromips;
+ bool IsSingleFloat;
enum MipsFloatABI {
- HardFloat, SingleFloat, SoftFloat
+ HardFloat, SoftFloat
} FloatABI;
enum DspRevEnum {
NoDSP, DSP1, DSP2
@@ -4422,6 +4611,8 @@ public:
: TargetInfo(triple),
CPU(CPUStr),
IsMips16(false),
+ IsMicromips(false),
+ IsSingleFloat(false),
FloatABI(HardFloat),
DspRev(NoDSP),
ABI(ABIStr)
@@ -4448,18 +4639,20 @@ public:
case HardFloat:
Builder.defineMacro("__mips_hard_float", Twine(1));
break;
- case SingleFloat:
- Builder.defineMacro("__mips_hard_float", Twine(1));
- Builder.defineMacro("__mips_single_float", Twine(1));
- break;
case SoftFloat:
Builder.defineMacro("__mips_soft_float", Twine(1));
break;
}
+ if (IsSingleFloat)
+ Builder.defineMacro("__mips_single_float", Twine(1));
+
if (IsMips16)
Builder.defineMacro("__mips16", Twine(1));
+ if (IsMicromips)
+ Builder.defineMacro("__mips_micromips", Twine(1));
+
switch (DspRev) {
default:
break;
@@ -4549,7 +4742,8 @@ public:
Name == "o32" || Name == "n32" || Name == "n64" || Name == "eabi" ||
Name == "mips32" || Name == "mips32r2" ||
Name == "mips64" || Name == "mips64r2" ||
- Name == "mips16" || Name == "dsp" || Name == "dspr2") {
+ Name == "mips16" || Name == "micromips" ||
+ Name == "dsp" || Name == "dspr2") {
Features[Name] = Enabled;
return true;
} else if (Name == "32") {
@@ -4564,17 +4758,21 @@ public:
virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
IsMips16 = false;
+ IsMicromips = false;
+ IsSingleFloat = false;
FloatABI = HardFloat;
DspRev = NoDSP;
for (std::vector<std::string>::iterator it = Features.begin(),
ie = Features.end(); it != ie; ++it) {
if (*it == "+single-float")
- FloatABI = SingleFloat;
+ IsSingleFloat = true;
else if (*it == "+soft-float")
FloatABI = SoftFloat;
else if (*it == "+mips16")
IsMips16 = true;
+ else if (*it == "+micromips")
+ IsMicromips = true;
else if (*it == "+dsp")
DspRev = std::max(DspRev, DSP1);
else if (*it == "+dspr2")
@@ -4862,7 +5060,7 @@ public:
this->SizeType = TargetInfo::UnsignedInt;
this->PtrDiffType = TargetInfo::SignedInt;
this->IntPtrType = TargetInfo::SignedInt;
- this->RegParmMax = 2;
+ this->RegParmMax = 0; // Disallow regparm
DescriptionString = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"
"f32:32:32-f64:64:64-p:32:32:32-v128:32:32";
}
@@ -5188,6 +5386,32 @@ static TargetInfo *AllocateTarget(const std::string &T) {
return new SparcV8TargetInfo(T);
}
+ case llvm::Triple::sparcv9:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SparcV9TargetInfo>(T);
+ case llvm::Triple::AuroraUX:
+ return new AuroraUXTargetInfo<SparcV9TargetInfo>(T);
+ case llvm::Triple::Solaris:
+ return new SolarisTargetInfo<SparcV9TargetInfo>(T);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<SparcV9TargetInfo>(T);
+ case llvm::Triple::OpenBSD:
+ return new OpenBSDTargetInfo<SparcV9TargetInfo>(T);
+ case llvm::Triple::FreeBSD:
+ return new FreeBSDTargetInfo<SparcV9TargetInfo>(T);
+ default:
+ return new SparcV9TargetInfo(T);
+ }
+
+ case llvm::Triple::systemz:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<SystemZTargetInfo>(T);
+ default:
+ return new SystemZTargetInfo(T);
+ }
+
case llvm::Triple::tce:
return new TCETargetInfo(T);
OpenPOWER on IntegriCloud