diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Basic/Targets.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/Targets.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Targets.cpp | 2173 |
1 files changed, 1240 insertions, 933 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index f7c8c9c..bccd0d7 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -73,7 +73,7 @@ protected: virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const=0; public: - OSTargetInfo(const std::string& triple) : TgtInfo(triple) {} + OSTargetInfo(const llvm::Triple &Triple) : TgtInfo(Triple) {} virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { TgtInfo::getTargetDefines(Opts, Builder); @@ -88,7 +88,7 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, const llvm::Triple &Triple, StringRef &PlatformName, VersionTuple &PlatformMinVersion) { - Builder.defineMacro("__APPLE_CC__", "5621"); + Builder.defineMacro("__APPLE_CC__", "6000"); Builder.defineMacro("__APPLE__"); Builder.defineMacro("__MACH__"); Builder.defineMacro("OBJC_NEW_PROPERTIES"); @@ -138,31 +138,37 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, return; } - // Set the appropriate OS version define. - if (Triple.getOS() == llvm::Triple::IOS) { - assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); - char Str[6]; - Str[0] = '0' + Maj; - Str[1] = '0' + (Min / 10); - Str[2] = '0' + (Min % 10); - Str[3] = '0' + (Rev / 10); - Str[4] = '0' + (Rev % 10); - Str[5] = '\0'; - Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str); - } else { - // Note that the Driver allows versions which aren't representable in the - // define (because we only get a single digit for the minor and micro - // revision numbers). So, we limit them to the maximum representable - // version. - assert(Triple.getEnvironmentName().empty() && "Invalid environment!"); - assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); - char Str[5]; - Str[0] = '0' + (Maj / 10); - Str[1] = '0' + (Maj % 10); - Str[2] = '0' + std::min(Min, 9U); - Str[3] = '0' + std::min(Rev, 9U); - Str[4] = '\0'; - Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); + // If there's an environment specified in the triple, that means we're dealing + // with an embedded variant of some sort and don't want the platform + // version-min defines, so only add them if there's not one. + if (Triple.getEnvironmentName().empty()) { + // Set the appropriate OS version define. + if (Triple.isiOS()) { + assert(Maj < 10 && Min < 100 && Rev < 100 && "Invalid version!"); + char Str[6]; + Str[0] = '0' + Maj; + Str[1] = '0' + (Min / 10); + Str[2] = '0' + (Min % 10); + Str[3] = '0' + (Rev / 10); + Str[4] = '0' + (Rev % 10); + Str[5] = '\0'; + Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", + Str); + } else { + // Note that the Driver allows versions which aren't representable in the + // define (because we only get a single digit for the minor and micro + // revision numbers). So, we limit them to the maximum representable + // version. + assert(Triple.getEnvironmentName().empty() && "Invalid environment!"); + assert(Maj < 100 && Min < 100 && Rev < 100 && "Invalid version!"); + char Str[5]; + Str[0] = '0' + (Maj / 10); + Str[1] = '0' + (Maj % 10); + Str[2] = '0' + std::min(Min, 9U); + Str[3] = '0' + std::min(Rev, 9U); + Str[4] = '\0'; + Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str); + } } PlatformMinVersion = VersionTuple(Maj, Min, Rev); @@ -179,12 +185,10 @@ protected: } public: - DarwinTargetInfo(const std::string& triple) : - OSTargetInfo<Target>(triple) { - llvm::Triple T = llvm::Triple(triple); - this->TLSSupported = T.isMacOSX() && !T.isMacOSXVersionLT(10,7); - this->MCountName = "\01mcount"; - } + DarwinTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->TLSSupported = Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 7); + this->MCountName = "\01mcount"; + } virtual std::string isValidSectionSpecifier(StringRef SR) const { // Let MCSectionMachO validate this. @@ -224,18 +228,17 @@ protected: DefineStd(Builder, "unix", Opts); } public: - DragonFlyBSDTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; + DragonFlyBSDTargetInfo(const llvm::Triple &Triple) + : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; - llvm::Triple Triple(triple); - switch (Triple.getArch()) { - default: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - this->MCountName = ".mcount"; - break; - } + switch (Triple.getArch()) { + default: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + this->MCountName = ".mcount"; + break; + } } }; @@ -256,31 +259,57 @@ protected: Builder.defineMacro("__KPRINTF_ATTRIBUTE__"); DefineStd(Builder, "unix", Opts); Builder.defineMacro("__ELF__"); + + // On FreeBSD, wchar_t contains the number of the code point as + // used by the character set of the locale. These character sets are + // not necessarily a superset of ASCII. + Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1"); } public: - FreeBSDTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - - llvm::Triple Triple(triple); - switch (Triple.getArch()) { - default: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - this->MCountName = ".mcount"; - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - this->MCountName = "_mcount"; - break; - case llvm::Triple::arm: - this->MCountName = "__mcount"; - break; - } + FreeBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + switch (Triple.getArch()) { + default: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + this->MCountName = ".mcount"; + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + this->MCountName = "_mcount"; + break; + case llvm::Triple::arm: + this->MCountName = "__mcount"; + break; } + } +}; + +// GNU/kFreeBSD Target +template<typename Target> +class KFreeBSDTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const { + // GNU/kFreeBSD defines; list based off of gcc output + + DefineStd(Builder, "unix", Opts); + Builder.defineMacro("__FreeBSD_kernel__"); + Builder.defineMacro("__GLIBC__"); + Builder.defineMacro("__ELF__"); + if (Opts.POSIXThreads) + Builder.defineMacro("_REENTRANT"); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + } +public: + KFreeBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + } }; // Minix Target @@ -302,10 +331,9 @@ protected: DefineStd(Builder, "unix", Opts); } public: - MinixTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - } + MinixTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + } }; // Linux target @@ -327,8 +355,7 @@ protected: Builder.defineMacro("_GNU_SOURCE"); } public: - LinuxTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + LinuxTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; this->WIntType = TargetInfo::UnsignedInt; } @@ -352,10 +379,9 @@ protected: Builder.defineMacro("_POSIX_THREADS"); } public: - NetBSDTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - } + NetBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + } }; // OpenBSD Target @@ -373,12 +399,10 @@ protected: Builder.defineMacro("_REENTRANT"); } public: - OpenBSDTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - this->TLSSupported = false; + OpenBSDTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + this->TLSSupported = false; - llvm::Triple Triple(triple); switch (Triple.getArch()) { default: case llvm::Triple::x86: @@ -412,11 +436,10 @@ protected: Builder.defineMacro("_REENTRANT"); } public: - BitrigTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - this->TLSSupported = false; - this->MCountName = "__mcount"; + BitrigTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + this->TLSSupported = false; + this->MCountName = "__mcount"; } }; @@ -433,8 +456,7 @@ protected: Builder.defineMacro("__ELF__"); } public: - PSPTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; } }; @@ -455,8 +477,7 @@ protected: Builder.defineMacro("__powerpc64__"); } public: - PS3PPUTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + PS3PPUTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; this->LongWidth = this->LongAlign = 32; this->PointerWidth = this->PointerAlign = 32; @@ -481,8 +502,7 @@ protected: Builder.defineMacro("__ELF__"); } public: - PS3SPUTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + PS3SPUTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; } }; @@ -500,8 +520,8 @@ protected: Builder.defineMacro("__SVR4"); } public: - AuroraUXTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + AuroraUXTargetInfo(const llvm::Triple &Triple) + : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; this->WCharType = this->SignedLong; // FIXME: WIntType should be SignedLong @@ -535,8 +555,7 @@ protected: Builder.defineMacro("_REENTRANT"); } public: - SolarisTargetInfo(const std::string& triple) - : OSTargetInfo<Target>(triple) { + SolarisTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; this->WCharType = this->SignedInt; // FIXME: WIntType should be SignedLong @@ -586,13 +605,13 @@ protected: } public: - WindowsTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) {} + WindowsTargetInfo(const llvm::Triple &Triple) + : OSTargetInfo<Target>(Triple) {} }; template <typename Target> class NaClTargetInfo : public OSTargetInfo<Target> { - protected: +protected: virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const { if (Opts.POSIXThreads) @@ -604,9 +623,9 @@ class NaClTargetInfo : public OSTargetInfo<Target> { Builder.defineMacro("__ELF__"); Builder.defineMacro("__native_client__"); } - public: - NaClTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { + +public: + NaClTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { this->UserLabelPrefix = ""; this->LongAlign = 32; this->LongWidth = 32; @@ -645,8 +664,14 @@ class PPCTargetInfo : public TargetInfo { static const char * const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; std::string CPU; + + // Target cpu features. + bool HasVSX; + public: - PPCTargetInfo(const std::string& triple) : TargetInfo(triple) { + PPCTargetInfo(const llvm::Triple &Triple) + : TargetInfo(Triple), HasVSX(false) { + BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble; } @@ -718,6 +743,8 @@ public: .Case("ppc", true) .Case("powerpc64", true) .Case("ppc64", true) + .Case("powerpc64le", true) + .Case("ppc64le", true) .Default(false); if (CPUKnown) @@ -739,10 +766,8 @@ public: virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const; - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const; - + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags); virtual bool hasFeature(StringRef Feature) const; virtual void getGCCRegNames(const char * const *&Names, @@ -864,6 +889,29 @@ const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { #include "clang/Basic/BuiltinsPPC.def" }; + /// handleTargetFeatures - Perform initialization based on the user +/// configured set of features. +bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { + // Remember the maximum enabled sselevel. + for (unsigned i = 0, e = Features.size(); i !=e; ++i) { + // Ignore disabled features. + if (Features[i][0] == '-') + continue; + + StringRef Feature = StringRef(Features[i]).substr(1); + + if (Feature == "vsx") { + HasVSX = true; + continue; + } + + // TODO: Finish this list and add an assert that we've handled them + // all. + } + + return true; +} /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific /// #defines that are not tied to a specific subtarget. @@ -871,6 +919,7 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. Builder.defineMacro("__ppc__"); + Builder.defineMacro("__PPC__"); Builder.defineMacro("_ARCH_PPC"); Builder.defineMacro("__powerpc__"); Builder.defineMacro("__POWERPC__"); @@ -878,22 +927,27 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("_ARCH_PPC64"); Builder.defineMacro("__powerpc64__"); Builder.defineMacro("__ppc64__"); - } else { - Builder.defineMacro("__ppc__"); + Builder.defineMacro("__PPC64__"); } // Target properties. - if (getTriple().getOS() != llvm::Triple::NetBSD && - getTriple().getOS() != llvm::Triple::OpenBSD) - Builder.defineMacro("_BIG_ENDIAN"); - Builder.defineMacro("__BIG_ENDIAN__"); + if (getTriple().getArch() == llvm::Triple::ppc64le) { + Builder.defineMacro("_LITTLE_ENDIAN"); + Builder.defineMacro("__LITTLE_ENDIAN__"); + } else { + if (getTriple().getOS() != llvm::Triple::NetBSD && + getTriple().getOS() != llvm::Triple::OpenBSD) + Builder.defineMacro("_BIG_ENDIAN"); + Builder.defineMacro("__BIG_ENDIAN__"); + } // Subtarget options. Builder.defineMacro("__NATURAL_ALIGNMENT__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); // FIXME: Should be controlled by command line option. - Builder.defineMacro("__LONG_DOUBLE_128__"); + if (LongDoubleWidth == 128) + Builder.defineMacro("__LONG_DOUBLE_128__"); if (Opts.AltiVec) { Builder.defineMacro("__VEC__", "10206"); @@ -988,13 +1042,15 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__TOS_BGQ__"); } + if (HasVSX) + Builder.defineMacro("__VSX__"); + // FIXME: The following are not yet generated here by Clang, but are // generated by GCC: // // _SOFT_FLOAT_ // __RECIP_PRECISION__ // __APPLE_ALTIVEC__ - // __VSX__ // __RECIP__ // __RECIPF__ // __RSQRTE__ @@ -1021,23 +1077,12 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { .Case("pwr6", true) .Case("pwr7", true) .Case("ppc64", true) + .Case("ppc64le", true) .Default(false); Features["qpx"] = (CPU == "a2q"); } -bool PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - if (Name == "altivec" || Name == "fprnd" || Name == "mfocrf" || - Name == "popcntd" || Name == "qpx") { - Features[Name] = Enabled; - return true; - } - - return false; -} - bool PPCTargetInfo::hasFeature(StringRef Feature) const { return Feature == "powerpc"; } @@ -1150,7 +1195,7 @@ void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, namespace { class PPC32TargetInfo : public PPCTargetInfo { public: - PPC32TargetInfo(const std::string &triple) : PPCTargetInfo(triple) { + PPC32TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) { 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-v128:128:128-n32"; @@ -1182,10 +1227,12 @@ public: }; } // end anonymous namespace. +// Note: ABI differences may eventually require us to have a separate +// TargetInfo for little endian. namespace { class PPC64TargetInfo : public PPCTargetInfo { public: - PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) { + PPC64TargetInfo(const llvm::Triple &Triple) : PPCTargetInfo(Triple) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = SignedLong; UIntMaxType = UnsignedLong; @@ -1195,7 +1242,7 @@ public: LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; 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-f128:64:64-" + "i64:64:64-f32:32:32-f64:64:64-" "v128:128:128-n32:64"; } else DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" @@ -1216,10 +1263,11 @@ namespace { class DarwinPPC32TargetInfo : public DarwinTargetInfo<PPC32TargetInfo> { public: - DarwinPPC32TargetInfo(const std::string& triple) - : DarwinTargetInfo<PPC32TargetInfo>(triple) { + DarwinPPC32TargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<PPC32TargetInfo>(Triple) { HasAlignMac68kSupport = true; BoolWidth = BoolAlign = 32; //XXX support -mone-byte-bool? + PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726 LongLongAlign = 32; SuitableAlign = 128; DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" @@ -1233,8 +1281,8 @@ public: class DarwinPPC64TargetInfo : public DarwinTargetInfo<PPC64TargetInfo> { public: - DarwinPPC64TargetInfo(const std::string& triple) - : DarwinTargetInfo<PPC64TargetInfo>(triple) { + DarwinPPC64TargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<PPC64TargetInfo>(Triple) { HasAlignMac68kSupport = true; SuitableAlign = 128; DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" @@ -1255,13 +1303,13 @@ namespace { class NVPTXTargetInfo : public TargetInfo { static const char * const GCCRegNames[]; static const Builtin::Info BuiltinInfo[]; - std::vector<StringRef> AvailableFeatures; public: - NVPTXTargetInfo(const std::string& triple) : TargetInfo(triple) { + NVPTXTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; TLSSupported = false; LongWidth = LongAlign = 64; AddrSpaceMap = &NVPTXAddrSpaceMap; + UseAddrSpaceMapMangling = true; // Define available target features // These must be defined in sorted order! NoAsmVariants = true; @@ -1289,9 +1337,18 @@ namespace { NumAliases = 0; } virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &info) const { - // FIXME: implement - return true; + TargetInfo::ConstraintInfo &Info) const { + switch (*Name) { + default: return false; + case 'c': + case 'h': + case 'r': + case 'l': + case 'f': + case 'd': + Info.setAllowsRegister(); + return true; + } } virtual const char *getClobbers() const { // FIXME: Is this really right? @@ -1311,9 +1368,6 @@ namespace { return Valid; } - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const; }; const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = { @@ -1333,21 +1387,9 @@ namespace { NumNames = llvm::array_lengthof(GCCRegNames); } - bool NVPTXTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - if(std::binary_search(AvailableFeatures.begin(), AvailableFeatures.end(), - Name)) { - Features[Name] = Enabled; - return true; - } else { - return false; - } - } - class NVPTX32TargetInfo : public NVPTXTargetInfo { public: - NVPTX32TargetInfo(const std::string& triple) : NVPTXTargetInfo(triple) { + NVPTX32TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) { PointerWidth = PointerAlign = 32; SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedInt; DescriptionString @@ -1359,7 +1401,7 @@ namespace { class NVPTX64TargetInfo : public NVPTXTargetInfo { public: - NVPTX64TargetInfo(const std::string& triple) : NVPTXTargetInfo(triple) { + NVPTX64TargetInfo(const llvm::Triple &Triple) : NVPTXTargetInfo(Triple) { PointerWidth = PointerAlign = 64; SizeType = PtrDiffType = IntPtrType = TargetInfo::UnsignedLongLong; DescriptionString @@ -1400,6 +1442,7 @@ static const char *DescriptionStringR600DoubleOps = static const char *DescriptionStringSI = "e" "-p:64:64:64" + "-p3:32:32:32" "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64" "-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128" "-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-v2048:2048:2048" @@ -1417,15 +1460,16 @@ class R600TargetInfo : public TargetInfo { GK_EVERGREEN_DOUBLE_OPS, GK_NORTHERN_ISLANDS, GK_CAYMAN, - GK_SOUTHERN_ISLANDS + GK_SOUTHERN_ISLANDS, + GK_SEA_ISLANDS } GPU; public: - R600TargetInfo(const std::string& triple) - : TargetInfo(triple), - GPU(GK_R600) { + R600TargetInfo(const llvm::Triple &Triple) + : TargetInfo(Triple), GPU(GK_R600) { DescriptionString = DescriptionStringR600; AddrSpaceMap = &R600AddrSpaceMap; + UseAddrSpaceMapMangling = true; } virtual const char * getClobbers() const { @@ -1496,6 +1540,10 @@ public: .Case("pitcairn", GK_SOUTHERN_ISLANDS) .Case("verde", GK_SOUTHERN_ISLANDS) .Case("oland", GK_SOUTHERN_ISLANDS) + .Case("bonaire", GK_SEA_ISLANDS) + .Case("kabini", GK_SEA_ISLANDS) + .Case("kaveri", GK_SEA_ISLANDS) + .Case("hawaii", GK_SEA_ISLANDS) .Default(GK_NONE); if (GPU == GK_NONE) { @@ -1518,6 +1566,7 @@ public: DescriptionString = DescriptionStringR600DoubleOps; break; case GK_SOUTHERN_ISLANDS: + case GK_SEA_ISLANDS: DescriptionString = DescriptionStringSI; break; } @@ -1529,137 +1578,6 @@ public: } // end anonymous namespace namespace { -// MBlaze abstract base class -class MBlazeTargetInfo : public TargetInfo { - static const char * const GCCRegNames[]; - static const TargetInfo::GCCRegAlias GCCRegAliases[]; - -public: - MBlazeTargetInfo(const std::string& triple) : TargetInfo(triple) { - DescriptionString = "E-p:32:32:32-i8:8:8-i16:16:16"; - } - - virtual void getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords) const { - // FIXME: Implement. - Records = 0; - NumRecords = 0; - } - - virtual void getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const; - - virtual bool hasFeature(StringRef Feature) const { - return Feature == "mblaze"; - } - - virtual BuiltinVaListKind getBuiltinVaListKind() const { - return TargetInfo::CharPtrBuiltinVaList; - } - virtual const char *getTargetPrefix() const { - return "mblaze"; - } - virtual void getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const; - virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const; - virtual bool validateAsmConstraint(const char *&Name, - TargetInfo::ConstraintInfo &Info) const { - switch (*Name) { - default: return false; - case 'O': // Zero - return true; - case 'b': // Base register - case 'f': // Floating point register - Info.setAllowsRegister(); - return true; - } - } - virtual const char *getClobbers() const { - return ""; - } -}; - -/// MBlazeTargetInfo::getTargetDefines - Return a set of the MBlaze-specific -/// #defines that are not tied to a specific subtarget. -void MBlazeTargetInfo::getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { - // Target identification. - Builder.defineMacro("__microblaze__"); - Builder.defineMacro("_ARCH_MICROBLAZE"); - Builder.defineMacro("__MICROBLAZE__"); - - // Target properties. - Builder.defineMacro("_BIG_ENDIAN"); - Builder.defineMacro("__BIG_ENDIAN__"); - - // Subtarget options. - Builder.defineMacro("__REGISTER_PREFIX__", ""); -} - - -const char * const MBlazeTargetInfo::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", - "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", - "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", - "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", - "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", - "hi", "lo", "accum","rmsr", "$fcc1","$fcc2","$fcc3","$fcc4", - "$fcc5","$fcc6","$fcc7","$ap", "$rap", "$frp" -}; - -void MBlazeTargetInfo::getGCCRegNames(const char * const *&Names, - unsigned &NumNames) const { - Names = GCCRegNames; - NumNames = llvm::array_lengthof(GCCRegNames); -} - -const TargetInfo::GCCRegAlias MBlazeTargetInfo::GCCRegAliases[] = { - { {"f0"}, "r0" }, - { {"f1"}, "r1" }, - { {"f2"}, "r2" }, - { {"f3"}, "r3" }, - { {"f4"}, "r4" }, - { {"f5"}, "r5" }, - { {"f6"}, "r6" }, - { {"f7"}, "r7" }, - { {"f8"}, "r8" }, - { {"f9"}, "r9" }, - { {"f10"}, "r10" }, - { {"f11"}, "r11" }, - { {"f12"}, "r12" }, - { {"f13"}, "r13" }, - { {"f14"}, "r14" }, - { {"f15"}, "r15" }, - { {"f16"}, "r16" }, - { {"f17"}, "r17" }, - { {"f18"}, "r18" }, - { {"f19"}, "r19" }, - { {"f20"}, "r20" }, - { {"f21"}, "r21" }, - { {"f22"}, "r22" }, - { {"f23"}, "r23" }, - { {"f24"}, "r24" }, - { {"f25"}, "r25" }, - { {"f26"}, "r26" }, - { {"f27"}, "r27" }, - { {"f28"}, "r28" }, - { {"f29"}, "r29" }, - { {"f30"}, "r30" }, - { {"f31"}, "r31" }, -}; - -void MBlazeTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, - unsigned &NumAliases) const { - Aliases = GCCRegAliases; - NumAliases = llvm::array_lengthof(GCCRegAliases); -} -} // end anonymous namespace. - -namespace { // Namespace for x86 abstract base class const Builtin::Info BuiltinInfo[] = { #define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, ALL_LANGUAGES }, @@ -1695,11 +1613,17 @@ const TargetInfo::AddlRegName AddlRegNames[] = { // most of the implementation can be shared. class X86TargetInfo : public TargetInfo { enum X86SSEEnum { - NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2 + NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F } SSELevel; enum MMX3DNowEnum { NoMMX3DNow, MMX, AMD3DNow, AMD3DNowAthlon } MMX3DNowLevel; + enum XOPEnum { + NoXOP, + SSE4A, + FMA4, + XOP + } XOPLevel; bool HasAES; bool HasPCLMUL; @@ -1711,11 +1635,12 @@ class X86TargetInfo : public TargetInfo { bool HasRTM; bool HasPRFCHW; bool HasRDSEED; - bool HasSSE4a; - bool HasFMA4; + bool HasTBM; bool HasFMA; - bool HasXOP; bool HasF16C; + bool HasAVX512CD, HasAVX512ER, HasAVX512PF; + bool HasSHA; + bool HasCX16; /// \brief Enumeration of all of the X86 CPUs supported by Clang. /// @@ -1789,6 +1714,7 @@ class X86TargetInfo : public TargetInfo { /// Atom processors //@{ CK_Atom, + CK_Silvermont, //@} /// \name Nehalem @@ -1800,6 +1726,10 @@ class X86TargetInfo : public TargetInfo { CK_CoreAVX2, //@} + /// \name Knights Landing + /// Knights Landing processor. + CK_KNL, + /// \name K6 /// K6 architecture processors. //@{ @@ -1843,6 +1773,7 @@ class X86TargetInfo : public TargetInfo { //@{ CK_BDVER1, CK_BDVER2, + CK_BDVER3, //@} /// This specification is deprecated and will be removed in the future. @@ -1858,13 +1789,21 @@ class X86TargetInfo : public TargetInfo { //@} } CPU; + enum FPMathKind { + FP_Default, + FP_SSE, + FP_387 + } FPMath; + public: - X86TargetInfo(const std::string& triple) - : TargetInfo(triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), - HasAES(false), HasPCLMUL(false), HasLZCNT(false), HasRDRND(false), - HasBMI(false), HasBMI2(false), HasPOPCNT(false), HasRTM(false), - HasPRFCHW(false), HasRDSEED(false), HasSSE4a(false), HasFMA4(false), - HasFMA(false), HasXOP(false), HasF16C(false), CPU(CK_Generic) { + X86TargetInfo(const llvm::Triple &Triple) + : TargetInfo(Triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow), + XOPLevel(NoXOP), HasAES(false), HasPCLMUL(false), HasLZCNT(false), + HasRDRND(false), HasBMI(false), HasBMI2(false), HasPOPCNT(false), + HasRTM(false), HasPRFCHW(false), HasRDSEED(false), HasTBM(false), + HasFMA(false), HasF16C(false), HasAVX512CD(false), HasAVX512ER(false), + HasAVX512PF(false), HasSHA(false), HasCX16(false), CPU(CK_Generic), + FPMath(FP_Default) { BigEndian = false; LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } @@ -1900,12 +1839,24 @@ public: } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const; - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const; + static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level, + bool Enabled); + static void setMMXLevel(llvm::StringMap<bool> &Features, MMX3DNowEnum Level, + bool Enabled); + static void setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level, + bool Enabled); + virtual void setFeatureEnabled(llvm::StringMap<bool> &Features, + StringRef Name, bool Enabled) const { + setFeatureEnabledImpl(Features, Name, Enabled); + } + // This exists purely to cut down on the number of virtual calls in + // getDefaultFeatures which calls this repeatedly. + static void setFeatureEnabledImpl(llvm::StringMap<bool> &Features, + StringRef Name, bool Enabled); virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const; virtual bool hasFeature(StringRef Feature) const; - virtual void HandleTargetFeatures(std::vector<std::string> &Features); + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags); virtual const char* getABI() const { if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX) return "avx"; @@ -1939,10 +1890,12 @@ public: .Case("core2", CK_Core2) .Case("penryn", CK_Penryn) .Case("atom", CK_Atom) + .Case("slm", CK_Silvermont) .Case("corei7", CK_Corei7) .Case("corei7-avx", CK_Corei7AVX) .Case("core-avx-i", CK_CoreAVXi) .Case("core-avx2", CK_CoreAVX2) + .Case("knl", CK_KNL) .Case("k6", CK_K6) .Case("k6-2", CK_K6_2) .Case("k6-3", CK_K6_3) @@ -1963,6 +1916,7 @@ public: .Case("btver2", CK_BTVER2) .Case("bdver1", CK_BDVER1) .Case("bdver2", CK_BDVER2) + .Case("bdver3", CK_BDVER3) .Case("x86-64", CK_x86_64) .Case("geode", CK_Geode) .Default(CK_Generic); @@ -2013,10 +1967,12 @@ public: case CK_Core2: case CK_Penryn: case CK_Atom: + case CK_Silvermont: case CK_Corei7: case CK_Corei7AVX: case CK_CoreAVXi: case CK_CoreAVX2: + case CK_KNL: case CK_Athlon64: case CK_Athlon64SSE3: case CK_AthlonFX: @@ -2029,12 +1985,15 @@ public: case CK_BTVER2: case CK_BDVER1: case CK_BDVER2: + case CK_BDVER3: case CK_x86_64: return true; } llvm_unreachable("Unhandled CPU kind"); } + virtual bool setFPMath(StringRef Name); + virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { // We accept all non-ARM calling conventions return (CC == CC_X86ThisCall || @@ -2050,40 +2009,24 @@ public: } }; -void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { - // FIXME: This should not be here. - Features["3dnow"] = false; - Features["3dnowa"] = false; - Features["mmx"] = false; - Features["sse"] = false; - Features["sse2"] = false; - Features["sse3"] = false; - Features["ssse3"] = false; - Features["sse41"] = false; - Features["sse42"] = false; - Features["sse4a"] = false; - Features["aes"] = false; - Features["pclmul"] = false; - Features["avx"] = false; - Features["avx2"] = false; - Features["lzcnt"] = false; - Features["rdrand"] = false; - Features["bmi"] = false; - Features["bmi2"] = false; - Features["popcnt"] = false; - Features["rtm"] = false; - Features["prfchw"] = false; - Features["rdseed"] = false; - Features["fma4"] = false; - Features["fma"] = false; - Features["xop"] = false; - Features["f16c"] = false; +bool X86TargetInfo::setFPMath(StringRef Name) { + if (Name == "387") { + FPMath = FP_387; + return true; + } + if (Name == "sse") { + FPMath = FP_SSE; + return true; + } + return false; +} +void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { // FIXME: This *really* should not be here. // X86_64 always has SSE2. if (getTriple().getArch() == llvm::Triple::x86_64) - setFeatureEnabled(Features, "sse2", true); + setFeatureEnabledImpl(Features, "sse2", true); switch (CPU) { case CK_Generic: @@ -2096,295 +2039,349 @@ void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { break; case CK_PentiumMMX: case CK_Pentium2: - setFeatureEnabled(Features, "mmx", true); + setFeatureEnabledImpl(Features, "mmx", true); break; case CK_Pentium3: case CK_Pentium3M: - setFeatureEnabled(Features, "sse", true); + setFeatureEnabledImpl(Features, "sse", true); break; case CK_PentiumM: case CK_Pentium4: case CK_Pentium4M: case CK_x86_64: - setFeatureEnabled(Features, "sse2", true); + setFeatureEnabledImpl(Features, "sse2", true); break; case CK_Yonah: case CK_Prescott: case CK_Nocona: - setFeatureEnabled(Features, "sse3", true); + setFeatureEnabledImpl(Features, "sse3", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Core2: - setFeatureEnabled(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Penryn: - setFeatureEnabled(Features, "sse4.1", true); + setFeatureEnabledImpl(Features, "sse4.1", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Atom: - setFeatureEnabled(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "cx16", true); + break; + case CK_Silvermont: + setFeatureEnabledImpl(Features, "sse4.2", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "cx16", true); + setFeatureEnabledImpl(Features, "pclmul", true); break; case CK_Corei7: - setFeatureEnabled(Features, "sse4", true); + setFeatureEnabledImpl(Features, "sse4.2", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_Corei7AVX: - setFeatureEnabled(Features, "avx", true); - setFeatureEnabled(Features, "aes", true); - setFeatureEnabled(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "avx", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "cx16", true); + setFeatureEnabledImpl(Features, "pclmul", true); break; case CK_CoreAVXi: - setFeatureEnabled(Features, "avx", true); - setFeatureEnabled(Features, "aes", true); - setFeatureEnabled(Features, "pclmul", true); - setFeatureEnabled(Features, "rdrnd", true); - setFeatureEnabled(Features, "f16c", true); + setFeatureEnabledImpl(Features, "avx", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "f16c", true); break; case CK_CoreAVX2: - setFeatureEnabled(Features, "avx2", true); - setFeatureEnabled(Features, "aes", true); - setFeatureEnabled(Features, "pclmul", true); - setFeatureEnabled(Features, "lzcnt", true); - setFeatureEnabled(Features, "rdrnd", true); - setFeatureEnabled(Features, "f16c", true); - setFeatureEnabled(Features, "bmi", true); - setFeatureEnabled(Features, "bmi2", true); - setFeatureEnabled(Features, "rtm", true); - setFeatureEnabled(Features, "fma", true); + setFeatureEnabledImpl(Features, "avx2", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "bmi2", true); + setFeatureEnabledImpl(Features, "rtm", true); + setFeatureEnabledImpl(Features, "fma", true); + setFeatureEnabledImpl(Features, "cx16", true); + break; + case CK_KNL: + setFeatureEnabledImpl(Features, "avx512f", true); + setFeatureEnabledImpl(Features, "avx512cd", true); + setFeatureEnabledImpl(Features, "avx512er", true); + setFeatureEnabledImpl(Features, "avx512pf", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "rdrnd", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "bmi2", true); + setFeatureEnabledImpl(Features, "rtm", true); + setFeatureEnabledImpl(Features, "fma", true); break; case CK_K6: case CK_WinChipC6: - setFeatureEnabled(Features, "mmx", true); + setFeatureEnabledImpl(Features, "mmx", true); break; case CK_K6_2: case CK_K6_3: case CK_WinChip2: case CK_C3: - setFeatureEnabled(Features, "3dnow", true); + setFeatureEnabledImpl(Features, "3dnow", true); break; case CK_Athlon: case CK_AthlonThunderbird: case CK_Geode: - setFeatureEnabled(Features, "3dnowa", true); + setFeatureEnabledImpl(Features, "3dnowa", true); break; case CK_Athlon4: case CK_AthlonXP: case CK_AthlonMP: - setFeatureEnabled(Features, "sse", true); - setFeatureEnabled(Features, "3dnowa", true); + setFeatureEnabledImpl(Features, "sse", true); + setFeatureEnabledImpl(Features, "3dnowa", true); break; case CK_K8: case CK_Opteron: case CK_Athlon64: case CK_AthlonFX: - setFeatureEnabled(Features, "sse2", true); - setFeatureEnabled(Features, "3dnowa", true); + setFeatureEnabledImpl(Features, "sse2", true); + setFeatureEnabledImpl(Features, "3dnowa", true); break; case CK_K8SSE3: case CK_OpteronSSE3: case CK_Athlon64SSE3: - setFeatureEnabled(Features, "sse3", true); - setFeatureEnabled(Features, "3dnowa", true); + setFeatureEnabledImpl(Features, "sse3", true); + setFeatureEnabledImpl(Features, "3dnowa", true); break; case CK_AMDFAM10: - setFeatureEnabled(Features, "sse3", true); - setFeatureEnabled(Features, "sse4a", true); - setFeatureEnabled(Features, "3dnowa", true); - setFeatureEnabled(Features, "lzcnt", true); - setFeatureEnabled(Features, "popcnt", true); + setFeatureEnabledImpl(Features, "sse3", true); + setFeatureEnabledImpl(Features, "sse4a", true); + setFeatureEnabledImpl(Features, "3dnowa", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "popcnt", true); break; case CK_BTVER1: - setFeatureEnabled(Features, "ssse3", true); - setFeatureEnabled(Features, "sse4a", true); - setFeatureEnabled(Features, "lzcnt", true); - setFeatureEnabled(Features, "popcnt", true); + setFeatureEnabledImpl(Features, "ssse3", true); + setFeatureEnabledImpl(Features, "sse4a", true); + setFeatureEnabledImpl(Features, "cx16", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "popcnt", true); + setFeatureEnabledImpl(Features, "prfchw", 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); + setFeatureEnabledImpl(Features, "avx", true); + setFeatureEnabledImpl(Features, "sse4a", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "prfchw", true); + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_BDVER1: - setFeatureEnabled(Features, "xop", true); - setFeatureEnabled(Features, "lzcnt", true); - setFeatureEnabled(Features, "aes", true); - setFeatureEnabled(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "xop", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "prfchw", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_BDVER2: - setFeatureEnabled(Features, "xop", true); - setFeatureEnabled(Features, "lzcnt", true); - setFeatureEnabled(Features, "aes", true); - setFeatureEnabled(Features, "pclmul", true); - setFeatureEnabled(Features, "bmi", true); - setFeatureEnabled(Features, "fma", true); - setFeatureEnabled(Features, "f16c", true); + case CK_BDVER3: + setFeatureEnabledImpl(Features, "xop", true); + setFeatureEnabledImpl(Features, "lzcnt", true); + setFeatureEnabledImpl(Features, "aes", true); + setFeatureEnabledImpl(Features, "pclmul", true); + setFeatureEnabledImpl(Features, "prfchw", true); + setFeatureEnabledImpl(Features, "bmi", true); + setFeatureEnabledImpl(Features, "fma", true); + setFeatureEnabledImpl(Features, "f16c", true); + setFeatureEnabledImpl(Features, "tbm", true); + setFeatureEnabledImpl(Features, "cx16", true); break; case CK_C3_2: - setFeatureEnabled(Features, "sse", true); + setFeatureEnabledImpl(Features, "sse", true); break; } } -bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - // FIXME: This *really* should not be here. We need some way of translating - // options into llvm subtarget features. - if (!Features.count(Name) && - (Name != "sse4" && Name != "sse4.2" && Name != "sse4.1" && - Name != "rdrnd")) - return false; +void X86TargetInfo::setSSELevel(llvm::StringMap<bool> &Features, + X86SSEEnum Level, bool Enabled) { + if (Enabled) { + switch (Level) { + case AVX512F: + Features["avx512f"] = true; + case AVX2: + Features["avx2"] = true; + case AVX: + Features["avx"] = true; + case SSE42: + Features["sse4.2"] = true; + case SSE41: + Features["sse4.1"] = true; + case SSSE3: + Features["ssse3"] = true; + case SSE3: + Features["sse3"] = true; + case SSE2: + Features["sse2"] = true; + case SSE1: + Features["sse"] = true; + case NoSSE: + break; + } + return; + } - // FIXME: this should probably use a switch with fall through. + switch (Level) { + case NoSSE: + case SSE1: + Features["sse"] = false; + case SSE2: + Features["sse2"] = Features["pclmul"] = Features["aes"] = + Features["sha"] = false; + case SSE3: + Features["sse3"] = false; + setXOPLevel(Features, NoXOP, false); + case SSSE3: + Features["ssse3"] = false; + case SSE41: + Features["sse4.1"] = false; + case SSE42: + Features["sse4.2"] = false; + case AVX: + Features["fma"] = Features["avx"] = Features["f16c"] = false; + setXOPLevel(Features, FMA4, false); + case AVX2: + Features["avx2"] = false; + case AVX512F: + Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] = + Features["avx512pf"] = false; + } +} +void X86TargetInfo::setMMXLevel(llvm::StringMap<bool> &Features, + MMX3DNowEnum Level, bool Enabled) { if (Enabled) { - if (Name == "mmx") + switch (Level) { + case AMD3DNowAthlon: + Features["3dnowa"] = true; + case AMD3DNow: + Features["3dnow"] = true; + case MMX: Features["mmx"] = true; - else if (Name == "sse") - Features["mmx"] = Features["sse"] = true; - else if (Name == "sse2") - Features["mmx"] = Features["sse"] = Features["sse2"] = true; - else if (Name == "sse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - true; - else if (Name == "ssse3") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = true; - else if (Name == "sse4" || Name == "sse4.2") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = true; - else if (Name == "sse4.1") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = true; - else if (Name == "3dnow") - Features["mmx"] = Features["3dnow"] = true; - else if (Name == "3dnowa") - Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = true; - else if (Name == "aes") - Features["sse"] = Features["sse2"] = Features["aes"] = true; - else if (Name == "pclmul") - Features["sse"] = Features["sse2"] = Features["pclmul"] = true; - else if (Name == "avx") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = Features["avx"] = true; - else if (Name == "avx2") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = Features["avx"] = Features["avx2"] = true; - else if (Name == "fma") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = Features["avx"] = Features["fma"] = true; - else if (Name == "fma4") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = Features["avx"] = Features["sse4a"] = - Features["fma4"] = true; - else if (Name == "xop") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["popcnt"] = Features["avx"] = Features["sse4a"] = - Features["fma4"] = Features["xop"] = true; - else if (Name == "sse4a") - Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["sse4a"] = true; - else if (Name == "lzcnt") - Features["lzcnt"] = true; - else if (Name == "rdrnd") - Features["rdrand"] = true; - else if (Name == "bmi") - Features["bmi"] = true; - else if (Name == "bmi2") - Features["bmi2"] = true; - else if (Name == "popcnt") - Features["popcnt"] = true; - else if (Name == "f16c") - Features["f16c"] = true; - else if (Name == "rtm") - Features["rtm"] = true; - else if (Name == "prfchw") - Features["prfchw"] = true; - else if (Name == "rdseed") - Features["rdseed"] = true; - } else { - if (Name == "mmx") - Features["mmx"] = Features["3dnow"] = Features["3dnowa"] = false; - else if (Name == "sse") - Features["sse"] = Features["sse2"] = Features["sse3"] = - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["sse4a"] = Features["avx"] = Features["avx2"] = - Features["fma"] = Features["fma4"] = Features["aes"] = - Features["pclmul"] = Features["xop"] = false; - else if (Name == "sse2") - Features["sse2"] = Features["sse3"] = Features["ssse3"] = - Features["sse41"] = Features["sse42"] = Features["sse4a"] = - Features["avx"] = Features["avx2"] = Features["fma"] = - Features["fma4"] = Features["aes"] = Features["pclmul"] = - Features["xop"] = false; - else if (Name == "sse3") - Features["sse3"] = Features["ssse3"] = Features["sse41"] = - Features["sse42"] = Features["sse4a"] = Features["avx"] = - Features["avx2"] = Features["fma"] = Features["fma4"] = - Features["xop"] = false; - else if (Name == "ssse3") - Features["ssse3"] = Features["sse41"] = Features["sse42"] = - Features["avx"] = Features["avx2"] = Features["fma"] = false; - else if (Name == "sse4" || Name == "sse4.1") - Features["sse41"] = Features["sse42"] = Features["avx"] = - Features["avx2"] = Features["fma"] = false; - else if (Name == "sse4.2") - Features["sse42"] = Features["avx"] = Features["avx2"] = - Features["fma"] = false; - else if (Name == "3dnow") - Features["3dnow"] = Features["3dnowa"] = false; - else if (Name == "3dnowa") - Features["3dnowa"] = false; - else if (Name == "aes") - Features["aes"] = false; - else if (Name == "pclmul") - Features["pclmul"] = false; - else if (Name == "avx") - Features["avx"] = Features["avx2"] = Features["fma"] = - Features["fma4"] = Features["xop"] = false; - else if (Name == "avx2") - Features["avx2"] = false; - else if (Name == "fma") - Features["fma"] = false; - else if (Name == "sse4a") - Features["sse4a"] = Features["fma4"] = Features["xop"] = false; - else if (Name == "lzcnt") - Features["lzcnt"] = false; - else if (Name == "rdrnd") - Features["rdrand"] = false; - else if (Name == "bmi") - Features["bmi"] = false; - else if (Name == "bmi2") - Features["bmi2"] = false; - else if (Name == "popcnt") - Features["popcnt"] = false; - else if (Name == "fma4") - Features["fma4"] = Features["xop"] = false; - else if (Name == "xop") - Features["xop"] = false; - else if (Name == "f16c") - Features["f16c"] = false; - else if (Name == "rtm") - Features["rtm"] = false; - else if (Name == "prfchw") - Features["prfchw"] = false; - else if (Name == "rdseed") - Features["rdseed"] = false; + case NoMMX3DNow: + break; + } + return; } - return true; + switch (Level) { + case NoMMX3DNow: + case MMX: + Features["mmx"] = false; + case AMD3DNow: + Features["3dnow"] = false; + case AMD3DNowAthlon: + Features["3dnowa"] = false; + } +} + +void X86TargetInfo::setXOPLevel(llvm::StringMap<bool> &Features, XOPEnum Level, + bool Enabled) { + if (Enabled) { + switch (Level) { + case XOP: + Features["xop"] = true; + case FMA4: + Features["fma4"] = true; + setSSELevel(Features, AVX, true); + case SSE4A: + Features["sse4a"] = true; + setSSELevel(Features, SSE3, true); + case NoXOP: + break; + } + return; + } + + switch (Level) { + case NoXOP: + case SSE4A: + Features["sse4a"] = false; + case FMA4: + Features["fma4"] = false; + case XOP: + Features["xop"] = false; + } } -/// HandleTargetOptions - Perform initialization based on the user +void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features, + StringRef Name, bool Enabled) { + // FIXME: This *really* should not be here. We need some way of translating + // options into llvm subtarget features. + if (Name == "sse4") + Name = "sse4.2"; + + Features[Name] = Enabled; + + if (Name == "mmx") { + setMMXLevel(Features, MMX, Enabled); + } else if (Name == "sse") { + setSSELevel(Features, SSE1, Enabled); + } else if (Name == "sse2") { + setSSELevel(Features, SSE2, Enabled); + } else if (Name == "sse3") { + setSSELevel(Features, SSE3, Enabled); + } else if (Name == "ssse3") { + setSSELevel(Features, SSSE3, Enabled); + } else if (Name == "sse4.2") { + setSSELevel(Features, SSE42, Enabled); + } else if (Name == "sse4.1") { + setSSELevel(Features, SSE41, Enabled); + } else if (Name == "3dnow") { + setMMXLevel(Features, AMD3DNow, Enabled); + } else if (Name == "3dnowa") { + setMMXLevel(Features, AMD3DNowAthlon, Enabled); + } else if (Name == "aes") { + if (Enabled) + setSSELevel(Features, SSE2, Enabled); + } else if (Name == "pclmul") { + if (Enabled) + setSSELevel(Features, SSE2, Enabled); + } else if (Name == "avx") { + setSSELevel(Features, AVX, Enabled); + } else if (Name == "avx2") { + setSSELevel(Features, AVX2, Enabled); + } else if (Name == "avx512f") { + setSSELevel(Features, AVX512F, Enabled); + } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf") { + if (Enabled) + setSSELevel(Features, AVX512F, Enabled); + } else if (Name == "fma") { + if (Enabled) + setSSELevel(Features, AVX, Enabled); + } else if (Name == "fma4") { + setXOPLevel(Features, FMA4, Enabled); + } else if (Name == "xop") { + setXOPLevel(Features, XOP, Enabled); + } else if (Name == "sse4a") { + setXOPLevel(Features, SSE4A, Enabled); + } else if (Name == "f16c") { + if (Enabled) + setSSELevel(Features, AVX, Enabled); + } else if (Name == "sha") { + if (Enabled) + setSSELevel(Features, SSE2, Enabled); + } +} + +/// handleTargetFeatures - Perform initialization based on the user /// configured set of features. -void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { +bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { // Remember the maximum enabled sselevel. for (unsigned i = 0, e = Features.size(); i !=e; ++i) { // Ignore disabled features. @@ -2408,7 +2405,7 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { continue; } - if (Feature == "rdrand") { + if (Feature == "rdrnd") { HasRDRND = true; continue; } @@ -2443,37 +2440,53 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { continue; } - if (Feature == "sse4a") { - HasSSE4a = true; + if (Feature == "tbm") { + HasTBM = true; continue; } - if (Feature == "fma4") { - HasFMA4 = true; + if (Feature == "fma") { + HasFMA = true; continue; } - if (Feature == "fma") { - HasFMA = true; + if (Feature == "f16c") { + HasF16C = true; continue; } - if (Feature == "xop") { - HasXOP = true; + if (Feature == "avx512cd") { + HasAVX512CD = true; continue; } - if (Feature == "f16c") { - HasF16C = true; + if (Feature == "avx512er") { + HasAVX512ER = true; + continue; + } + + if (Feature == "avx512pf") { + HasAVX512PF = true; + continue; + } + + if (Feature == "sha") { + HasSHA = true; + continue; + } + + if (Feature == "cx16") { + HasCX16 = true; continue; } assert(Features[i][0] == '+' && "Invalid target feature!"); X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Feature) + .Case("avx512f", AVX512F) .Case("avx2", AVX2) .Case("avx", AVX) - .Case("sse42", SSE42) - .Case("sse41", SSE41) + .Case("sse4.2", SSE42) + .Case("sse4.1", SSE41) .Case("ssse3", SSSE3) .Case("sse3", SSE3) .Case("sse2", SSE2) @@ -2487,16 +2500,53 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) { .Case("3dnow", AMD3DNow) .Case("mmx", MMX) .Default(NoMMX3DNow); - MMX3DNowLevel = std::max(MMX3DNowLevel, ThreeDNowLevel); + + XOPEnum XLevel = llvm::StringSwitch<XOPEnum>(Feature) + .Case("xop", XOP) + .Case("fma4", FMA4) + .Case("sse4a", SSE4A) + .Default(NoXOP); + XOPLevel = std::max(XOPLevel, XLevel); + } + + // Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled. + // Can't do this earlier because we need to be able to explicitly enable + // popcnt and still disable sse4.2. + if (!HasPOPCNT && SSELevel >= SSE42 && + std::find(Features.begin(), Features.end(), "-popcnt") == Features.end()){ + HasPOPCNT = true; + Features.push_back("+popcnt"); + } + + // Enable prfchw if 3DNow! is enabled and prfchw is not explicitly disabled. + if (!HasPRFCHW && MMX3DNowLevel >= AMD3DNow && + std::find(Features.begin(), Features.end(), "-prfchw") == Features.end()){ + HasPRFCHW = true; + Features.push_back("+prfchw"); + } + + // LLVM doesn't have a separate switch for fpmath, so only accept it if it + // matches the selected sse level. + if (FPMath == FP_SSE && SSELevel < SSE1) { + Diags.Report(diag::err_target_unsupported_fpmath) << "sse"; + return false; + } else if (FPMath == FP_387 && SSELevel >= SSE1) { + Diags.Report(diag::err_target_unsupported_fpmath) << "387"; + return false; } // Don't tell the backend if we're turning off mmx; it will end up disabling // SSE, which we don't want. + // Additionally, if SSE is enabled and mmx is not explicitly disabled, + // then enable MMX. std::vector<std::string>::iterator it; it = std::find(Features.begin(), Features.end(), "-mmx"); if (it != Features.end()) Features.erase(it); + else if (SSELevel > NoSSE) + MMX3DNowLevel = std::max(MMX3DNowLevel, MMX); + return true; } /// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro @@ -2574,12 +2624,18 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_Atom: defineCPUMacros(Builder, "atom"); break; + case CK_Silvermont: + defineCPUMacros(Builder, "slm"); + break; case CK_Corei7: case CK_Corei7AVX: case CK_CoreAVXi: case CK_CoreAVX2: defineCPUMacros(Builder, "corei7"); break; + case CK_KNL: + defineCPUMacros(Builder, "knl"); + break; case CK_K6_2: Builder.defineMacro("__k6_2__"); Builder.defineMacro("__tune_k6_2__"); @@ -2632,6 +2688,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_BDVER2: defineCPUMacros(Builder, "bdver2"); break; + case CK_BDVER3: + defineCPUMacros(Builder, "bdver3"); + break; case CK_Geode: defineCPUMacros(Builder, "geode"); break; @@ -2676,23 +2735,43 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasRDSEED) Builder.defineMacro("__RDSEED__"); - if (HasSSE4a) - Builder.defineMacro("__SSE4A__"); + if (HasTBM) + Builder.defineMacro("__TBM__"); - if (HasFMA4) + switch (XOPLevel) { + case XOP: + Builder.defineMacro("__XOP__"); + case FMA4: Builder.defineMacro("__FMA4__"); + case SSE4A: + Builder.defineMacro("__SSE4A__"); + case NoXOP: + break; + } if (HasFMA) Builder.defineMacro("__FMA__"); - if (HasXOP) - Builder.defineMacro("__XOP__"); - if (HasF16C) Builder.defineMacro("__F16C__"); + if (HasAVX512CD) + Builder.defineMacro("__AVX512CD__"); + if (HasAVX512ER) + Builder.defineMacro("__AVX512ER__"); + if (HasAVX512PF) + Builder.defineMacro("__AVX512PF__"); + + if (HasSHA) + Builder.defineMacro("__SHA__"); + + if (HasCX16) + Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16"); + // Each case falls through to the previous one here. switch (SSELevel) { + case AVX512F: + Builder.defineMacro("__AVX512F__"); case AVX2: Builder.defineMacro("__AVX2__"); case AVX: @@ -2717,6 +2796,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (Opts.MicrosoftExt && getTriple().getArch() == llvm::Triple::x86) { switch (SSELevel) { + case AVX512F: case AVX2: case AVX: case SSE42: @@ -2760,10 +2840,17 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("aes", HasAES) .Case("avx", SSELevel >= AVX) .Case("avx2", SSELevel >= AVX2) + .Case("avx512f", SSELevel >= AVX512F) + .Case("avx512cd", HasAVX512CD) + .Case("avx512er", HasAVX512ER) + .Case("avx512pf", HasAVX512PF) .Case("bmi", HasBMI) .Case("bmi2", HasBMI2) + .Case("cx16", HasCX16) + .Case("f16c", HasF16C) .Case("fma", HasFMA) - .Case("fma4", HasFMA4) + .Case("fma4", XOPLevel >= FMA4) + .Case("tbm", HasTBM) .Case("lzcnt", HasLZCNT) .Case("rdrnd", HasRDRND) .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow) @@ -2774,18 +2861,18 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("rtm", HasRTM) .Case("prfchw", HasPRFCHW) .Case("rdseed", HasRDSEED) + .Case("sha", HasSHA) .Case("sse", SSELevel >= SSE1) .Case("sse2", SSELevel >= SSE2) .Case("sse3", SSELevel >= SSE3) .Case("ssse3", SSELevel >= SSSE3) - .Case("sse41", SSELevel >= SSE41) - .Case("sse42", SSELevel >= SSE42) - .Case("sse4a", HasSSE4a) + .Case("sse4.1", SSELevel >= SSE41) + .Case("sse4.2", SSELevel >= SSE42) + .Case("sse4a", XOPLevel >= SSE4A) .Case("x86", true) .Case("x86_32", getTriple().getArch() == llvm::Triple::x86) .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64) - .Case("xop", HasXOP) - .Case("f16c", HasF16C) + .Case("xop", XOPLevel >= XOP) .Default(false); } @@ -2858,7 +2945,7 @@ namespace { // X86-32 generic target class X86_32TargetInfo : public X86TargetInfo { public: - X86_32TargetInfo(const std::string& triple) : X86TargetInfo(triple) { + X86_32TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple) { DoubleAlign = LongLongAlign = 32; LongDoubleWidth = 96; LongDoubleAlign = 32; @@ -2909,12 +2996,16 @@ public: namespace { class NetBSDI386TargetInfo : public NetBSDTargetInfo<X86_32TargetInfo> { public: - NetBSDI386TargetInfo(const std::string &triple) : - NetBSDTargetInfo<X86_32TargetInfo>(triple) { - } + NetBSDI386TargetInfo(const llvm::Triple &Triple) + : NetBSDTargetInfo<X86_32TargetInfo>(Triple) {} virtual unsigned getFloatEvalMethod() const { - // NetBSD defaults to "double" rounding + unsigned Major, Minor, Micro; + getTriple().getOSVersion(Major, Minor, Micro); + // New NetBSD uses the default rounding mode. + if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0) + return X86_32TargetInfo::getFloatEvalMethod(); + // NetBSD before 6.99.26 defaults to "double" rounding. return 1; } }; @@ -2923,8 +3014,8 @@ public: namespace { class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> { public: - OpenBSDI386TargetInfo(const std::string& triple) : - OpenBSDTargetInfo<X86_32TargetInfo>(triple) { + OpenBSDI386TargetInfo(const llvm::Triple &Triple) + : OpenBSDTargetInfo<X86_32TargetInfo>(Triple) { SizeType = UnsignedLong; IntPtrType = SignedLong; PtrDiffType = SignedLong; @@ -2935,8 +3026,8 @@ public: namespace { class BitrigI386TargetInfo : public BitrigTargetInfo<X86_32TargetInfo> { public: - BitrigI386TargetInfo(const std::string& triple) : - BitrigTargetInfo<X86_32TargetInfo>(triple) { + BitrigI386TargetInfo(const llvm::Triple &Triple) + : BitrigTargetInfo<X86_32TargetInfo>(Triple) { SizeType = UnsignedLong; IntPtrType = SignedLong; PtrDiffType = SignedLong; @@ -2947,8 +3038,8 @@ public: namespace { class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> { public: - DarwinI386TargetInfo(const std::string& triple) : - DarwinTargetInfo<X86_32TargetInfo>(triple) { + DarwinI386TargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<X86_32TargetInfo>(Triple) { LongDoubleWidth = 128; LongDoubleAlign = 128; SuitableAlign = 128; @@ -2968,8 +3059,8 @@ namespace { // x86-32 Windows target class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> { public: - WindowsX86_32TargetInfo(const std::string& triple) - : WindowsTargetInfo<X86_32TargetInfo>(triple) { + WindowsX86_32TargetInfo(const llvm::Triple &Triple) + : WindowsTargetInfo<X86_32TargetInfo>(Triple) { TLSSupported = false; WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; @@ -2989,8 +3080,8 @@ namespace { // x86-32 Windows Visual Studio target class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo { public: - VisualStudioWindowsX86_32TargetInfo(const std::string& triple) - : WindowsX86_32TargetInfo(triple) { + VisualStudioWindowsX86_32TargetInfo(const llvm::Triple &Triple) + : WindowsX86_32TargetInfo(Triple) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } @@ -3010,9 +3101,8 @@ namespace { // x86-32 MinGW target class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo { public: - MinGWX86_32TargetInfo(const std::string& triple) - : WindowsX86_32TargetInfo(triple) { - } + MinGWX86_32TargetInfo(const llvm::Triple &Triple) + : WindowsX86_32TargetInfo(Triple) {} virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder); @@ -3038,8 +3128,8 @@ namespace { // x86-32 Cygwin target class CygwinX86_32TargetInfo : public X86_32TargetInfo { public: - CygwinX86_32TargetInfo(const std::string& triple) - : X86_32TargetInfo(triple) { + CygwinX86_32TargetInfo(const llvm::Triple &Triple) + : X86_32TargetInfo(Triple) { TLSSupported = false; WCharType = UnsignedShort; DoubleAlign = LongLongAlign = 64; @@ -3064,8 +3154,7 @@ namespace { // x86-32 Haiku target class HaikuX86_32TargetInfo : public X86_32TargetInfo { public: - HaikuX86_32TargetInfo(const std::string& triple) - : X86_32TargetInfo(triple) { + HaikuX86_32TargetInfo(const llvm::Triple &Triple) : X86_32TargetInfo(Triple) { SizeType = UnsignedLong; IntPtrType = SignedLong; PtrDiffType = SignedLong; @@ -3093,37 +3182,35 @@ protected: Builder.defineMacro("__rtems__"); Builder.defineMacro("__ELF__"); } -public: - RTEMSTargetInfo(const std::string &triple) - : OSTargetInfo<Target>(triple) { - this->UserLabelPrefix = ""; - llvm::Triple Triple(triple); - switch (Triple.getArch()) { - default: - case llvm::Triple::x86: - // this->MCountName = ".mcount"; - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - // this->MCountName = "_mcount"; - break; - case llvm::Triple::arm: - // this->MCountName = "__mcount"; - break; - } +public: + RTEMSTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) { + this->UserLabelPrefix = ""; + switch (Triple.getArch()) { + default: + case llvm::Triple::x86: + // this->MCountName = ".mcount"; + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + // this->MCountName = "_mcount"; + break; + case llvm::Triple::arm: + // this->MCountName = "__mcount"; + break; } + } }; namespace { // x86-32 RTEMS target class RTEMSX86_32TargetInfo : public X86_32TargetInfo { public: - RTEMSX86_32TargetInfo(const std::string& triple) - : X86_32TargetInfo(triple) { + RTEMSX86_32TargetInfo(const llvm::Triple &Triple) : X86_32TargetInfo(Triple) { SizeType = UnsignedLong; IntPtrType = SignedLong; PtrDiffType = SignedLong; @@ -3142,7 +3229,7 @@ namespace { // x86-64 generic target class X86_64TargetInfo : public X86TargetInfo { public: - X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) { + X86_64TargetInfo(const llvm::Triple &Triple) : X86TargetInfo(Triple) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; LongDoubleWidth = 128; LongDoubleAlign = 128; @@ -3181,8 +3268,7 @@ public: } virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const { - return (CC == CC_Default || - CC == CC_C || + return (CC == CC_C || CC == CC_IntelOclBicc || CC == CC_X86_64Win64) ? CCCR_OK : CCCR_Warning; } @@ -3198,8 +3284,8 @@ namespace { // x86-64 Windows target class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> { public: - WindowsX86_64TargetInfo(const std::string& triple) - : WindowsTargetInfo<X86_64TargetInfo>(triple) { + WindowsX86_64TargetInfo(const llvm::Triple &Triple) + : WindowsTargetInfo<X86_64TargetInfo>(Triple) { TLSSupported = false; WCharType = UnsignedShort; LongWidth = LongAlign = 32; @@ -3232,8 +3318,8 @@ namespace { // x86-64 Windows Visual Studio target class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo { public: - VisualStudioWindowsX86_64TargetInfo(const std::string& triple) - : WindowsX86_64TargetInfo(triple) { + VisualStudioWindowsX86_64TargetInfo(const llvm::Triple &Triple) + : WindowsX86_64TargetInfo(Triple) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble; } @@ -3251,9 +3337,8 @@ namespace { // x86-64 MinGW target class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo { public: - MinGWX86_64TargetInfo(const std::string& triple) - : WindowsX86_64TargetInfo(triple) { - } + MinGWX86_64TargetInfo(const llvm::Triple &Triple) + : WindowsX86_64TargetInfo(Triple) {} virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder); @@ -3277,8 +3362,8 @@ public: namespace { class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> { public: - DarwinX86_64TargetInfo(const std::string& triple) - : DarwinTargetInfo<X86_64TargetInfo>(triple) { + DarwinX86_64TargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<X86_64TargetInfo>(Triple) { Int64Type = SignedLongLong; MaxVectorAlign = 256; } @@ -3288,8 +3373,8 @@ public: namespace { class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> { public: - OpenBSDX86_64TargetInfo(const std::string& triple) - : OpenBSDTargetInfo<X86_64TargetInfo>(triple) { + OpenBSDX86_64TargetInfo(const llvm::Triple &Triple) + : OpenBSDTargetInfo<X86_64TargetInfo>(Triple) { IntMaxType = SignedLongLong; UIntMaxType = UnsignedLongLong; Int64Type = SignedLongLong; @@ -3300,11 +3385,11 @@ public: namespace { class BitrigX86_64TargetInfo : public BitrigTargetInfo<X86_64TargetInfo> { public: - BitrigX86_64TargetInfo(const std::string& triple) - : BitrigTargetInfo<X86_64TargetInfo>(triple) { - IntMaxType = SignedLongLong; - UIntMaxType = UnsignedLongLong; - Int64Type = SignedLongLong; + BitrigX86_64TargetInfo(const llvm::Triple &Triple) + : BitrigTargetInfo<X86_64TargetInfo>(Triple) { + IntMaxType = SignedLongLong; + UIntMaxType = UnsignedLongLong; + Int64Type = SignedLongLong; } }; } @@ -3314,9 +3399,17 @@ class AArch64TargetInfo : public TargetInfo { static const char * const GCCRegNames[]; static const TargetInfo::GCCRegAlias GCCRegAliases[]; + enum FPUModeEnum { + FPUMode, + NeonMode + }; + + unsigned FPU; + unsigned Crypto; static const Builtin::Info BuiltinInfo[]; + public: - AArch64TargetInfo(const std::string& triple) : TargetInfo(triple) { + AArch64TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; LongWidth = LongAlign = 64; LongDoubleWidth = LongDoubleAlign = 128; @@ -3342,22 +3435,20 @@ public: Builder.defineMacro("__AARCH64EL__"); // ACLE predefines. Many can only have one possible value on v8 AArch64. - - // 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: __ARM_ARCH_ISA_ARM, __ARM_ARCH_ISA_THUMB, __ARM_PCS. - Builder.defineMacro("__ARM_ACLE", "101"); + Builder.defineMacro("__ARM_ACLE", "200"); Builder.defineMacro("__ARM_ARCH", "8"); Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'"); + Builder.defineMacro("__ARM_64BIT_STATE"); + Builder.defineMacro("__ARM_PCS_AAPCS64"); + Builder.defineMacro("__ARM_ARCH_ISA_A64"); + Builder.defineMacro("__ARM_FEATURE_UNALIGNED"); Builder.defineMacro("__ARM_FEATURE_CLZ"); Builder.defineMacro("__ARM_FEATURE_FMA"); + Builder.defineMacro("__ARM_FEATURE_DIV"); - // 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("__ARM_FEATURE_LDREX", "0xf"); + Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4"); // 0xe implies support for half, single and double precision operations. Builder.defineMacro("__ARM_FP", "0xe"); @@ -3379,7 +3470,17 @@ public: Opts.ShortEnums ? "1" : "4"); if (BigEndian) - Builder.defineMacro("__ARM_BIG_ENDIAN"); + Builder.defineMacro("__AARCH_BIG_ENDIAN"); + + if (FPU == NeonMode) { + Builder.defineMacro("__ARM_NEON"); + // 64-bit NEON supports half, single and double precision operations. + Builder.defineMacro("__ARM_NEON_FP", "7"); + } + + if (Crypto) { + Builder.defineMacro("__ARM_FEATURE_CRYPTO"); + } } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { @@ -3387,9 +3488,30 @@ public: NumRecords = clang::AArch64::LastTSBuiltin-Builtin::FirstTSBuiltin; } virtual bool hasFeature(StringRef Feature) const { - return Feature == "aarch64"; + return Feature == "aarch64" || (Feature == "neon" && FPU == NeonMode); } - virtual void getGCCRegNames(const char * const *&Names, + + virtual bool setCPU(const std::string &Name) { + return llvm::StringSwitch<bool>(Name) + .Case("generic", true) + .Cases("cortex-a53", "cortex-a57", true) + .Default(false); + } + + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { + FPU = FPUMode; + Crypto = 0; + for (unsigned i = 0, e = Features.size(); i != e; ++i) { + if (Features[i] == "+neon") + FPU = NeonMode; + if (Features[i] == "+crypto") + Crypto = 1; + } + return true; + } + + virtual void getGCCRegNames(const char *const *&Names, unsigned &NumNames) const; virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, unsigned &NumAliases) const; @@ -3510,11 +3632,18 @@ class ARMTargetInfo : public TargetInfo { VFP2FPU = (1 << 0), VFP3FPU = (1 << 1), VFP4FPU = (1 << 2), - NeonFPU = (1 << 3) + NeonFPU = (1 << 3), + FPARMV8 = (1 << 4) + }; + + // Possible HWDiv features. + enum HWDivMode { + HWDivThumb = (1 << 0), + HWDivARM = (1 << 1) }; static bool FPUModeIsVFP(FPUMode Mode) { - return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU); + return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8); } static const TargetInfo::GCCRegAlias GCCRegAliases[]; @@ -3522,15 +3651,24 @@ class ARMTargetInfo : public TargetInfo { std::string ABI, CPU; - unsigned FPU : 4; + enum { + FP_Default, + FP_VFP, + FP_Neon + } FPMath; + + unsigned FPU : 5; unsigned IsAAPCS : 1; unsigned IsThumb : 1; + unsigned HWDiv : 2; // Initialized via features. unsigned SoftFloat : 1; unsigned SoftFloatABI : 1; + unsigned CRC : 1; + static const Builtin::Info BuiltinInfo[]; static bool shouldUseInlineAtomic(const llvm::Triple &T) { @@ -3539,7 +3677,10 @@ class ARMTargetInfo : public TargetInfo { // 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 && T.getOS() != llvm::Triple::FreeBSD) + if (!T.isOSLinux() && + T.getOS() != llvm::Triple::FreeBSD && + T.getOS() != llvm::Triple::NetBSD && + T.getOS() != llvm::Triple::Bitrig) return false; StringRef ArchName = T.getArchName(); if (T.getArch() == llvm::Triple::arm) { @@ -3562,14 +3703,23 @@ class ARMTargetInfo : public TargetInfo { } public: - ARMTargetInfo(const std::string &TripleStr) - : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s"), IsAAPCS(true) - { + ARMTargetInfo(const llvm::Triple &Triple) + : TargetInfo(Triple), ABI("aapcs-linux"), CPU("arm1136j-s"), + FPMath(FP_Default), IsAAPCS(true) { BigEndian = false; - SizeType = UnsignedInt; - PtrDiffType = SignedInt; - // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. - WCharType = UnsignedInt; + switch (getTriple().getOS()) { + case llvm::Triple::NetBSD: + SizeType = UnsignedLong; + PtrDiffType = SignedLong; + WCharType = SignedInt; + break; + default: + // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. + WCharType = UnsignedInt; + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + break; + } // {} in inline assembly are neon specifiers, not assembly variant // specifiers. @@ -3645,6 +3795,9 @@ public: // FIXME: Override "preferred align" for double and long long. } else if (Name == "aapcs" || Name == "aapcs-vfp") { + // size_t is unsigned long on Darwin. + if (getTriple().isOSDarwin()) + SizeType = UnsignedLong; IsAAPCS = true; // FIXME: Enumerated types are variable width in straight AAPCS. } else if (Name == "aapcs-linux") { @@ -3656,33 +3809,45 @@ public: } void getDefaultFeatures(llvm::StringMap<bool> &Features) const { + StringRef ArchName = getTriple().getArchName(); if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") Features["vfp2"] = true; - else if (CPU == "cortex-a8" || CPU == "cortex-a15" || - CPU == "cortex-a9" || CPU == "cortex-a9-mp") + else if (CPU == "cortex-a8" || CPU == "cortex-a9" || + CPU == "cortex-a9-mp") { + Features["vfp3"] = true; Features["neon"] = true; - else if (CPU == "swift" || CPU == "cortex-a7") { + } + else if (CPU == "cortex-a5") { + Features["vfp4"] = true; + Features["neon"] = true; + } else if (CPU == "swift" || CPU == "cortex-a7" || CPU == "cortex-a15") { Features["vfp4"] = true; Features["neon"] = true; + Features["hwdiv"] = true; + Features["hwdiv-arm"] = true; + } else if (CPU == "cortex-a53" || CPU == "cortex-a57") { + Features["fp-armv8"] = true; + Features["neon"] = true; + Features["hwdiv"] = true; + Features["hwdiv-arm"] = true; + Features["crc"] = true; + } else if (CPU == "cortex-r5" || CPU == "cortex-m3" || + CPU == "cortex-m4" || + // Enable the hwdiv extension for all v8a AArch32 cores by + // default. + ArchName == "armv8a" || ArchName == "armv8" || + ArchName == "thumbv8a" || ArchName == "thumbv8") { + Features["hwdiv"] = true; + Features["hwdiv-arm"] = true; } } - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - if (Name == "soft-float" || Name == "soft-float-abi" || - Name == "vfp2" || Name == "vfp3" || Name == "vfp4" || Name == "neon" || - Name == "d16" || Name == "neonfp") { - Features[Name] = Enabled; - } else - return false; - - return true; - } - - virtual void HandleTargetFeatures(std::vector<std::string> &Features) { + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { FPU = 0; + CRC = 0; SoftFloat = SoftFloatABI = false; + HWDiv = 0; for (unsigned i = 0, e = Features.size(); i != e; ++i) { if (Features[i] == "+soft-float") SoftFloat = true; @@ -3694,10 +3859,28 @@ public: FPU |= VFP3FPU; else if (Features[i] == "+vfp4") FPU |= VFP4FPU; + else if (Features[i] == "+fp-armv8") + FPU |= FPARMV8; else if (Features[i] == "+neon") FPU |= NeonFPU; + else if (Features[i] == "+hwdiv") + HWDiv |= HWDivThumb; + else if (Features[i] == "+hwdiv-arm") + HWDiv |= HWDivARM; + else if (Features[i] == "+crc") + CRC = 1; + } + + if (!(FPU & NeonFPU) && FPMath == FP_Neon) { + Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; + return false; } + if (FPMath == FP_Neon) + Features.push_back("+neonfp"); + else if (FPMath == FP_VFP) + Features.push_back("-neonfp"); + // Remove front-end specific options which the backend handles differently. std::vector<std::string>::iterator it; it = std::find(Features.begin(), Features.end(), "+soft-float"); @@ -3706,6 +3889,7 @@ public: it = std::find(Features.begin(), Features.end(), "+soft-float-abi"); if (it != Features.end()) Features.erase(it); + return true; } virtual bool hasFeature(StringRef Feature) const { @@ -3713,8 +3897,9 @@ public: .Case("arm", true) .Case("softfloat", SoftFloat) .Case("thumb", IsThumb) - .Case("neon", FPU == NeonFPU && !SoftFloat && - StringRef(getCPUDefineSuffix(CPU)).startswith("7")) + .Case("neon", (FPU & NeonFPU) && !SoftFloat) + .Case("hwdiv", HWDiv & HWDivThumb) + .Case("hwdiv-arm", HWDiv & HWDivARM) .Default(false); } // FIXME: Should we actually have some table instead of these switches? @@ -3735,19 +3920,22 @@ public: .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K") .Cases("arm1156t2-s", "arm1156t2f-s", "6T2") .Cases("cortex-a5", "cortex-a7", "cortex-a8", "7A") - .Cases("cortex-a9", "cortex-a15", "7A") - .Case("cortex-r5", "7R") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "7A") + .Cases("cortex-r4", "cortex-r5", "7R") .Case("cortex-a9-mp", "7F") .Case("swift", "7S") .Cases("cortex-m3", "cortex-m4", "7M") .Case("cortex-m0", "6M") + .Cases("cortex-a53", "cortex-a57", "8A") .Default(0); } static const char *getCPUProfile(StringRef Name) { return llvm::StringSwitch<const char*>(Name) - .Cases("cortex-a8", "cortex-a9", "A") + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "A") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "A") + .Cases("cortex-a53", "cortex-a57", "A") .Cases("cortex-m3", "cortex-m4", "cortex-m0", "M") - .Case("cortex-r5", "R") + .Cases("cortex-r4", "cortex-r5", "R") .Default(""); } virtual bool setCPU(const std::string &Name) { @@ -3757,6 +3945,7 @@ public: CPU = Name; return true; } + virtual bool setFPMath(StringRef Name); virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. @@ -3769,6 +3958,10 @@ public: 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 + "__"); Builder.defineMacro("__ARM_ARCH", CPUArch.substr(0, 1)); StringRef CPUProfile = getCPUProfile(CPU); @@ -3779,12 +3972,12 @@ public: // FIXME: It's more complicated than this and we don't really support // interworking. - if ('5' <= CPUArch[0] && CPUArch[0] <= '7') + if (5 <= CPUArchVer && CPUArchVer <= 7) Builder.defineMacro("__THUMB_INTERWORK__"); if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") { - // M-class CPUs on Darwin follow AAPCS, but not EABI. - if (!(getTriple().isOSDarwin() && CPUProfile == "M")) + // Embedded targets on Darwin follow AAPCS, but not EABI. + if (!getTriple().isOSDarwin()) Builder.defineMacro("__ARM_EABI__"); Builder.defineMacro("__ARM_PCS", "1"); @@ -3798,13 +3991,14 @@ public: if (CPU == "xscale") Builder.defineMacro("__XSCALE__"); - bool IsARMv7 = CPUArch.startswith("7"); if (IsThumb) { Builder.defineMacro("__THUMBEL__"); Builder.defineMacro("__thumb__"); - if (CPUArch == "6T2" || IsARMv7) + if (CPUArch == "6T2" || CPUArchVer == 7) Builder.defineMacro("__thumb2__"); } + 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. Builder.defineMacro("__APCS_32__"); @@ -3823,8 +4017,18 @@ 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 && IsARMv7) + if ((FPU & NeonFPU) && !SoftFloat && CPUArchVer >= 7) Builder.defineMacro("__ARM_NEON__"); + + if (CRC) + Builder.defineMacro("__ARM_FEATURE_CRC32"); + + if (CPUArchVer >= 6 && CPUArch != "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"); + } } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { @@ -3902,8 +4106,7 @@ public: case 'r': { switch (Modifier) { default: - return isInOut || (isOutput && Size >= 32) || - (!isOutput && !isInOut && Size <= 32); + return (isInOut || isOutput || Size <= 64); case 'q': // A register of size 32 cannot fit a vector type. return false; @@ -3929,6 +4132,18 @@ public: } }; +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; +} + const char * const ARMTargetInfo::GCCRegNames[] = { // Integer registers "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", @@ -4002,8 +4217,8 @@ protected: } public: - DarwinARMTargetInfo(const std::string& triple) - : DarwinTargetInfo<ARMTargetInfo>(triple) { + DarwinARMTargetInfo(const llvm::Triple &Triple) + : DarwinTargetInfo<ARMTargetInfo>(Triple) { HasAlignMac68kSupport = true; // iOS always has 64-bit atomic instructions. // FIXME: This should be based off of the target features in ARMTargetInfo. @@ -4024,7 +4239,7 @@ class HexagonTargetInfo : public TargetInfo { static const TargetInfo::GCCRegAlias GCCRegAliases[]; std::string CPU; public: - HexagonTargetInfo(const std::string& triple) : TargetInfo(triple) { + HexagonTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; DescriptionString = ("e-p:32:32:32-" "i64:64:64-i32:32:32-i16:16:16-i1:32:32-" @@ -4177,23 +4392,15 @@ class SparcTargetInfo : public TargetInfo { static const char * const GCCRegNames[]; bool SoftFloat; public: - SparcTargetInfo(const std::string &triple) : TargetInfo(triple) {} - - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - if (Name == "soft-float") - Features[Name] = Enabled; - else - return false; + SparcTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {} - return true; - } - virtual void HandleTargetFeatures(std::vector<std::string> &Features) { + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { SoftFloat = false; for (unsigned i = 0, e = Features.size(); i != e; ++i) if (Features[i] == "+soft-float") SoftFloat = true; + return true; } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -4290,7 +4497,7 @@ void SparcTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, // SPARC v8 is the 32-bit mode selected by Triple::sparc. class SparcV8TargetInfo : public SparcTargetInfo { public: - SparcV8TargetInfo(const std::string& triple) : SparcTargetInfo(triple) { + SparcV8TargetInfo(const llvm::Triple &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"; @@ -4306,10 +4513,22 @@ public: // SPARC v9 is the 64-bit mode selected by Triple::sparcv9. class SparcV9TargetInfo : public SparcTargetInfo { public: - SparcV9TargetInfo(const std::string& triple) : SparcTargetInfo(triple) { + SparcV9TargetInfo(const llvm::Triple &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"; + // This is an LP64 platform. + LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + + // OpenBSD uses long long for int64_t and intmax_t. + if (getTriple().getOS() == llvm::Triple::OpenBSD) { + IntMaxType = SignedLongLong; + UIntMaxType = UnsignedLongLong; + } else { + IntMaxType = SignedLong; + UIntMaxType = UnsignedLong; + } + Int64Type = IntMaxType; } virtual void getTargetDefines(const LangOptions &Opts, @@ -4333,16 +4552,16 @@ public: namespace { class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> { public: - AuroraUXSparcV8TargetInfo(const std::string& triple) : - AuroraUXTargetInfo<SparcV8TargetInfo>(triple) { + AuroraUXSparcV8TargetInfo(const llvm::Triple &Triple) + : AuroraUXTargetInfo<SparcV8TargetInfo>(Triple) { SizeType = UnsignedInt; PtrDiffType = SignedInt; } }; class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> { public: - SolarisSparcV8TargetInfo(const std::string& triple) : - SolarisTargetInfo<SparcV8TargetInfo>(triple) { + SolarisSparcV8TargetInfo(const llvm::Triple &Triple) + : SolarisTargetInfo<SparcV8TargetInfo>(Triple) { SizeType = UnsignedInt; PtrDiffType = SignedInt; } @@ -4354,7 +4573,7 @@ namespace { static const char *const GCCRegNames[]; public: - SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) { + SystemZTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { TLSSupported = true; IntWidth = IntAlign = 32; LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; @@ -4398,6 +4617,17 @@ namespace { virtual BuiltinVaListKind getBuiltinVaListKind() const { return TargetInfo::SystemZBuiltinVaList; } + virtual bool setCPU(const std::string &Name) { + bool CPUKnown = llvm::StringSwitch<bool>(Name) + .Case("z10", true) + .Case("z196", true) + .Case("zEC12", true) + .Default(false); + + // No need to store the CPU yet. There aren't any CPU-specific + // macros to define. + return CPUKnown; + } }; const char *const SystemZTargetInfo::GCCRegNames[] = { @@ -4447,7 +4677,7 @@ namespace { class MSP430TargetInfo : public TargetInfo { static const char * const GCCRegNames[]; public: - MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) { + MSP430TargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; TLSSupported = false; IntWidth = 16; IntAlign = 16; @@ -4456,9 +4686,9 @@ namespace { PointerWidth = 16; PointerAlign = 16; SuitableAlign = 16; SizeType = UnsignedInt; - IntMaxType = SignedLong; - UIntMaxType = UnsignedLong; - IntPtrType = SignedShort; + IntMaxType = SignedLongLong; + UIntMaxType = UnsignedLongLong; + IntPtrType = SignedInt; PtrDiffType = SignedInt; SigAtomicType = SignedLong; DescriptionString = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"; @@ -4534,7 +4764,7 @@ namespace { class TCETargetInfo : public TargetInfo{ public: - TCETargetInfo(const std::string& triple) : TargetInfo(triple) { + TCETargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { TLSSupported = false; IntWidth = 32; LongWidth = LongLongWidth = 32; @@ -4562,6 +4792,7 @@ namespace { "f32:32:32-f64:32:32-v64:32:32-" "v128:32:32-a0:0:32-n32"; AddrSpaceMap = &TCEOpenCLAddrSpaceMap; + UseAddrSpaceMapMangling = true; } virtual void getTargetDefines(const LangOptions &Opts, @@ -4595,10 +4826,13 @@ namespace { namespace { class MipsTargetInfoBase : public TargetInfo { + virtual void setDescriptionString() = 0; + static const Builtin::Info BuiltinInfo[]; std::string CPU; bool IsMips16; bool IsMicromips; + bool IsNan2008; bool IsSingleFloat; enum MipsFloatABI { HardFloat, SoftFloat @@ -4606,23 +4840,18 @@ class MipsTargetInfoBase : public TargetInfo { enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; + bool HasMSA; protected: + bool HasFP64; std::string ABI; public: - MipsTargetInfoBase(const std::string& triple, - const std::string& ABIStr, - const std::string& CPUStr) - : TargetInfo(triple), - CPU(CPUStr), - IsMips16(false), - IsMicromips(false), - IsSingleFloat(false), - FloatABI(HardFloat), - DspRev(NoDSP), - ABI(ABIStr) - {} + MipsTargetInfoBase(const llvm::Triple &Triple, const std::string &ABIStr, + const std::string &CPUStr) + : TargetInfo(Triple), CPU(CPUStr), IsMips16(false), IsMicromips(false), + IsNan2008(false), IsSingleFloat(false), FloatABI(HardFloat), + DspRev(NoDSP), HasMSA(false), HasFP64(false), ABI(ABIStr) {} virtual const char *getABI() const { return ABI.c_str(); } virtual bool setABI(const std::string &Name) = 0; @@ -4653,12 +4882,19 @@ public: if (IsSingleFloat) Builder.defineMacro("__mips_single_float", Twine(1)); + Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32)); + Builder.defineMacro("_MIPS_FPSET", + Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2))); + if (IsMips16) Builder.defineMacro("__mips16", Twine(1)); if (IsMicromips) Builder.defineMacro("__mips_micromips", Twine(1)); + if (IsNan2008) + Builder.defineMacro("__mips_nan2008", Twine(1)); + switch (DspRev) { default: break; @@ -4673,6 +4909,9 @@ public: break; } + if (HasMSA) + Builder.defineMacro("__mips_msa", Twine(1)); + Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0))); Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth())); Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth())); @@ -4687,14 +4926,17 @@ public: NumRecords = clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin; } virtual bool hasFeature(StringRef Feature) const { - return Feature == "mips"; + return llvm::StringSwitch<bool>(Feature) + .Case("mips", true) + .Case("fp64", HasFP64) + .Default(false); } virtual BuiltinVaListKind getBuiltinVaListKind() const { return TargetInfo::VoidPtrBuiltinVaList; } virtual void getGCCRegNames(const char * const *&Names, unsigned &NumNames) const { - static const char * const GCCRegNames[] = { + static const char *const GCCRegNames[] = { // CPU register names // Must match second column of GCCRegAliases "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", @@ -4708,7 +4950,15 @@ public: "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", // Hi/lo and condition register names "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", - "$fcc5","$fcc6","$fcc7" + "$fcc5","$fcc6","$fcc7", + // MSA register names + "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", + "$w8", "$w9", "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", + "$w16", "$w17", "$w18", "$w19", "$w20", "$w21", "$w22", "$w23", + "$w24", "$w25", "$w26", "$w27", "$w28", "$w29", "$w30", "$w31", + // MSA control register names + "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify", + "$msarequest", "$msamap", "$msaunmap" }; Names = GCCRegNames; NumNames = llvm::array_lengthof(GCCRegNames); @@ -4741,33 +4991,15 @@ public: return ""; } - virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, - StringRef Name, - bool Enabled) const { - if (Name == "soft-float" || Name == "single-float" || - Name == "o32" || Name == "n32" || Name == "n64" || Name == "eabi" || - Name == "mips32" || Name == "mips32r2" || - Name == "mips64" || Name == "mips64r2" || - Name == "mips16" || Name == "micromips" || - Name == "dsp" || Name == "dspr2") { - Features[Name] = Enabled; - return true; - } else if (Name == "32") { - Features["o32"] = Enabled; - return true; - } else if (Name == "64") { - Features["n64"] = Enabled; - return true; - } - return false; - } - - virtual void HandleTargetFeatures(std::vector<std::string> &Features) { + virtual bool handleTargetFeatures(std::vector<std::string> &Features, + DiagnosticsEngine &Diags) { IsMips16 = false; IsMicromips = false; + IsNan2008 = false; IsSingleFloat = false; FloatABI = HardFloat; DspRev = NoDSP; + HasFP64 = ABI == "n32" || ABI == "n64" || ABI == "64"; for (std::vector<std::string>::iterator it = Features.begin(), ie = Features.end(); it != ie; ++it) { @@ -4783,13 +5015,28 @@ public: DspRev = std::max(DspRev, DSP1); else if (*it == "+dspr2") DspRev = std::max(DspRev, DSP2); + else if (*it == "+msa") + HasMSA = true; + else if (*it == "+fp64") + HasFP64 = true; + else if (*it == "-fp64") + HasFP64 = false; + else if (*it == "+nan2008") + IsNan2008 = true; } - // Remove front-end specific option. + // Remove front-end specific options. std::vector<std::string>::iterator it = std::find(Features.begin(), Features.end(), "+soft-float"); if (it != Features.end()) Features.erase(it); + it = std::find(Features.begin(), Features.end(), "+nan2008"); + if (it != Features.end()) + Features.erase(it); + + setDescriptionString(); + + return true; } virtual int getEHDataRegisterNumber(unsigned RegNo) const { @@ -4808,8 +5055,8 @@ const Builtin::Info MipsTargetInfoBase::BuiltinInfo[] = { class Mips32TargetInfoBase : public MipsTargetInfoBase { public: - Mips32TargetInfoBase(const std::string& triple) : - MipsTargetInfoBase(triple, "o32", "mips32") { + Mips32TargetInfoBase(const llvm::Triple &Triple) + : MipsTargetInfoBase(Triple, "o32", "mips32") { SizeType = UnsignedInt; PtrDiffType = SignedInt; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; @@ -4879,11 +5126,15 @@ public: }; class Mips32EBTargetInfo : public Mips32TargetInfoBase { -public: - Mips32EBTargetInfo(const std::string& triple) : Mips32TargetInfoBase(triple) { + virtual void setDescriptionString() { DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"; } + +public: + Mips32EBTargetInfo(const llvm::Triple &Triple) + : Mips32TargetInfoBase(Triple) { + } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { DefineStd(Builder, "MIPSEB", Opts); @@ -4893,12 +5144,16 @@ public: }; class Mips32ELTargetInfo : public Mips32TargetInfoBase { -public: - Mips32ELTargetInfo(const std::string& triple) : Mips32TargetInfoBase(triple) { - BigEndian = false; + virtual void setDescriptionString() { DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"; } + +public: + Mips32ELTargetInfo(const llvm::Triple &Triple) + : Mips32TargetInfoBase(Triple) { + BigEndian = false; + } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { DefineStd(Builder, "MIPSEL", Opts); @@ -4908,10 +5163,9 @@ public: }; class Mips64TargetInfoBase : public MipsTargetInfoBase { - virtual void SetDescriptionString(const std::string &Name) = 0; public: - Mips64TargetInfoBase(const std::string& triple) : - MipsTargetInfoBase(triple, "n64", "mips64") { + Mips64TargetInfoBase(const llvm::Triple &Triple) + : MipsTargetInfoBase(Triple, "n64", "mips64") { LongWidth = LongAlign = 64; PointerWidth = PointerAlign = 64; LongDoubleWidth = LongDoubleAlign = 128; @@ -4924,7 +5178,6 @@ public: MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; } virtual bool setABI(const std::string &Name) { - SetDescriptionString(Name); if (Name == "n32") { LongWidth = LongAlign = 32; PointerWidth = PointerAlign = 32; @@ -5000,20 +5253,21 @@ public: }; class Mips64EBTargetInfo : public Mips64TargetInfoBase { - virtual void SetDescriptionString(const std::string &Name) { - // Change DescriptionString only if ABI is n32. - if (Name == "n32") + virtual void setDescriptionString() { + if (ABI == "n32") DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" "v64:64:64-n32:64-S128"; + else + DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" + "v64:64:64-n32:64-S128"; + } + public: - Mips64EBTargetInfo(const std::string& triple) : Mips64TargetInfoBase(triple) { - // Default ABI is n64. - DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v64:64:64-n32:64-S128"; - } + Mips64EBTargetInfo(const llvm::Triple &Triple) + : Mips64TargetInfoBase(Triple) {} virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { DefineStd(Builder, "MIPSEB", Opts); @@ -5023,20 +5277,21 @@ public: }; class Mips64ELTargetInfo : public Mips64TargetInfoBase { - virtual void SetDescriptionString(const std::string &Name) { - // Change DescriptionString only if ABI is n32. - if (Name == "n32") + virtual void setDescriptionString() { + if (ABI == "n32") DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-f128:128:128" "-v64:64:64-n32:64-S128"; + else + DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" + "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" + "v64:64:64-n32:64-S128"; } public: - Mips64ELTargetInfo(const std::string& triple) : Mips64TargetInfoBase(triple) { + Mips64ELTargetInfo(const llvm::Triple &Triple) + : Mips64TargetInfoBase(Triple) { // Default ABI is n64. BigEndian = false; - DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-" - "i64:64:64-f32:32:32-f64:64:64-f128:128:128-" - "v64:64:64-n32:64-S128"; } virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { @@ -5050,7 +5305,7 @@ public: namespace { class PNaClTargetInfo : public TargetInfo { public: - PNaClTargetInfo(const std::string& triple) : TargetInfo(triple) { + PNaClTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { BigEndian = false; this->UserLabelPrefix = ""; this->LongAlign = 32; @@ -5129,11 +5384,8 @@ namespace { 0 // cuda_shared }; class SPIRTargetInfo : public TargetInfo { - static const char * const GCCRegNames[]; - static const Builtin::Info BuiltinInfo[]; - std::vector<StringRef> AvailableFeatures; public: - SPIRTargetInfo(const std::string& triple) : TargetInfo(triple) { + SPIRTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { assert(getTriple().getOS() == llvm::Triple::UnknownOS && "SPIR target must use unknown OS"); assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && @@ -5142,6 +5394,7 @@ namespace { TLSSupported = false; LongWidth = LongAlign = 64; AddrSpaceMap = &SPIRAddrSpaceMap; + UseAddrSpaceMapMangling = true; // Define available target features // These must be defined in sorted order! NoAsmVariants = true; @@ -5175,7 +5428,7 @@ namespace { class SPIR32TargetInfo : public SPIRTargetInfo { public: - SPIR32TargetInfo(const std::string& triple) : SPIRTargetInfo(triple) { + SPIR32TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) { PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; @@ -5193,7 +5446,7 @@ namespace { class SPIR64TargetInfo : public SPIRTargetInfo { public: - SPIR64TargetInfo(const std::string& triple) : SPIRTargetInfo(triple) { + SPIR64TargetInfo(const llvm::Triple &Triple) : SPIRTargetInfo(Triple) { PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; @@ -5210,300 +5463,374 @@ namespace { }; } +namespace { +class XCoreTargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; +public: + XCoreTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) { + BigEndian = false; + NoAsmVariants = true; + LongLongAlign = 32; + SuitableAlign = 32; + DoubleAlign = LongDoubleAlign = 32; + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + IntPtrType = SignedInt; + WCharType = UnsignedChar; + WIntType = UnsignedInt; + UseZeroLengthBitfieldAlignment = true; + DescriptionString = "e-p:32:32:32-a0:0:32-n32" + "-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32" + "-f16:16:32-f32:32:32-f64:32:32"; + } + virtual void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__XS1B__"); + } + virtual void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const { + Records = BuiltinInfo; + NumRecords = clang::XCore::LastTSBuiltin-Builtin::FirstTSBuiltin; + } + virtual BuiltinVaListKind getBuiltinVaListKind() const { + return TargetInfo::VoidPtrBuiltinVaList; + } + virtual const char *getClobbers() const { + return ""; + } + virtual void getGCCRegNames(const char * const *&Names, + unsigned &NumNames) const { + static const char * const GCCRegNames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "cp", "dp", "sp", "lr" + }; + Names = GCCRegNames; + NumNames = llvm::array_lengthof(GCCRegNames); + } + virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, + unsigned &NumAliases) const { + Aliases = NULL; + NumAliases = 0; + } + virtual bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const { + return false; + } +}; + +const Builtin::Info XCoreTargetInfo::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/BuiltinsXCore.def" +}; +} // end anonymous namespace. + //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// -static TargetInfo *AllocateTarget(const std::string &T) { - llvm::Triple Triple(T); +static TargetInfo *AllocateTarget(const llvm::Triple &Triple) { llvm::Triple::OSType os = Triple.getOS(); switch (Triple.getArch()) { default: return NULL; + case llvm::Triple::xcore: + return new XCoreTargetInfo(Triple); + case llvm::Triple::hexagon: - return new HexagonTargetInfo(T); + return new HexagonTargetInfo(Triple); case llvm::Triple::aarch64: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<AArch64TargetInfo>(T); + return new LinuxTargetInfo<AArch64TargetInfo>(Triple); default: - return new AArch64TargetInfo(T); + return new AArch64TargetInfo(Triple); } case llvm::Triple::arm: case llvm::Triple::thumb: if (Triple.isOSDarwin()) - return new DarwinARMTargetInfo(T); + return new DarwinARMTargetInfo(Triple); switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<ARMTargetInfo>(T); + return new LinuxTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<ARMTargetInfo>(T); + return new FreeBSDTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<ARMTargetInfo>(T); + return new NetBSDTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<ARMTargetInfo>(T); + return new OpenBSDTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::Bitrig: - return new BitrigTargetInfo<ARMTargetInfo>(T); + return new BitrigTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<ARMTargetInfo>(T); + return new RTEMSTargetInfo<ARMTargetInfo>(Triple); case llvm::Triple::NaCl: - return new NaClTargetInfo<ARMTargetInfo>(T); + return new NaClTargetInfo<ARMTargetInfo>(Triple); default: - return new ARMTargetInfo(T); + return new ARMTargetInfo(Triple); } case llvm::Triple::msp430: - return new MSP430TargetInfo(T); + return new MSP430TargetInfo(Triple); case llvm::Triple::mips: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<Mips32EBTargetInfo>(T); + return new LinuxTargetInfo<Mips32EBTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<Mips32EBTargetInfo>(T); + return new RTEMSTargetInfo<Mips32EBTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<Mips32EBTargetInfo>(T); + return new FreeBSDTargetInfo<Mips32EBTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<Mips32EBTargetInfo>(T); + return new NetBSDTargetInfo<Mips32EBTargetInfo>(Triple); default: - return new Mips32EBTargetInfo(T); + return new Mips32EBTargetInfo(Triple); } case llvm::Triple::mipsel: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<Mips32ELTargetInfo>(T); + return new LinuxTargetInfo<Mips32ELTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<Mips32ELTargetInfo>(T); + return new RTEMSTargetInfo<Mips32ELTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<Mips32ELTargetInfo>(T); + return new FreeBSDTargetInfo<Mips32ELTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<Mips32ELTargetInfo>(T); + return new NetBSDTargetInfo<Mips32ELTargetInfo>(Triple); + case llvm::Triple::NaCl: + return new NaClTargetInfo<Mips32ELTargetInfo>(Triple); default: - return new Mips32ELTargetInfo(T); + return new Mips32ELTargetInfo(Triple); } case llvm::Triple::mips64: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<Mips64EBTargetInfo>(T); + return new LinuxTargetInfo<Mips64EBTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<Mips64EBTargetInfo>(T); + return new RTEMSTargetInfo<Mips64EBTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<Mips64EBTargetInfo>(T); + return new FreeBSDTargetInfo<Mips64EBTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<Mips64EBTargetInfo>(T); + return new NetBSDTargetInfo<Mips64EBTargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<Mips64EBTargetInfo>(T); + return new OpenBSDTargetInfo<Mips64EBTargetInfo>(Triple); default: - return new Mips64EBTargetInfo(T); + return new Mips64EBTargetInfo(Triple); } case llvm::Triple::mips64el: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<Mips64ELTargetInfo>(T); + return new LinuxTargetInfo<Mips64ELTargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<Mips64ELTargetInfo>(T); + return new RTEMSTargetInfo<Mips64ELTargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<Mips64ELTargetInfo>(T); + return new FreeBSDTargetInfo<Mips64ELTargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<Mips64ELTargetInfo>(T); + return new NetBSDTargetInfo<Mips64ELTargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<Mips64ELTargetInfo>(T); + return new OpenBSDTargetInfo<Mips64ELTargetInfo>(Triple); default: - return new Mips64ELTargetInfo(T); + return new Mips64ELTargetInfo(Triple); } case llvm::Triple::le32: switch (os) { case llvm::Triple::NaCl: - return new NaClTargetInfo<PNaClTargetInfo>(T); + return new NaClTargetInfo<PNaClTargetInfo>(Triple); default: return NULL; } case llvm::Triple::ppc: if (Triple.isOSDarwin()) - return new DarwinPPC32TargetInfo(T); + return new DarwinPPC32TargetInfo(Triple); switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<PPC32TargetInfo>(T); + return new LinuxTargetInfo<PPC32TargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<PPC32TargetInfo>(T); + return new FreeBSDTargetInfo<PPC32TargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<PPC32TargetInfo>(T); + return new NetBSDTargetInfo<PPC32TargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<PPC32TargetInfo>(T); + return new OpenBSDTargetInfo<PPC32TargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<PPC32TargetInfo>(T); + return new RTEMSTargetInfo<PPC32TargetInfo>(Triple); default: - return new PPC32TargetInfo(T); + return new PPC32TargetInfo(Triple); } case llvm::Triple::ppc64: if (Triple.isOSDarwin()) - return new DarwinPPC64TargetInfo(T); + return new DarwinPPC64TargetInfo(Triple); switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<PPC64TargetInfo>(T); + return new LinuxTargetInfo<PPC64TargetInfo>(Triple); case llvm::Triple::Lv2: - return new PS3PPUTargetInfo<PPC64TargetInfo>(T); + return new PS3PPUTargetInfo<PPC64TargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<PPC64TargetInfo>(T); + return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<PPC64TargetInfo>(T); + return new NetBSDTargetInfo<PPC64TargetInfo>(Triple); + default: + return new PPC64TargetInfo(Triple); + } + + case llvm::Triple::ppc64le: + switch (os) { + case llvm::Triple::Linux: + return new LinuxTargetInfo<PPC64TargetInfo>(Triple); default: - return new PPC64TargetInfo(T); + return new PPC64TargetInfo(Triple); } case llvm::Triple::nvptx: - return new NVPTX32TargetInfo(T); + return new NVPTX32TargetInfo(Triple); case llvm::Triple::nvptx64: - return new NVPTX64TargetInfo(T); - - case llvm::Triple::mblaze: - return new MBlazeTargetInfo(T); + return new NVPTX64TargetInfo(Triple); case llvm::Triple::r600: - return new R600TargetInfo(T); + return new R600TargetInfo(Triple); case llvm::Triple::sparc: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<SparcV8TargetInfo>(T); + return new LinuxTargetInfo<SparcV8TargetInfo>(Triple); case llvm::Triple::AuroraUX: - return new AuroraUXSparcV8TargetInfo(T); + return new AuroraUXSparcV8TargetInfo(Triple); case llvm::Triple::Solaris: - return new SolarisSparcV8TargetInfo(T); + return new SolarisSparcV8TargetInfo(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<SparcV8TargetInfo>(T); + return new NetBSDTargetInfo<SparcV8TargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<SparcV8TargetInfo>(T); + return new OpenBSDTargetInfo<SparcV8TargetInfo>(Triple); case llvm::Triple::RTEMS: - return new RTEMSTargetInfo<SparcV8TargetInfo>(T); + return new RTEMSTargetInfo<SparcV8TargetInfo>(Triple); default: - return new SparcV8TargetInfo(T); + return new SparcV8TargetInfo(Triple); } case llvm::Triple::sparcv9: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<SparcV9TargetInfo>(T); + return new LinuxTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<SparcV9TargetInfo>(T); + return new AuroraUXTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::Solaris: - return new SolarisTargetInfo<SparcV9TargetInfo>(T); + return new SolarisTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<SparcV9TargetInfo>(T); + return new NetBSDTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDTargetInfo<SparcV9TargetInfo>(T); + return new OpenBSDTargetInfo<SparcV9TargetInfo>(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<SparcV9TargetInfo>(T); + return new FreeBSDTargetInfo<SparcV9TargetInfo>(Triple); default: - return new SparcV9TargetInfo(T); + return new SparcV9TargetInfo(Triple); } case llvm::Triple::systemz: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo<SystemZTargetInfo>(T); + return new LinuxTargetInfo<SystemZTargetInfo>(Triple); default: - return new SystemZTargetInfo(T); + return new SystemZTargetInfo(Triple); } case llvm::Triple::tce: - return new TCETargetInfo(T); + return new TCETargetInfo(Triple); case llvm::Triple::x86: if (Triple.isOSDarwin()) - return new DarwinI386TargetInfo(T); + return new DarwinI386TargetInfo(Triple); switch (os) { case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<X86_32TargetInfo>(T); + return new AuroraUXTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Linux: - return new LinuxTargetInfo<X86_32TargetInfo>(T); + return new LinuxTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::DragonFly: - return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T); + return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDI386TargetInfo(T); + return new NetBSDI386TargetInfo(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDI386TargetInfo(T); + return new OpenBSDI386TargetInfo(Triple); case llvm::Triple::Bitrig: - return new BitrigI386TargetInfo(T); + return new BitrigI386TargetInfo(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<X86_32TargetInfo>(T); + return new FreeBSDTargetInfo<X86_32TargetInfo>(Triple); + case llvm::Triple::KFreeBSD: + return new KFreeBSDTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Minix: - return new MinixTargetInfo<X86_32TargetInfo>(T); + return new MinixTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Solaris: - return new SolarisTargetInfo<X86_32TargetInfo>(T); + return new SolarisTargetInfo<X86_32TargetInfo>(Triple); case llvm::Triple::Cygwin: - return new CygwinX86_32TargetInfo(T); + return new CygwinX86_32TargetInfo(Triple); case llvm::Triple::MinGW32: - return new MinGWX86_32TargetInfo(T); + return new MinGWX86_32TargetInfo(Triple); case llvm::Triple::Win32: - return new VisualStudioWindowsX86_32TargetInfo(T); + return new VisualStudioWindowsX86_32TargetInfo(Triple); case llvm::Triple::Haiku: - return new HaikuX86_32TargetInfo(T); + return new HaikuX86_32TargetInfo(Triple); case llvm::Triple::RTEMS: - return new RTEMSX86_32TargetInfo(T); + return new RTEMSX86_32TargetInfo(Triple); case llvm::Triple::NaCl: - return new NaClTargetInfo<X86_32TargetInfo>(T); + return new NaClTargetInfo<X86_32TargetInfo>(Triple); default: - return new X86_32TargetInfo(T); + return new X86_32TargetInfo(Triple); } case llvm::Triple::x86_64: if (Triple.isOSDarwin() || Triple.getEnvironment() == llvm::Triple::MachO) - return new DarwinX86_64TargetInfo(T); + return new DarwinX86_64TargetInfo(Triple); switch (os) { case llvm::Triple::AuroraUX: - return new AuroraUXTargetInfo<X86_64TargetInfo>(T); + return new AuroraUXTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::Linux: - return new LinuxTargetInfo<X86_64TargetInfo>(T); + return new LinuxTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::DragonFly: - return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(T); + return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::NetBSD: - return new NetBSDTargetInfo<X86_64TargetInfo>(T); + return new NetBSDTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::OpenBSD: - return new OpenBSDX86_64TargetInfo(T); + return new OpenBSDX86_64TargetInfo(Triple); case llvm::Triple::Bitrig: - return new BitrigX86_64TargetInfo(T); + return new BitrigX86_64TargetInfo(Triple); case llvm::Triple::FreeBSD: - return new FreeBSDTargetInfo<X86_64TargetInfo>(T); + return new FreeBSDTargetInfo<X86_64TargetInfo>(Triple); + case llvm::Triple::KFreeBSD: + return new KFreeBSDTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::Solaris: - return new SolarisTargetInfo<X86_64TargetInfo>(T); + return new SolarisTargetInfo<X86_64TargetInfo>(Triple); case llvm::Triple::MinGW32: - return new MinGWX86_64TargetInfo(T); + return new MinGWX86_64TargetInfo(Triple); case llvm::Triple::Win32: // This is what Triple.h supports now. - return new VisualStudioWindowsX86_64TargetInfo(T); + return new VisualStudioWindowsX86_64TargetInfo(Triple); case llvm::Triple::NaCl: - return new NaClTargetInfo<X86_64TargetInfo>(T); + return new NaClTargetInfo<X86_64TargetInfo>(Triple); default: - return new X86_64TargetInfo(T); + return new X86_64TargetInfo(Triple); } case llvm::Triple::spir: { - llvm::Triple Triple(T); if (Triple.getOS() != llvm::Triple::UnknownOS || - Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) + Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return NULL; - return new SPIR32TargetInfo(T); + return new SPIR32TargetInfo(Triple); } case llvm::Triple::spir64: { - llvm::Triple Triple(T); if (Triple.getOS() != llvm::Triple::UnknownOS || - Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) + Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return NULL; - return new SPIR64TargetInfo(T); + return new SPIR64TargetInfo(Triple); } } } @@ -5515,7 +5842,7 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, llvm::Triple Triple(Opts->Triple); // Construct the target - OwningPtr<TargetInfo> Target(AllocateTarget(Triple.str())); + OwningPtr<TargetInfo> Target(AllocateTarget(Triple)); if (!Target) { Diags.Report(diag::err_target_unknown_triple) << Triple.str(); return 0; @@ -5540,45 +5867,24 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, return 0; } + // Set the fp math unit. + if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) { + Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath; + return 0; + } + // Compute the default target features, we need the target to handle this // because features may have dependencies on one another. llvm::StringMap<bool> Features; Target->getDefaultFeatures(Features); // Apply the user specified deltas. - // First the enables. - for (std::vector<std::string>::const_iterator - it = Opts->FeaturesAsWritten.begin(), - ie = Opts->FeaturesAsWritten.end(); - it != ie; ++it) { - const char *Name = it->c_str(); - - if (Name[0] != '+') - continue; - + for (unsigned I = 0, N = Opts->FeaturesAsWritten.size(); + I < N; ++I) { + const char *Name = Opts->FeaturesAsWritten[I].c_str(); // Apply the feature via the target. - if (!Target->setFeatureEnabled(Features, Name + 1, true)) { - Diags.Report(diag::err_target_invalid_feature) << Name; - return 0; - } - } - - // Then the disables. - for (std::vector<std::string>::const_iterator - it = Opts->FeaturesAsWritten.begin(), - ie = Opts->FeaturesAsWritten.end(); - it != ie; ++it) { - const char *Name = it->c_str(); - - if (Name[0] == '+') - continue; - - // Apply the feature via the target. - if (Name[0] != '-' || - !Target->setFeatureEnabled(Features, Name + 1, false)) { - Diags.Report(diag::err_target_invalid_feature) << Name; - return 0; - } + bool Enabled = Name[0] == '+'; + Target->setFeatureEnabled(Features, Name + 1, Enabled); } // Add the features to the compile options. @@ -5589,7 +5895,8 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, for (llvm::StringMap<bool>::const_iterator it = Features.begin(), ie = Features.end(); it != ie; ++it) Opts->Features.push_back((it->second ? "+" : "-") + it->first().str()); - Target->HandleTargetFeatures(Opts->Features); + if (!Target->handleTargetFeatures(Opts->Features, Diags)) + return 0; return Target.take(); } |