]> granicus.if.org Git - clang/commitdiff
Improve handling of (X86) target features.
authorDaniel Dunbar <daniel@zuster.org>
Wed, 6 May 2009 03:16:41 +0000 (03:16 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 6 May 2009 03:16:41 +0000 (03:16 +0000)
 - 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

14 files changed:
include/clang/Basic/TargetInfo.h
include/clang/Driver/Options.def
lib/Basic/Targets.cpp
lib/Driver/Tools.cpp
test/CodeGen/mmintrin-test.c
test/Driver/analyze.c
test/Driver/clang-translation.c
test/Sema/carbon-pth.c
test/Sema/carbon.c
test/SemaCXX/carbon.cpp
test/SemaObjC/cocoa-pth.m
test/SemaObjC/cocoa.m
test/SemaObjCXX/cocoa.mm
tools/clang-cc/clang-cc.cpp

index 94fa0d4aea20d0cdd589fb4525494f6eaa43c1d5..ce54db75813038b78c9d4b2685718a5644bfc4f9 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef LLVM_CLANG_BASIC_TARGETINFO_H
 #define LLVM_CLANG_BASIC_TARGETINFO_H
 
+// FIXME: Daniel isn't smart enough to use a prototype for this.
+#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/DataTypes.h"
 #include <cassert>
 #include <vector>
@@ -334,22 +336,16 @@ public:
   /// options. 
   virtual void getDefaultLangOptions(LangOptions &Opts) {}
 
-  /// HandleTargetFeatures - Handle target-specific options like -mattr=+sse2
-  /// 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.
-  ///
-  /// Note that the driver should have already consolidated all the
-  /// target-feature settings and passed them to us in the -mattr list.  The
-  /// -mattr list is treated by the code generator as a diff against the -mcpu
-  /// setting, but the driver should pass all enabled options as "+" settings.
-  /// This means that the target should only look at + settings.
-  virtual int HandleTargetFeatures(std::string *StrArray, unsigned NumStrs,
-                                   std::string &ErrorReason) {
-    if (NumStrs == 0)
-      return -1;
-    return 0;
+  /// getDefaultFeatures - Get the default set of target features for
+  /// the \args CPU; this should include all legal feature strings on
+  /// the target.
+  virtual void getDefaultFeatures(const std::string &CPU, 
+                                  llvm::StringMap<bool> &Features) {
+  }
+
+  /// HandleTargetOptions - Perform initialization based on the user
+  /// configured set of features.
+  virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) {
   }
 
   // getRegParmMax - Returns maximal number of args passed in registers.
index 5d35602e5b09fb4bb11b7be6bafa65e036a10418..cf077be969df9bb3e4b37504ea80806bfceea96c 100644 (file)
@@ -108,6 +108,7 @@ OPTION("<g group>", g_Group, Group, INVALID, INVALID, "", 0, 0, 0)
 OPTION("<i group>", i_Group, Group, INVALID, INVALID, "", 0, 0, 0)
 OPTION("<clang i group>", clang_i_Group, Group, i_Group, INVALID, "", 0, 0, 0)
 OPTION("<m group>", m_Group, Group, INVALID, INVALID, "", 0, 0, 0)
+OPTION("<m x86 features group>", m_x86_Features_Group, Group, INVALID, INVALID, "", 0, 0, 0)
 OPTION("<u group>", u_Group, Group, INVALID, INVALID, "", 0, 0, 0)
 
 OPTION("<pedantic group>", pedantic_Group, Group, INVALID, INVALID, "", 0, 0, 0)
@@ -477,41 +478,42 @@ OPTION("-i", i, Joined, i_Group, INVALID, "", 0, 0, 0)
 OPTION("-keep_private_externs", keep__private__externs, Flag, INVALID, INVALID, "", 0, 0, 0)
 OPTION("-l", l, JoinedOrSeparate, INVALID, INVALID, "l", 0, 0, 0)
 OPTION("-m32", m32, Flag, m_Group, INVALID, "d", 0, 0, 0)
-OPTION("-m3dnowa", m3dnowa, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-m3dnow", m3dnow, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-m3dnowa", m3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-m3dnow", m3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
 OPTION("-m64", m64, Flag, m_Group, INVALID, "d", 0, 0, 0)
+OPTION("-march=", march_EQ, Joined, m_Group, INVALID, "d", 0, 0, 0)
 OPTION("-mconstant-cfstrings", mconstant_cfstrings, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mdynamic-no-pic", mdynamic_no_pic, Joined, m_Group, INVALID, "q", 0, 0, 0)
 OPTION("-mfix-and-continue", mfix_and_continue, Flag, clang_ignored_m_Group, INVALID, "", 0, 0, 0)
 OPTION("-miphoneos-version-min=", miphoneos_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mkernel", mkernel, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mmacosx-version-min=", mmacosx_version_min_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mmmx", mmmx, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-3dnowa", mno_3dnowa, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-3dnow", mno_3dnow, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mmmx", mmmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnowa", mno_3dnowa, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-3dnow", mno_3dnow, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
 OPTION("-mno-constant-cfstrings", mno_constant_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-mmx", mno_mmx, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-mmx", mno_mmx, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
 OPTION("-mno-pascal-strings", mno_pascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mno-red-zone", mno_red_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mno-soft-float", mno_soft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse2", mno_sse2, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse3", mno_sse3, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse41", mno_sse41, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse42", mno_sse42, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse4a", mno_sse4a, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-sse", mno_sse, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mno-ssse3", mno_ssse3, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse2", mno_sse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse3", mno_sse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse41", mno_sse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse42", mno_sse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse4a", mno_sse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-sse", mno_sse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mno-ssse3", mno_ssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
 OPTION("-mno-warn-nonportable-cfstrings", mno_warn_nonportable_cfstrings, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mpascal-strings", mpascal_strings, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-mred-zone", mred_zone, Flag, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-msoft-float", msoft_float, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse2", msse2, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse3", msse3, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse41", msse41, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse42", msse42, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse4a", msse4a, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-msse", msse, Flag, m_Group, INVALID, "", 0, 0, 0)
-OPTION("-mssse3", mssse3, Flag, m_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse2", msse2, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse3", msse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse41", msse41, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse42", msse42, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse4a", msse4a, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-msse", msse, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
+OPTION("-mssse3", mssse3, Flag, m_x86_Features_Group, INVALID, "", 0, 0, 0)
 OPTION("-mtune=", mtune_EQ, Joined, m_Group, INVALID, "", 0, 0, 0)
 OPTION("-multi_module", multi__module, Flag, INVALID, INVALID, "", 0, 0, 0)
 OPTION("-multiply_defined_unused", multiply__defined__unused, Separate, INVALID, INVALID, "", 0, 0, 0)
index e0db82d2a81a581aca148f2dd871d77d965e889d..bb568b149b46711a827b6d3a0254aaebda686e25 100644 (file)
@@ -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
index 2a959b3c55aceda6810969240ce4e5720f0dc453..a52498dc9506579c12584decb297f8c032a44b58 100644 (file)
 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.
index 97f3b3b67c606dd732a5f95264b3381b57e0310b..2a9ab56723303211fa660c3b3cff8177c3b73e58 100644 (file)
@@ -1,6 +1,6 @@
-// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s && 
+// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -emit-llvm -o %t %s && 
 // RUN: grep define %t | count 1 &&
-// RUN: clang-cc -triple i386-apple-darwin9 -g -emit-llvm -o %t %s && 
+// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -g -emit-llvm -o %t %s && 
 // RUN: grep define %t | count 1
 
 #include <mmintrin.h>
index f82199d356e4a5ec5374abd84cbc39300b3aa49e..338c6148c1c37ec2b60616db38041e0e7d197eaf 100644 (file)
@@ -4,6 +4,6 @@
 // RUN: clang -ccc-host-triple i386-apple-darwin9  -### --analyze -o /dev/null %s -msse 2> %t.log &&
 // RUN: grep '"-analyze"' %t.log &&
 // RUN: grep '"--fmath-errno=0"' %t.log &&
-// RUN: grep '"--mattr" "+sse"' %t.log &&
+// RUN: grep '"-target-feature" "+sse"' %t.log &&
 // RUN: grep '"-mmacosx-version-min=10.5.0"' %t.log
 
index 2421bd1f3acdea746a44c4641ed169ae69c72c5c..6d523954c7fabb84792f8dc9fd96258b6d626cd6 100644 (file)
@@ -9,4 +9,8 @@
 // RUN: grep '"-Os"' %t.log &&
 // RUN: grep '"-o" .*clang-translation\.c\.out\.tmp\.s' %t.log &&
 // RUN: grep '"--asm-verbose"' %t.log &&
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu=pentium4"' %t.log &&
+// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -o %t.s 2> %t.log
+// RUN: grep '"--mcpu=core2"' %t.log &&
 // RUN: true
index ebc884054577f6d1fd2d2bcb7d15fba7ed5470ec..c956d2a7a1c82055ac1c99b25d18be714d387d35 100644 (file)
@@ -1,6 +1,6 @@
-// RUN: clang-cc -emit-pth -o %t %s && 
-// RUN: clang-cc -token-cache %t %s &&
-// RUN: clang-cc -token-cache %t %s -E %s -o /dev/null
+// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s && 
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null
 #ifdef __APPLE__
 #include <Carbon/Carbon.h>
 #endif
index 8e6837f12562b9cd89110c0b7627974a3119e7b9..5eda4385ac4906642ab8934e6c46d50b5cb25c00 100644 (file)
@@ -1,5 +1,4 @@
-// RUN: clang-cc %s -print-stats &&
-// RUN: clang-cc %s -disable-free
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
 #ifdef __APPLE__
 #include <Carbon/Carbon.h>
 #endif
index 983a000b2cf94c605093c28d7d0b2d6faecd1a53..0e7570f33529e202746ba4e8c11755a6e44cdd77 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -fsyntax-only -print-stats
+// RUN: clang-cc -mcpu=pentium4 %s -fsyntax-only -print-stats
 #ifdef __APPLE__
 #include <Carbon/Carbon.h>
 #endif
index 24b0579a249f8b6034d975288a7f9d8e64956efd..dc806dfb7c091d93e7f391df9e9f35ad838d1404 100644 (file)
@@ -1,6 +1,6 @@
-// RUN: clang-cc -emit-pth -o %t %s && 
-// RUN: clang-cc -token-cache %t %s &&
-// RUN: clang-cc -token-cache %t %s -E %s -o /dev/null
+// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s && 
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s &&
+// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null
 #ifdef __APPLE__
 #include <Cocoa/Cocoa.h>
 #endif
index 153c46e1034d1345c8b7a826fa76e32ad18c4e0d..b73b3c4ccd33f92ad53e76b721145687cc45948b 100644 (file)
@@ -1,5 +1,4 @@
-// RUN: clang-cc %s -print-stats &&
-// RUN: clang-cc %s -disable-free
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
 #ifdef __APPLE__
 #include <Cocoa/Cocoa.h>
 #endif
index dd9684ce065f9b86a7d1289fe9e0dafc4ed88f3b..c061d4e096840f71c1b22fc2d10df9e66d68be44 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -print-stats
+// RUN: clang-cc -mcpu=pentium4 %s -print-stats
 #ifdef __APPLE__
 #include <Cocoa/Cocoa.h>
 #endif
index 17eeac776c0e76798f959762d1ab492b564fb130..3726f1c738a1a14de38ada4612206e2793f6e92f 100644 (file)
@@ -50,6 +50,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/CommandLine.h"
@@ -663,10 +664,6 @@ NeXTRuntime("fnext-runtime",
 static llvm::cl::opt<bool>
 Trigraphs("trigraphs", llvm::cl::desc("Process trigraph sequences"));
 
-static llvm::cl::list<std::string>
-TargetFeatures("mattr", llvm::cl::CommaSeparated,
-        llvm::cl::desc("Target specific attributes (-mattr=help for details)"));
-
 static llvm::cl::opt<unsigned>
 TemplateDepth("ftemplate-depth", llvm::cl::init(99),
               llvm::cl::desc("Maximum depth of recursive template "
@@ -711,30 +708,14 @@ static llvm::cl::opt<bool>
 StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined"));
 
 static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
-                                       TargetInfo *Target) {
+                                       TargetInfo *Target,
+                                       const llvm::StringMap<bool> &Features) {
   // Allow the target to set the default the langauge options as it sees fit.
   Target->getDefaultLangOptions(Options);
-  
-  // If there are any -mattr options, pass them to the target for validation and
-  // processing.  The driver should have already consolidated all the
-  // target-feature settings and passed them to us in the -mattr list.  The
-  // -mattr list is treated by the code generator as a diff against the -mcpu
-  // setting, but the driver should pass all enabled options as "+" settings.
-  // This means that the target should only look at + settings.
-  if (!TargetFeatures.empty()) {
-    std::string ErrorStr;
-    int Opt = Target->HandleTargetFeatures(&TargetFeatures[0],
-                                           TargetFeatures.size(), ErrorStr);
-    if (Opt != -1) {
-      if (ErrorStr.empty())
-        fprintf(stderr, "invalid feature '%s'\n",
-                TargetFeatures[Opt].c_str());
-      else
-        fprintf(stderr, "feature '%s': %s\n",
-                TargetFeatures[Opt].c_str(), ErrorStr.c_str());
-      exit(1);
-    }
-  }
+
+  // Pass the map of target features to the target for validation and
+  // processing.
+  Target->HandleTargetFeatures(Features);
   
   if (LangStd == lang_unspecified) {
     // Based on the base language, pick one.
@@ -1429,8 +1410,47 @@ static llvm::cl::opt<std::string>
 TargetCPU("mcpu",
          llvm::cl::desc("Target a specific cpu type (-mcpu=help for details)"));
 
+static llvm::cl::list<std::string>
+TargetFeatures("target-feature", llvm::cl::desc("Target specific attributes"));
+
+/// ComputeTargetFeatures - Recompute the target feature list to only
+/// be the list of things that are enabled, based on the target cpu
+/// and feature list.
+static void ComputeFeatureMap(TargetInfo *Target,
+                              llvm::StringMap<bool> &Features) {
+  assert(Features.empty() && "invalid map"); 
+
+  // Initialize the feature map based on the target.
+  Target->getDefaultFeatures(TargetCPU, Features);
+
+  // Apply the user specified deltas.
+  for (llvm::cl::list<std::string>::iterator it = TargetFeatures.begin(), 
+         ie = TargetFeatures.end(); it != ie; ++it) {
+    const char *Name = it->c_str();
+    
+    // FIXME: Don't handle errors like this.
+    if (Name[0] != '-' && Name[0] != '+') {
+      fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n", 
+              Name);
+      exit(1);
+    }
+
+    llvm::StringMap<bool>::iterator it = Features.find(Name + 1);
+    if (it == Features.end()) {
+      fprintf(stderr, "error: clang-cc: invalid target feature string: %s\n", 
+              Name);
+      exit(1);
+    }
+
+    // FIXME: Actually, we need to apply all the features implied by
+    // this feature.
+    it->second = (Name[0] == '+');
+  }
+}
+
 static void InitializeCompileOptions(CompileOptions &Opts,
-                                     const LangOptions &LangOpts) {
+                                     const LangOptions &LangOpts,
+                                     const llvm::StringMap<bool> &Features) {
   Opts.OptimizeSize = OptSize;
   Opts.DebugInfo = GenerateDebugInfo;
   if (OptSize) {
@@ -1451,8 +1471,15 @@ static void InitializeCompileOptions(CompileOptions &Opts,
 #endif
 
   Opts.CPU = TargetCPU;
-  Opts.Features.insert(Opts.Features.end(),
-                       TargetFeatures.begin(), TargetFeatures.end());
+  Opts.Features.clear();
+  for (llvm::StringMap<bool>::const_iterator it = Features.begin(), 
+         ie = Features.end(); it != ie; ++it) {
+    // FIXME: If we are completely confident that we have the right
+    // set, we only need to pass the minuses.
+    std::string Name(it->second ? "+" : "-");
+    Name += it->first();
+    Opts.Features.push_back(Name);
+  }
   
   Opts.NoCommon = NoCommon | LangOpts.CPlusPlus;
   
@@ -1556,6 +1583,7 @@ static void SetUpBuildDumpLog(unsigned argc, char **argv,
 static ASTConsumer *CreateASTConsumer(const std::string& InFile,
                                       Diagnostic& Diag, FileManager& FileMgr, 
                                       const LangOptions& LangOpts,
+                                      const llvm::StringMap<bool>& Features,
                                       Preprocessor *PP,
                                       PreprocessorFactory *PPF) {
   switch (ProgAction) {
@@ -1598,7 +1626,7 @@ static ASTConsumer *CreateASTConsumer(const std::string& InFile,
       Act = Backend_EmitBC;
     
     CompileOptions Opts;
-    InitializeCompileOptions(Opts, LangOpts);
+    InitializeCompileOptions(Opts, LangOpts, Features);
     return CreateBackendConsumer(Act, Diag, LangOpts, Opts, 
                                  InFile, OutputFile);
   }
@@ -1620,7 +1648,8 @@ static ASTConsumer *CreateASTConsumer(const std::string& InFile,
 /// ProcessInputFile - Process a single input file with the specified state.
 ///
 static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
-                             const std::string &InFile, ProgActions PA) {
+                             const std::string &InFile, ProgActions PA,
+                             const llvm::StringMap<bool> &Features) {
   llvm::OwningPtr<ASTConsumer> Consumer;
   bool ClearSourceMgr = false;
   FixItRewriter *FixItRewrite = 0;
@@ -1630,7 +1659,7 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
   default:
     Consumer.reset(CreateASTConsumer(InFile, PP.getDiagnostics(),
                                      PP.getFileManager(), PP.getLangOptions(),
-                                     &PP, &PPF));
+                                     Features, &PP, &PPF));
     
     if (!Consumer) {      
       fprintf(stderr, "Unexpected program action!\n");
@@ -1999,6 +2028,10 @@ int main(int argc, char **argv) {
   // Create a file manager object to provide access to and cache the filesystem.
   FileManager FileMgr;
 
+  // Compute the feature set, unfortunately this effects the language!
+  llvm::StringMap<bool> Features;
+  ComputeFeatureMap(Target.get(), Features);
+
   for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
     const std::string &InFile = InputFilenames[i];
     
@@ -2016,7 +2049,7 @@ int main(int argc, char **argv) {
     InitializeBaseLanguage();
     LangKind LK = GetLanguage(InFile);
     InitializeLangOptions(LangInfo, LK);
-    InitializeLanguageStandard(LangInfo, LK, Target.get());
+    InitializeLanguageStandard(LangInfo, LK, Target.get(), Features);
           
     // Process the -I options and set them in the HeaderInfo.
     HeaderSearch HeaderInfo(FileMgr);
@@ -2041,7 +2074,7 @@ int main(int argc, char **argv) {
       ((PathDiagnosticClient*)DiagClient.get())->SetPreprocessor(PP.get());
 
     // Process the source file.
-    ProcessInputFile(*PP, PPFactory, InFile, ProgAction);
+    ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features);
     
     HeaderInfo.ClearFileInfo();
     DiagClient->setLangOptions(0);