clang-cl: Implement the -arch flag

Summary:
This implements the -arch flag for both x86 and x86-64 by letting
them affect the default target features we pass to cc1.  -m machine
flags will override the features set by -arch.

Reviewers: hansw

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D4519

llvm-svn: 213083
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index bc64d5c..c5bf7e4 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -1423,7 +1423,8 @@
     CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
 }
 
-static void getX86TargetFeatures(const llvm::Triple &Triple,
+static void getX86TargetFeatures(const Driver & D,
+                                 const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
   if (Triple.getArchName() == "x86_64h") {
@@ -1446,6 +1447,31 @@
       Features.push_back("+ssse3");
   }
 
+  // Set features according to the -arch flag on MSVC
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+    StringRef Arch = A->getValue();
+    bool ArchUsed = false;
+    // First, look for flags that are shared in x86 and x86-64.
+    if (Triple.getArch() == llvm::Triple::x86_64 ||
+        Triple.getArch() == llvm::Triple::x86) {
+      if (Arch == "AVX" || Arch == "AVX2") {
+        ArchUsed = true;
+        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+      }
+    }
+    // Then, look for x86-specific flags.
+    if (Triple.getArch() == llvm::Triple::x86) {
+      if (Arch == "IA32") {
+        ArchUsed = true;
+      } else if (Arch == "SSE" || Arch == "SSE2") {
+        ArchUsed = true;
+        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+      }
+    }
+    if (!ArchUsed)
+      D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
+  }
+
   // Now add any that the user explicitly requested on the command line,
   // which may override the defaults.
   for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
@@ -1608,7 +1634,7 @@
     break;
   case llvm::Triple::x86:
   case llvm::Triple::x86_64:
-    getX86TargetFeatures(Triple, Args, Features);
+    getX86TargetFeatures(D, Triple, Args, Features);
     break;
   }