diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-05-06 03:16:41 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-05-06 03:16:41 +0000 |
commit | 868bd0aa9281929ef50d2e9a8c82a036906f53f5 (patch) | |
tree | 112dd090bf8ad85dac458a0b669ff7f582d8128a /lib | |
parent | 02f7ed72fa0d4674e2123a1bd54d7972812f8cc7 (diff) |
Improve handling of (X86) target features.
- This is a WIP...
- This adds -march= handling to the driver, and fixes the defaulting
of -mcpu on Darwin (which was using the wrong test).
Instead of handling -m{sse, ...} in the driver, pass them to clang-cc as
-target-feature [+-]name
In clang-cc, communicate with the (clang) target to discover the legal
features of a target, and the features which are enabled based on
-mcpu. This is currently hardcoded just enough to not be a feature
regression, we need to get this information from the backend's
TableGen information somehow.
This is used to construct the full list of features which are being
used, which is in turn used to initialize the predefines.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71061 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Basic/Targets.cpp | 97 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 98 |
2 files changed, 99 insertions, 96 deletions
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index e0db82d2a8..bb568b149b 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -503,10 +503,7 @@ class X86TargetInfo : public TargetInfo { } SSELevel; public: X86TargetInfo(const std::string& triple) - : TargetInfo(triple), - // FIXME: hard coding to SSE2 for now. This should change to NoMMXSSE so - // that the driver controls this. - SSELevel(SSE2) { + : TargetInfo(triple), SSELevel(NoMMXSSE) { LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; } virtual void getTargetBuiltins(const Builtin::Info *&Records, @@ -536,49 +533,59 @@ public: virtual void getTargetDefines(const LangOptions &Opts, std::vector<char> &Defines) const; - virtual int HandleTargetFeatures(std::string *StrArray, unsigned NumStrs, - std::string &ErrorReason); + virtual void getDefaultFeatures(const std::string &CPU, + llvm::StringMap<bool> &Features); + virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features); }; -/// HandleTargetOptions - Handle target-specific options like -msse2 and -/// friends. An array of arguments is passed in: if they are all valid, this -/// should handle them and return -1. If there is an error, the index of the -/// invalid argument should be returned along with an optional error string. -int X86TargetInfo::HandleTargetFeatures(std::string *StrArray, unsigned NumStrs, - std::string &ErrorReason) { - for (unsigned i = 0; i != NumStrs; ++i) { - const std::string &Feature = StrArray[i]; - if (Feature.size() < 2) return i; - // Ignore explicitly disabled features. - if (Feature[0] == '-') continue; - - // Feature strings are of the form "+feature". - if (Feature[0] != '+') return i; - - // The set of supported subtarget features is defined in - // lib/Target/X86/X86.td. Here we recognize and map onto our internal - // state. - if (Feature == "+mmx") - SSELevel = std::max(SSELevel, MMX); - else if (Feature == "+sse") - SSELevel = std::max(SSELevel, SSE1); - else if (Feature == "+sse2") - SSELevel = std::max(SSELevel, SSE2); - else if (Feature == "+sse3") - SSELevel = std::max(SSELevel, SSE3); - else if (Feature == "+ssse3") - SSELevel = std::max(SSELevel, SSSE3); - else if (Feature == "+sse41") - SSELevel = std::max(SSELevel, SSE41); - else if (Feature == "+sse42") - SSELevel = std::max(SSELevel, SSE42); - else if (Feature == "+64bit" || Feature == "+slow-bt-mem") - // Ignore these features. - continue; - else - return i; - } - return -1; +void X86TargetInfo::getDefaultFeatures(const std::string &CPU, + llvm::StringMap<bool> &Features) { + // 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; + + // LLVM does not currently recognize this. + // Features["sse4a"] = false; + + // FIXME: This *really* should not be here. + + // X86_64 always has SSE2. + if (PointerWidth == 64) + Features["sse2"] = Features["sse"] = Features["mmx"] = true; + + // FIXME: LLVM says core2 has SSSE3, but gcc doesn't define + // __SSSE3__ with it? What else is going on here? + if (CPU == "core2") + Features["ssse3"] = Features["sse3"] = Features["sse2"] = Features["sse"] = + Features["mmx"] = true; + else if (CPU == "pentium4") + Features["sse2"] = Features["sse"] = Features["mmx"] = true; +} + +/// HandleTargetOptions - Perform initialization based on the user +/// configured set of features. +void X86TargetInfo::HandleTargetFeatures(const llvm::StringMap<bool>&Features) { + if (Features.lookup("sse42")) + SSELevel = SSE42; + else if (Features.lookup("sse41")) + SSELevel = SSE41; + else if (Features.lookup("ssse3")) + SSELevel = SSSE3; + else if (Features.lookup("sse3")) + SSELevel = SSE3; + else if (Features.lookup("sse2")) + SSELevel = SSE2; + else if (Features.lookup("sse")) + SSELevel = SSE1; + else if (Features.lookup("mmx")) + SSELevel = MMX; } /// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 2a959b3c55..a52498dc95 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -31,6 +31,13 @@ using namespace clang::driver; using namespace clang::driver::tools; +static const char *MakeFormattedString(const ArgList &Args, + const llvm::format_object_base &Fmt) { + std::string Str; + llvm::raw_string_ostream(Str) << Fmt; + return Args.MakeArgString(Str.c_str()); +} + void Clang::AddPreprocessingOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, @@ -318,52 +325,48 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("--soft-float"); - // FIXME: Need target hooks. - if (memcmp(getToolChain().getPlatform().c_str(), "darwin", 6) == 0) { - if (getToolChain().getArchName() == "x86_64") - CmdArgs.push_back("--mcpu=core2"); - else if (getToolChain().getArchName() == "i386") - CmdArgs.push_back("--mcpu=yonah"); - } - - // FIXME: Ignores ordering. Also, we need to find a realistic - // solution for this. - static const struct { - options::ID Pos, Neg; - const char *Name; - } FeatureOptions[] = { - { options::OPT_mmmx, options::OPT_mno_mmx, "mmx" }, - { options::OPT_msse, options::OPT_mno_sse, "sse" }, - { options::OPT_msse2, options::OPT_mno_sse2, "sse2" }, - { options::OPT_msse3, options::OPT_mno_sse3, "sse3" }, - { options::OPT_mssse3, options::OPT_mno_ssse3, "ssse3" }, - { options::OPT_msse41, options::OPT_mno_sse41, "sse41" }, - { options::OPT_msse42, options::OPT_mno_sse42, "sse42" }, - { options::OPT_msse4a, options::OPT_mno_sse4a, "sse4a" }, - { options::OPT_m3dnow, options::OPT_mno_3dnow, "3dnow" }, - { options::OPT_m3dnowa, options::OPT_mno_3dnowa, "3dnowa" } - }; - const unsigned NumFeatureOptions = - sizeof(FeatureOptions)/sizeof(FeatureOptions[0]); - - // FIXME: Avoid std::string - std::string Attrs; - for (unsigned i=0; i < NumFeatureOptions; ++i) { - if (Args.hasArg(FeatureOptions[i].Pos)) { - if (!Attrs.empty()) - Attrs += ','; - Attrs += '+'; - Attrs += FeatureOptions[i].Name; - } else if (Args.hasArg(FeatureOptions[i].Neg)) { - if (!Attrs.empty()) - Attrs += ','; - Attrs += '-'; - Attrs += FeatureOptions[i].Name; + // FIXME: Handle -mtune=. + (void) Args.hasArg(options::OPT_mtune_EQ); + + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + // FIXME: We made need some translation here from the options gcc + // takes to names the LLVM backend understand? + CmdArgs.push_back("-mcpu"); + CmdArgs.push_back(A->getValue(Args)); + } else { + // Select default CPU. + + // FIXME: Need target hooks. + if (memcmp(getToolChain().getOS().c_str(), "darwin", 6) == 0) { + if (getToolChain().getArchName() == "x86_64") + CmdArgs.push_back("--mcpu=core2"); + else if (getToolChain().getArchName() == "i386") + CmdArgs.push_back("--mcpu=pentium4"); } } - if (!Attrs.empty()) { - CmdArgs.push_back("--mattr"); - CmdArgs.push_back(Args.MakeArgString(Attrs.c_str())); + + // FIXME: Use iterator. + for (ArgList::const_iterator + it = Args.begin(), ie = Args.end(); it != ie; ++it) { + const Arg *A = *it; + if (A->getOption().matches(options::OPT_m_x86_Features_Group)) { + const char *Name = A->getOption().getName(); + + // Skip over "-m". + assert(Name[0] == '-' && Name[1] == 'm' && "Invalid feature name."); + Name += 2; + + bool IsNegative = memcmp(Name, "no-", 3) == 0; + if (IsNegative) + Name += 3; + + A->claim(); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(MakeFormattedString(Args, + llvm::format("%c%s", + IsNegative ? '-' : '+', + Name))); + } } if (Args.hasFlag(options::OPT_fmath_errno, @@ -1215,13 +1218,6 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, Dest.addCommand(new Command(Exec, CmdArgs)); } -static const char *MakeFormattedString(const ArgList &Args, - const llvm::format_object_base &Fmt) { - std::string Str; - llvm::raw_string_ostream(Str) << Fmt; - return Args.MakeArgString(Str.c_str()); -} - /// Helper routine for seeing if we should use dsymutil; this is a /// gcc compatible hack, we should remove it and use the input /// type information. |