diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 4057e48..ba2e26e 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -10,6 +10,7 @@
 #ifndef CLANG_DRIVER_ACTION_H_
 #define CLANG_DRIVER_ACTION_H_
 
+#include "clang/Driver/CPUArch.h"
 #include "clang/Driver/Types.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/SmallVector.h"
@@ -109,12 +110,12 @@ class BindArchAction : public Action {
   virtual void anchor();
   /// The architecture to bind, or 0 if the default architecture
   /// should be bound.
-  const char *ArchName;
+  CPUArch CPUArch;
 
 public:
-  BindArchAction(Action *Input, const char *_ArchName);
+  BindArchAction(Action *Input, enum CPUArch C);
 
-  const char *getArchName() const { return ArchName; }
+  enum CPUArch getCPUArch() const { return CPUArch; }
 
   static bool classof(const Action *A) {
     return A->getKind() == BindArchClass;
diff --git a/include/clang/Driver/CPUArch.h b/include/clang/Driver/CPUArch.h
new file mode 100644
index 0000000..1cc74df
--- /dev/null
+++ b/include/clang/Driver/CPUArch.h
@@ -0,0 +1,50 @@
+//===--- CPUArch.h - Enum and helper functions for -arch --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_DRIVER_CPUARCH_H_
+#define CLANG_DRIVER_CPUARCH_H_
+
+namespace clang {
+namespace driver {
+enum CPUArch {
+  CA_PPC,
+  CA_PPC601,
+  CA_PPC603,
+  CA_PPC604,
+  CA_PPC604e,
+  CA_PPC750,
+  CA_PPC7400,
+  CA_PPC7450,
+  CA_PPC970,
+  CA_PPC64,
+  CA_I386,
+  CA_I486,
+  CA_I586,
+  CA_I686,
+  CA_Pentium,
+  CA_Pentium2,
+  CA_Pentpro,
+  CA_PentIIm3,
+  CA_X86_64,
+  CA_ARM,
+  CA_ARMv4t,
+  CA_ARMv5,
+  CA_XScale,
+  CA_ARMv6,
+  CA_ARMv7,
+  CA_ARMv7f,
+  CA_ARMv7k,
+  CA_ARMv7s,
+  CA_UnknownCPUArch
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 5f63aa7..381bce3 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -10,6 +10,7 @@
 #ifndef CLANG_DRIVER_COMPILATION_H_
 #define CLANG_DRIVER_COMPILATION_H_
 
+#include "clang/Driver/CPUArch.h"
 #include "clang/Driver/Job.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/DenseMap.h"
@@ -47,7 +48,7 @@ class Compilation {
 
   /// Cache of translated arguments for a particular tool chain and bound
   /// architecture.
-  llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+  llvm::DenseMap<std::pair<const ToolChain*, unsigned>,
                  DerivedArgList*> TCArgs;
 
   /// Temporary files which should be removed on exit.
@@ -102,7 +103,7 @@ public:
   ///
   /// \param BoundArch - The bound architecture name, or 0.
   const DerivedArgList &getArgsForToolChain(const ToolChain *TC,
-                                            const char *BoundArch);
+                                            CPUArch BoundArch);
 
   /// addTempFile - Add a file to remove on exit, and returns its
   /// argument.
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index fa83c37..6a15b1d 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -12,6 +12,7 @@
 
 #include "clang/Basic/Diagnostic.h"
 
+#include "clang/Driver/CPUArch.h"
 #include "clang/Driver/Phases.h"
 #include "clang/Driver/Types.h"
 #include "clang/Driver/Util.h"
@@ -344,7 +345,7 @@ public:
   void BuildJobsForAction(Compilation &C,
                           const Action *A,
                           const ToolChain *TC,
-                          const char *BoundArch,
+                          CPUArch BoundArch,
                           bool AtTopLevel,
                           const char *LinkingOutput,
                           InputInfo &Result) const;
@@ -382,7 +383,7 @@ private:
   /// Will cache ToolChains for the life of the driver object, and create them
   /// on-demand.
   const ToolChain &getToolChain(const ArgList &Args,
-                                StringRef DarwinArchName = "") const;
+                                CPUArch DarwinArch) const;
 
   /// @}
 
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index d694e0f..4e5bf6a 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -10,6 +10,7 @@
 #ifndef CLANG_DRIVER_TOOLCHAIN_H_
 #define CLANG_DRIVER_TOOLCHAIN_H_
 
+#include "clang/Driver/CPUArch.h"
 #include "clang/Driver/Util.h"
 #include "clang/Driver/Types.h"
 #include "llvm/ADT/SmallVector.h"
@@ -103,7 +104,7 @@ public:
   ///
   /// \param BoundArch - The bound architecture name, or 0.
   virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
-                                        const char *BoundArch) const {
+                                        CPUArch BoundArch) const {
     return 0;
   }
 
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index d7b4bc7..0eeb0e8 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -47,8 +47,8 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type)
 
 void BindArchAction::anchor() {}
 
-BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
-  : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) {
+BindArchAction::BindArchAction(Action *Input, enum CPUArch A)
+  : Action(BindArchClass, Input, Input->getType()), CPUArch(A) {
 }
 
 void JobAction::anchor() {}
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index e804a54..00c05ff 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -37,7 +37,7 @@ Compilation::~Compilation() {
   delete Args;
 
   // Free any derived arg lists.
-  for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+  for (llvm::DenseMap<std::pair<const ToolChain*, unsigned>,
                       DerivedArgList*>::iterator it = TCArgs.begin(),
          ie = TCArgs.end(); it != ie; ++it)
     if (it->second != TranslatedArgs)
@@ -57,7 +57,7 @@ Compilation::~Compilation() {
 }
 
 const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
-                                                       const char *BoundArch) {
+                                                       CPUArch BoundArch) {
   if (!TC)
     TC = &DefaultToolChain;
 
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 6b0300b..5188651 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -26,6 +26,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
@@ -297,7 +298,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
 
   // Owned by the host.
-  const ToolChain &TC = getToolChain(*Args);
+  const ToolChain &TC = getToolChain(*Args, CA_UnknownCPUArch);
 
   // The compilation takes ownership of Args.
   Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs);
@@ -732,7 +733,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
   if (InputAction *IA = dyn_cast<InputAction>(A)) {
     os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\"";
   } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
-    os << '"' << BIA->getArchName() << '"'
+    os << '"' <<  tools::darwin::getCPUArchName(BIA->getCPUArch()) << '"'
        << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
   } else {
     os << "{";
@@ -780,8 +781,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
   llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
   // Collect the list of architectures. Duplicates are allowed, but should only
   // be handled once (in the order seen).
-  llvm::StringSet<> ArchNames;
-  SmallVector<const char *, 4> Archs;
+  llvm::SetVector<CPUArch> Archs;
   for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
        it != ie; ++it) {
     Arg *A = *it;
@@ -789,24 +789,26 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
     if (A->getOption().matches(options::OPT_arch)) {
       // Validate the option here; we don't save the type here because its
       // particular spelling may participate in other driver choices.
-      llvm::Triple::ArchType Arch =
-        tools::darwin::getArchTypeForDarwinArchName(A->getValue(Args));
-      if (Arch == llvm::Triple::UnknownArch) {
+      CPUArch Arch =
+        tools::darwin::getCPUArchTypeForDarwinArchName(A->getValue(Args));
+      if (Arch == CA_UnknownCPUArch) {
         Diag(clang::diag::err_drv_invalid_arch_name)
           << A->getAsString(Args);
         continue;
       }
 
       A->claim();
-      if (ArchNames.insert(A->getValue(Args)))
-        Archs.push_back(A->getValue(Args));
+      Archs.insert(Arch);
     }
   }
 
   // When there is no explicit arch for this platform, make sure we still bind
   // the architecture (to the default) so that -Xarch_ is handled correctly.
-  if (!Archs.size())
-    Archs.push_back(Args.MakeArgString(TC.getArchName()));
+  if (Archs.empty()) {
+    CPUArch C =
+      tools::darwin::getCPUArchTypeForDarwinArchName(TC.getArchName());
+    Archs.insert(C);
+  }
 
   // FIXME: We killed off some others but these aren't yet detected in a
   // functional manner. If we added information to jobs about which "auxiliary"
@@ -1220,7 +1222,7 @@ void Driver::BuildJobs(Compilation &C) const {
 
     InputInfo II;
     BuildJobsForAction(C, A, &C.getDefaultToolChain(),
-                       /*BoundArch*/0,
+                       CA_UnknownCPUArch,
                        /*AtTopLevel*/ true,
                        /*LinkingOutput*/ LinkingOutput,
                        II);
@@ -1314,7 +1316,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
 void Driver::BuildJobsForAction(Compilation &C,
                                 const Action *A,
                                 const ToolChain *TC,
-                                const char *BoundArch,
+                                CPUArch BoundArch,
                                 bool AtTopLevel,
                                 const char *LinkingOutput,
                                 InputInfo &Result) const {
@@ -1335,14 +1337,14 @@ void Driver::BuildJobsForAction(Compilation &C,
 
   if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
     const ToolChain *TC;
-    const char *ArchName = BAA->getArchName();
+    CPUArch Arch = BAA->getCPUArch();
 
-    if (ArchName)
-      TC = &getToolChain(C.getArgs(), ArchName);
+    if (Arch != CA_UnknownCPUArch)
+      TC = &getToolChain(C.getArgs(), Arch);
     else
       TC = &C.getDefaultToolChain();
 
-    BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
+    BuildJobsForAction(C, *BAA->begin(), TC, Arch,
                        AtTopLevel, LinkingOutput, Result);
     return;
   }
@@ -1611,7 +1613,7 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
 /// args passed to the driver and the default triple string.
 static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
                                         const ArgList &Args,
-                                        StringRef DarwinArchName) {
+                                        CPUArch DarwinArch) {
   // FIXME: Already done in Compilation *Driver::BuildCompilation
   if (const Arg *A = Args.getLastArg(options::OPT_target))
     DefaultTargetTriple = A->getValue(Args);
@@ -1621,18 +1623,21 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
   // Handle Darwin-specific options available here.
   if (Target.isOSDarwin()) {
     // If an explict Darwin arch name is given, that trumps all.
-    if (!DarwinArchName.empty()) {
+    if (DarwinArch != CA_UnknownCPUArch) {
       Target.setArch(
-        tools::darwin::getArchTypeForDarwinArchName(DarwinArchName));
+        tools::darwin::getArchTypeForDarwinCPUArch(DarwinArch));
       return Target;
     }
 
     // Handle the Darwin '-arch' flag.
     if (Arg *A = Args.getLastArg(options::OPT_arch)) {
-      llvm::Triple::ArchType DarwinArch
-        = tools::darwin::getArchTypeForDarwinArchName(A->getValue(Args));
-      if (DarwinArch != llvm::Triple::UnknownArch)
+      CPUArch DarwinCPUArch =
+        tools::darwin::getCPUArchTypeForDarwinArchName(A->getValue(Args));
+      if (DarwinCPUArch != CA_UnknownCPUArch) {
+        llvm::Triple::ArchType DarwinArch
+          = tools::darwin::getArchTypeForDarwinCPUArch(DarwinCPUArch);
         Target.setArch(DarwinArch);
+      }
     }
   }
 
@@ -1662,9 +1667,9 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
 }
 
 const ToolChain &Driver::getToolChain(const ArgList &Args,
-                                      StringRef DarwinArchName) const {
+                                      CPUArch DarwinArch) const {
   llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args,
-                                            DarwinArchName);
+                                            DarwinArch);
 
   ToolChain *&TC = ToolChains[Target.str()];
   if (!TC) {
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index eca5b3b..9d34eb9 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -695,7 +695,7 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
 }
 
 DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
-                                      const char *BoundArch) const {
+                                      CPUArch BoundArch) const {
   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
   const OptTable &Opts = getDriver().getOpts();
 
@@ -713,11 +713,14 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
     if (A->getOption().matches(options::OPT_Xarch__)) {
       // Skip this argument unless the architecture matches either the toolchain
       // triple arch, or the arch being bound.
+      CPUArch XarchCPUArch =
+        tools::darwin::getCPUArchTypeForDarwinArchName(A->getValue(Args, 0));
+      // FIXME: should this compare CPUArch instead?
       llvm::Triple::ArchType XarchArch =
-        tools::darwin::getArchTypeForDarwinArchName(A->getValue(Args, 0));
+        tools::darwin::getArchTypeForDarwinCPUArch(XarchCPUArch);
       if (!(XarchArch == getArch()  ||
-            (BoundArch && XarchArch ==
-             tools::darwin::getArchTypeForDarwinArchName(BoundArch))))
+            (BoundArch != CA_UnknownCPUArch && XarchArch ==
+             tools::darwin::getArchTypeForDarwinCPUArch(BoundArch))))
         continue;
 
       Arg *OriginalArg = A;
@@ -833,82 +836,105 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
 
   // Add the arch options based on the particular spelling of -arch, to match
   // how the driver driver works.
-  if (BoundArch) {
-    StringRef Name = BoundArch;
+  if (BoundArch != CA_UnknownCPUArch) {
     const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
     const Option MArch = Opts.getOption(options::OPT_march_EQ);
 
     // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
     // which defines the list of which architectures we accept.
-    if (Name == "ppc")
-      ;
-    else if (Name == "ppc601")
+    switch(BoundArch) {
+    case CA_PPC:
+      break;
+    case CA_PPC601:
       DAL->AddJoinedArg(0, MCpu, "601");
-    else if (Name == "ppc603")
+      break;
+    case CA_PPC603:
       DAL->AddJoinedArg(0, MCpu, "603");
-    else if (Name == "ppc604")
+      break;
+    case CA_PPC604:
       DAL->AddJoinedArg(0, MCpu, "604");
-    else if (Name == "ppc604e")
+      break;
+    case CA_PPC604e:
       DAL->AddJoinedArg(0, MCpu, "604e");
-    else if (Name == "ppc750")
+      break;
+    case CA_PPC750:
       DAL->AddJoinedArg(0, MCpu, "750");
-    else if (Name == "ppc7400")
+      break;
+    case CA_PPC7400:
       DAL->AddJoinedArg(0, MCpu, "7400");
-    else if (Name == "ppc7450")
+      break;
+    case CA_PPC7450:
       DAL->AddJoinedArg(0, MCpu, "7450");
-    else if (Name == "ppc970")
+      break;
+    case CA_PPC970:
       DAL->AddJoinedArg(0, MCpu, "970");
-
-    else if (Name == "ppc64")
+      break;
+    case CA_PPC64:
       DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
-
-    else if (Name == "i386")
-      ;
-    else if (Name == "i486")
+      break;
+    case CA_I386:
+      break;
+    case CA_I486:
       DAL->AddJoinedArg(0, MArch, "i486");
-    else if (Name == "i586")
+      break;
+    case CA_I586:
       DAL->AddJoinedArg(0, MArch, "i586");
-    else if (Name == "i686")
+      break;
+    case CA_I686:
       DAL->AddJoinedArg(0, MArch, "i686");
-    else if (Name == "pentium")
+      break;
+    case CA_Pentium:
       DAL->AddJoinedArg(0, MArch, "pentium");
-    else if (Name == "pentium2")
+      break;
+    case CA_Pentium2:
       DAL->AddJoinedArg(0, MArch, "pentium2");
-    else if (Name == "pentpro")
+      break;
+    case CA_Pentpro:
       DAL->AddJoinedArg(0, MArch, "pentiumpro");
-    else if (Name == "pentIIm3")
+      break;
+    case CA_PentIIm3:
       DAL->AddJoinedArg(0, MArch, "pentium2");
-
-    else if (Name == "x86_64")
+      break;
+    case CA_X86_64:
       DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
-
-    else if (Name == "arm")
+      break;
+    case CA_ARM:
       DAL->AddJoinedArg(0, MArch, "armv4t");
-    else if (Name == "armv4t")
+      break;
+    case CA_ARMv4t:
       DAL->AddJoinedArg(0, MArch, "armv4t");
-    else if (Name == "armv5")
+      break;
+    case CA_ARMv5:
       DAL->AddJoinedArg(0, MArch, "armv5tej");
-    else if (Name == "xscale")
+      break;
+    case CA_XScale:
       DAL->AddJoinedArg(0, MArch, "xscale");
-    else if (Name == "armv6")
+      break;
+    case CA_ARMv6:
       DAL->AddJoinedArg(0, MArch, "armv6k");
-    else if (Name == "armv7")
+      break;
+    case CA_ARMv7:
       DAL->AddJoinedArg(0, MArch, "armv7a");
-    else if (Name == "armv7f")
+      break;
+    case CA_ARMv7f:
       DAL->AddJoinedArg(0, MArch, "armv7f");
-    else if (Name == "armv7k")
+      break;
+    case CA_ARMv7k:
       DAL->AddJoinedArg(0, MArch, "armv7k");
-    else if (Name == "armv7s")
+      break;
+    case CA_ARMv7s:
       DAL->AddJoinedArg(0, MArch, "armv7s");
-
-    else
+      break;
+    case CA_UnknownCPUArch:
       llvm_unreachable("invalid Darwin arch");
+      break;
+    }
   }
 
   // Add an explicit version min argument for the deployment target. We do this
   // after argument translation because -Xarch_ arguments may add a version min
   // argument.
-  if (BoundArch)
+  if (BoundArch != CA_UnknownCPUArch)
     AddDeploymentTarget(*DAL);
 
   // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 9095433..3ad3b30 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -291,7 +291,7 @@ public:
   virtual bool hasBlocksRuntime() const;
 
   virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
-                                        const char *BoundArch) const;
+                                        CPUArch BoundArch) const;
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
                            const ActionList &Inputs) const;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 95db821..4f9fb73 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -3526,7 +3526,89 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
 }
 // Hexagon tools end.
 
-llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
+llvm::Triple::ArchType darwin::getArchTypeForDarwinCPUArch(CPUArch CA) {
+  switch (CA) {
+  case CA_UnknownCPUArch:
+    return llvm::Triple::UnknownArch;
+
+  case CA_PPC:
+  case CA_PPC601:
+  case CA_PPC603:
+  case CA_PPC604:
+  case CA_PPC604e:
+  case CA_PPC750:
+  case CA_PPC7400:
+  case CA_PPC7450:
+  case CA_PPC970:
+    return llvm::Triple::ppc;
+
+  case CA_PPC64:
+    return llvm::Triple::ppc64;
+
+  case CA_I386:
+  case CA_I486:
+  case CA_I586:
+  case CA_I686:
+  case CA_Pentium:
+  case CA_Pentium2:
+  case CA_Pentpro:
+  case CA_PentIIm3:
+    return llvm::Triple::x86;
+
+  case CA_X86_64:
+    return llvm::Triple::x86_64;
+
+  case CA_ARM:
+  case CA_ARMv4t:
+  case CA_ARMv5:
+  case CA_XScale:
+  case CA_ARMv6:
+  case CA_ARMv7:
+  case CA_ARMv7f:
+  case CA_ARMv7k:
+  case CA_ARMv7s:
+    return llvm::Triple::arm;
+  }
+}
+
+const char *darwin::getCPUArchName(CPUArch CA) {
+  switch (CA) {
+  case CA_UnknownCPUArch: return "unknown";
+
+  case CA_PPC:            return "ppc";
+  case CA_PPC601:         return "ppc601";
+  case CA_PPC603:         return "ppc603";
+  case CA_PPC604:         return "ppc604";
+  case CA_PPC604e:        return "ppc604e";
+  case CA_PPC750:         return "ppc750";
+  case CA_PPC7400:        return "ppc7400";
+  case CA_PPC7450:        return "ppc7450";
+  case CA_PPC970:         return "ppc970";
+  case CA_PPC64:          return "ppc64";
+
+  case CA_I386:           return "i386";
+  case CA_I486:           return "i486";
+  case CA_I586:           return "i586";
+  case CA_I686:           return "i686";
+  case CA_Pentium:        return "pentium";
+  case CA_Pentium2:       return "pentium2";
+  case CA_Pentpro:        return "pentpro";
+  case CA_PentIIm3:       return "pentIIm3";
+  case CA_X86_64:         return "x86_64";
+
+  case CA_ARM:            return "arm";
+  case CA_ARMv4t:         return "armv4t";
+  case CA_ARMv5:          return "armv5";
+  case CA_XScale:         return "xscale";
+  case CA_ARMv6:          return "armv6";
+  case CA_ARMv7:          return "armv7";
+  case CA_ARMv7f:         return "armv7f";
+  case CA_ARMv7k:         return "armv7k";
+  case CA_ARMv7s:         return "armv7s";
+  }
+}
+
+CPUArch darwin::getCPUArchTypeForDarwinArchName(StringRef Arch) {
   // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
   // archs which Darwin doesn't use.
 
@@ -3539,23 +3621,36 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
   // This code must be kept in sync with Clang's Darwin specific argument
   // translation.
 
-  return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
-    .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
-    .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
-    .Case("ppc64", llvm::Triple::ppc64)
-    .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
-    .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
-           llvm::Triple::x86)
-    .Case("x86_64", llvm::Triple::x86_64)
-    // This is derived from the driver driver.
-    .Cases("arm", "armv4t", "armv5", "armv6", llvm::Triple::arm)
-    .Cases("armv7", "armv7f", "armv7k", "armv7s", "xscale", llvm::Triple::arm)
-    .Case("r600", llvm::Triple::r600)
-    .Case("nvptx", llvm::Triple::nvptx)
-    .Case("nvptx64", llvm::Triple::nvptx64)
-    .Case("amdil", llvm::Triple::amdil)
-    .Case("spir", llvm::Triple::spir)
-    .Default(llvm::Triple::UnknownArch);
+  return llvm::StringSwitch<CPUArch>(Arch)
+    .Case("ppc", CA_PPC)
+    .Case("ppc601", CA_PPC601)
+    .Case("ppc603", CA_PPC603)
+    .Case("ppc604", CA_PPC604)
+    .Case("ppc604e", CA_PPC604e)
+    .Case("ppc750", CA_PPC750)
+    .Case("ppc7400", CA_PPC7400)
+    .Case("ppc7450", CA_PPC7450)
+    .Case("ppc970", CA_PPC970)
+    .Case("ppc64", CA_PPC64)
+    .Case("i386", CA_I386)
+    .Case("i486", CA_I486)
+    .Case("i586", CA_I586)
+    .Case("i686", CA_I686)
+    .Case("pentium", CA_Pentium)
+    .Case("pentium2", CA_Pentium2)
+    .Case("pentpro", CA_Pentpro)
+    .Case("pentIIm3", CA_PentIIm3)
+    .Case("x86_64", CA_X86_64)
+    .Case("arm", CA_ARM)
+    .Case("armv4t", CA_ARMv4t)
+    .Case("armv5", CA_ARMv5)
+    .Case("xscale", CA_XScale)
+    .Case("armv6", CA_ARMv6)
+    .Case("armv7", CA_ARMv7)
+    .Case("armv7f", CA_ARMv7f)
+    .Case("armv7k", CA_ARMv7k)
+    .Case("armv7s", CA_ARMv7s)
+    .Default(CA_UnknownCPUArch);
 }
 
 const char *darwin::CC1::getCC1Name(types::ID Type) const {
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 5898c66..0168de9 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -10,6 +10,7 @@
 #ifndef CLANG_LIB_DRIVER_TOOLS_H_
 #define CLANG_LIB_DRIVER_TOOLS_H_
 
+#include "clang/Driver/CPUArch.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/Types.h"
 #include "clang/Driver/Util.h"
@@ -202,7 +203,9 @@ namespace hexagon {
 
 
 namespace darwin {
-  llvm::Triple::ArchType getArchTypeForDarwinArchName(StringRef Str);
+  CPUArch getCPUArchTypeForDarwinArchName(StringRef Str);
+  const char *getCPUArchName(CPUArch Kind);
+  llvm::Triple::ArchType getArchTypeForDarwinCPUArch(CPUArch Arch);
 
   class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool {
     virtual void anchor();
