Check in LLVM r95781.
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
new file mode 100644
index 0000000..6243489
--- /dev/null
+++ b/lib/Driver/Action.cpp
@@ -0,0 +1,79 @@
+//===--- Action.cpp - Abstract compilation steps ------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Action.h"
+
+#include <cassert>
+using namespace clang::driver;
+
+Action::~Action() {
+  // FIXME: Free the inputs. The problem is that BindArchAction shares
+  // inputs; so we can't just walk the inputs.
+}
+
+const char *Action::getClassName(ActionClass AC) {
+  switch (AC) {
+  case InputClass: return "input";
+  case BindArchClass: return "bind-arch";
+  case PreprocessJobClass: return "preprocessor";
+  case PrecompileJobClass: return "precompiler";
+  case AnalyzeJobClass: return "analyzer";
+  case CompileJobClass: return "compiler";
+  case AssembleJobClass: return "assembler";
+  case LinkJobClass: return "linker";
+  case LipoJobClass: return "lipo";
+  }
+
+  assert(0 && "invalid class");
+  return 0;
+}
+
+InputAction::InputAction(const Arg &_Input, types::ID _Type)
+  : Action(InputClass, _Type), Input(_Input) {
+}
+
+BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
+  : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) {
+}
+
+JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
+  : Action(Kind, Input, Type) {
+}
+
+JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
+  : Action(Kind, Inputs, Type) {
+}
+
+PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
+  : JobAction(PreprocessJobClass, Input, OutputType) {
+}
+
+PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
+  : JobAction(PrecompileJobClass, Input, OutputType) {
+}
+
+AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
+  : JobAction(AnalyzeJobClass, Input, OutputType) {
+}
+
+CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
+  : JobAction(CompileJobClass, Input, OutputType) {
+}
+
+AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
+  : JobAction(AssembleJobClass, Input, OutputType) {
+}
+
+LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
+  : JobAction(LinkJobClass, Inputs, Type) {
+}
+
+LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
+  : JobAction(LipoJobClass, Inputs, Type) {
+}
diff --git a/lib/Driver/Arg.cpp b/lib/Driver/Arg.cpp
new file mode 100644
index 0000000..a09ba09
--- /dev/null
+++ b/lib/Driver/Arg.cpp
@@ -0,0 +1,191 @@
+//===--- Arg.cpp - Argument Implementations -----------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+
+Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index,
+         const Arg *_BaseArg)
+  : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false) {
+}
+
+Arg::~Arg() { }
+
+void Arg::dump() const {
+  llvm::errs() << "<";
+  switch (Kind) {
+  default:
+    assert(0 && "Invalid kind");
+#define P(N) case N: llvm::errs() << #N; break
+    P(FlagClass);
+    P(PositionalClass);
+    P(JoinedClass);
+    P(SeparateClass);
+    P(CommaJoinedClass);
+    P(JoinedAndSeparateClass);
+#undef P
+  }
+
+  llvm::errs() << " Opt:";
+  Opt->dump();
+
+  llvm::errs() << " Index:" << Index;
+
+  if (isa<CommaJoinedArg>(this) || isa<SeparateArg>(this))
+    llvm::errs() << " NumValues:" << getNumValues();
+
+  llvm::errs() << ">\n";
+}
+
+std::string Arg::getAsString(const ArgList &Args) const {
+  std::string Res;
+  llvm::raw_string_ostream OS(Res);
+
+  ArgStringList ASL;
+  render(Args, ASL);
+  for (ArgStringList::iterator
+         it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
+    if (it != ASL.begin())
+      OS << ' ';
+    OS << *it;
+  }
+
+  return OS.str();
+}
+
+void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
+  if (!getOption().hasNoOptAsInput()) {
+    render(Args, Output);
+    return;
+  }
+
+  for (unsigned i = 0, e = getNumValues(); i != e; ++i)
+    Output.push_back(getValue(Args, i));
+}
+
+FlagArg::FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
+  : Arg(FlagClass, Opt, Index, BaseArg) {
+}
+
+void FlagArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *FlagArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(0 && "Invalid index.");
+  return 0;
+}
+
+PositionalArg::PositionalArg(const Option *Opt, unsigned Index,
+                             const Arg *BaseArg)
+  : Arg(PositionalClass, Opt, Index, BaseArg) {
+}
+
+void PositionalArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *PositionalArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Args.getArgString(getIndex());
+}
+
+JoinedArg::JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg)
+  : Arg(JoinedClass, Opt, Index, BaseArg) {
+}
+
+void JoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
+  if (getOption().hasForceSeparateRender()) {
+    Output.push_back(getOption().getName());
+    Output.push_back(getValue(Args, 0));
+  } else {
+    Output.push_back(Args.getArgString(getIndex()));
+  }
+}
+
+const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  // FIXME: Avoid strlen.
+  return Args.getArgString(getIndex()) + strlen(getOption().getName());
+}
+
+CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
+                               const char *Str, const Arg *BaseArg)
+  : Arg(CommaJoinedClass, Opt, Index, BaseArg) {
+  const char *Prev = Str;
+  for (;; ++Str) {
+    char c = *Str;
+
+    if (!c) {
+      if (Prev != Str)
+        Values.push_back(std::string(Prev, Str));
+      break;
+    } else if (c == ',') {
+      if (Prev != Str)
+        Values.push_back(std::string(Prev, Str));
+      Prev = Str + 1;
+    }
+  }
+}
+
+void CommaJoinedArg::render(const ArgList &Args, ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+}
+
+const char *CommaJoinedArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Values[N].c_str();
+}
+
+SeparateArg::SeparateArg(const Option *Opt, unsigned Index, unsigned _NumValues,
+                         const Arg *BaseArg)
+  : Arg(SeparateClass, Opt, Index, BaseArg), NumValues(_NumValues) {
+}
+
+void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const {
+  if (getOption().hasForceJoinedRender()) {
+    assert(getNumValues() == 1 && "Cannot force joined render with > 1 args.");
+    // FIXME: Avoid std::string.
+    std::string Joined(getOption().getName());
+    Joined += Args.getArgString(getIndex());
+    Output.push_back(Args.MakeArgString(Joined.c_str()));
+  } else {
+    Output.push_back(Args.getArgString(getIndex()));
+    for (unsigned i = 0; i < NumValues; ++i)
+      Output.push_back(Args.getArgString(getIndex() + 1 + i));
+  }
+}
+
+const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  return Args.getArgString(getIndex() + 1 + N);
+}
+
+JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index,
+                                           const Arg *BaseArg)
+  : Arg(JoinedAndSeparateClass, Opt, Index, BaseArg) {
+}
+
+void JoinedAndSeparateArg::render(const ArgList &Args,
+                                  ArgStringList &Output) const {
+  Output.push_back(Args.getArgString(getIndex()));
+  Output.push_back(Args.getArgString(getIndex() + 1));
+}
+
+const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
+                                           unsigned N) const {
+  assert(N < getNumValues() && "Invalid index.");
+  if (N == 0)
+    return Args.getArgString(getIndex()) + strlen(getOption().getName());
+  return Args.getArgString(getIndex() + 1);
+}
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
new file mode 100644
index 0000000..8a57d14
--- /dev/null
+++ b/lib/Driver/ArgList.cpp
@@ -0,0 +1,240 @@
+//===--- ArgList.cpp - Argument List Management -------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/Option.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+
+void arg_iterator::SkipToNextArg() {
+  for (; Current != Args.end(); ++Current) {
+    // Done if there are no filters.
+    if (!Id0.isValid())
+      break;
+
+    // Otherwise require a match.
+    const Option &O = (*Current)->getOption();
+    if (O.matches(Id0) ||
+        (Id1.isValid() && O.matches(Id1)) ||
+        (Id2.isValid() && O.matches(Id2)))
+      break;
+  }
+}
+
+//
+
+ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
+}
+
+ArgList::~ArgList() {
+}
+
+void ArgList::append(Arg *A) {
+  Args.push_back(A);
+}
+
+Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
+  // FIXME: Make search efficient?
+  for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
+    if ((*it)->getOption().matches(Id))
+      return *it;
+  return 0;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id) const {
+  Arg *A = getLastArgNoClaim(Id);
+  if (A)
+    A->claim();
+  return A;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
+  Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1);
+
+  if (A0 && A1)
+    Res = A0->getIndex() > A1->getIndex() ? A0 : A1;
+  else
+    Res = A0 ? A0 : A1;
+
+  if (Res)
+    Res->claim();
+
+  return Res;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
+                         OptSpecifier Id2) const {
+  Arg *Res = 0;
+  Arg *A0 = getLastArgNoClaim(Id0);
+  Arg *A1 = getLastArgNoClaim(Id1);
+  Arg *A2 = getLastArgNoClaim(Id2);
+
+  int A0Idx = A0 ? A0->getIndex() : -1;
+  int A1Idx = A1 ? A1->getIndex() : -1;
+  int A2Idx = A2 ? A2->getIndex() : -1;
+
+  if (A0Idx > A1Idx) {
+    if (A0Idx > A2Idx)
+      Res = A0;
+    else if (A2Idx != -1)
+      Res = A2;
+  } else {
+    if (A1Idx > A2Idx)
+      Res = A1;
+    else if (A2Idx != -1)
+      Res = A2;
+  }
+
+  if (Res)
+    Res->claim();
+
+  return Res;
+}
+
+bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
+  if (Arg *A = getLastArg(Pos, Neg))
+    return A->getOption().matches(Pos);
+  return Default;
+}
+
+void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
+  if (Arg *A = getLastArg(Id)) {
+    A->claim();
+    A->render(*this, Output);
+  }
+}
+
+void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
+                         OptSpecifier Id1, OptSpecifier Id2) const {
+  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
+         ie = filtered_end(); it != ie; ++it) {
+    it->claim();
+    it->render(*this, Output);
+  }
+}
+
+void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
+                              OptSpecifier Id1, OptSpecifier Id2) const {
+  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
+         ie = filtered_end(); it != ie; ++it) {
+    it->claim();
+    for (unsigned i = 0, e = it->getNumValues(); i != e; ++i)
+      Output.push_back(it->getValue(*this, i));
+  }
+}
+
+void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
+                                   const char *Translation,
+                                   bool Joined) const {
+  for (arg_iterator it = filtered_begin(Id0),
+         ie = filtered_end(); it != ie; ++it) {
+    it->claim();
+
+    if (Joined) {
+      Output.push_back(MakeArgString(llvm::StringRef(Translation) +
+                                     it->getValue(*this, 0)));
+    } else {
+      Output.push_back(Translation);
+      Output.push_back(it->getValue(*this, 0));
+    }
+  }
+}
+
+void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
+  for (arg_iterator it = filtered_begin(Id0),
+         ie = filtered_end(); it != ie; ++it)
+      it->claim();
+}
+
+const char *ArgList::MakeArgString(const llvm::Twine &T) const {
+  llvm::SmallString<256> Str;
+  T.toVector(Str);
+  return MakeArgString(Str.str());
+}
+
+//
+
+InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
+  : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin) {
+  ArgStrings.append(ArgBegin, ArgEnd);
+}
+
+InputArgList::~InputArgList() {
+  // An InputArgList always owns its arguments.
+  for (iterator it = begin(), ie = end(); it != ie; ++it)
+    delete *it;
+}
+
+unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
+  unsigned Index = ArgStrings.size();
+
+  // Tuck away so we have a reliable const char *.
+  SynthesizedStrings.push_back(String0);
+  ArgStrings.push_back(SynthesizedStrings.back().c_str());
+
+  return Index;
+}
+
+unsigned InputArgList::MakeIndex(llvm::StringRef String0,
+                                 llvm::StringRef String1) const {
+  unsigned Index0 = MakeIndex(String0);
+  unsigned Index1 = MakeIndex(String1);
+  assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
+  (void) Index1;
+  return Index0;
+}
+
+const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
+  return getArgString(MakeIndex(Str));
+}
+
+//
+
+DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy)
+  : ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs),
+    BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) {
+}
+
+DerivedArgList::~DerivedArgList() {
+  // We only own the arguments we explicitly synthesized.
+  for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
+       it != ie; ++it)
+    delete *it;
+}
+
+const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
+  return BaseArgs.MakeArgString(Str);
+}
+
+Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
+  return new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
+}
+
+Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
+                                       llvm::StringRef Value) const {
+  return new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
+}
+
+Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
+                                     llvm::StringRef Value) const {
+  return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
+                         BaseArg);
+}
+
+Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
+                                   llvm::StringRef Value) const {
+  std::string Joined(Opt->getName());
+  Joined += Value;
+  return new JoinedArg(Opt, BaseArgs.MakeIndex(Joined.c_str()), BaseArg);
+}
diff --git a/lib/Driver/CC1Options.cpp b/lib/Driver/CC1Options.cpp
new file mode 100644
index 0000000..0e98bb9
--- /dev/null
+++ b/lib/Driver/CC1Options.cpp
@@ -0,0 +1,38 @@
+//===--- CC1Options.cpp - Clang CC1 Options Table -----------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/OptTable.h"
+using namespace clang;
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::driver::cc1options;
+
+static const OptTable::Info CC1InfoTable[] = {
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+               HELPTEXT, METAVAR)   \
+  { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+    OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/CC1Options.inc"
+};
+
+namespace {
+
+class CC1OptTable : public OptTable {
+public:
+  CC1OptTable()
+    : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createCC1OptTable() {
+  return new CC1OptTable();
+}
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
new file mode 100644
index 0000000..60d8e9c
--- /dev/null
+++ b/lib/Driver/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangDriver
+  Action.cpp
+  Arg.cpp
+  ArgList.cpp
+  CC1Options.cpp
+  Compilation.cpp
+  Driver.cpp
+  DriverOptions.cpp
+  HostInfo.cpp
+  Job.cpp
+  OptTable.cpp
+  Option.cpp
+  Phases.cpp
+  Tool.cpp
+  ToolChain.cpp
+  ToolChains.cpp
+  Tools.cpp
+  Types.cpp
+  )
+
+add_dependencies(clangDriver ClangDiagnosticDriver ClangDriverOptions ClangCC1Options)
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
new file mode 100644
index 0000000..b819cda
--- /dev/null
+++ b/lib/Driver/Compilation.cpp
@@ -0,0 +1,167 @@
+//===--- Compilation.cpp - Compilation Task Implementation --------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Compilation.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Program.h"
+#include <sys/stat.h>
+#include <errno.h>
+using namespace clang::driver;
+
+Compilation::Compilation(const Driver &D,
+                         const ToolChain &_DefaultToolChain,
+                         InputArgList *_Args)
+  : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args) {
+}
+
+Compilation::~Compilation() {
+  delete Args;
+
+  // Free any derived arg lists.
+  for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+                      DerivedArgList*>::iterator it = TCArgs.begin(),
+         ie = TCArgs.end(); it != ie; ++it)
+    delete it->second;
+
+  // Free the actions, if built.
+  for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
+       it != ie; ++it)
+    delete *it;
+}
+
+const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
+                                                       const char *BoundArch) {
+  if (!TC)
+    TC = &DefaultToolChain;
+
+  DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
+  if (!Entry)
+    Entry = TC->TranslateArgs(*Args, BoundArch);
+
+  return *Entry;
+}
+
+void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
+                           const char *Terminator, bool Quote) const {
+  if (const Command *C = dyn_cast<Command>(&J)) {
+    OS << " \"" << C->getExecutable() << '"';
+    for (ArgStringList::const_iterator it = C->getArguments().begin(),
+           ie = C->getArguments().end(); it != ie; ++it) {
+      if (Quote)
+        OS << " \"" << *it << '"';
+      else
+        OS << ' ' << *it;
+    }
+    OS << Terminator;
+  } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
+    for (PipedJob::const_iterator
+           it = PJ->begin(), ie = PJ->end(); it != ie; ++it)
+      PrintJob(OS, **it, (it + 1 != PJ->end()) ? " |\n" : "\n", Quote);
+  } else {
+    const JobList *Jobs = cast<JobList>(&J);
+    for (JobList::const_iterator
+           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
+      PrintJob(OS, **it, Terminator, Quote);
+  }
+}
+
+bool Compilation::CleanupFileList(const ArgStringList &Files,
+                                  bool IssueErrors) const {
+  bool Success = true;
+
+  for (ArgStringList::const_iterator
+         it = Files.begin(), ie = Files.end(); it != ie; ++it) {
+
+    llvm::sys::Path P(*it);
+    std::string Error;
+
+    if (!P.isRegularFile()) {
+      // If we have a special file in our list, i.e. /dev/null
+      //  then don't call eraseFromDisk() and just continue.
+      continue;
+    }
+
+    if (P.eraseFromDisk(false, &Error)) {
+      // Failure is only failure if the file doesn't exist. There is a
+      // race condition here due to the limited interface of
+      // llvm::sys::Path, we want to know if the removal gave E_NOENT.
+
+      // FIXME: Grumble, P.exists() is broken. PR3837.
+      struct stat buf;
+      if (::stat(P.c_str(), &buf) == 0
+          || errno != ENOENT) {
+        if (IssueErrors)
+          getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+            << Error;
+        Success = false;
+      }
+    }
+  }
+
+  return Success;
+}
+
+int Compilation::ExecuteCommand(const Command &C,
+                                const Command *&FailingCommand) const {
+  llvm::sys::Path Prog(C.getExecutable());
+  const char **Argv = new const char*[C.getArguments().size() + 2];
+  Argv[0] = C.getExecutable();
+  std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
+  Argv[C.getArguments().size() + 1] = 0;
+
+  if (getDriver().CCCEcho || getArgs().hasArg(options::OPT_v))
+    PrintJob(llvm::errs(), C, "\n", false);
+
+  std::string Error;
+  int Res =
+    llvm::sys::Program::ExecuteAndWait(Prog, Argv,
+                                       /*env*/0, /*redirects*/0,
+                                       /*secondsToWait*/0, /*memoryLimit*/0,
+                                       &Error);
+  if (!Error.empty()) {
+    assert(Res && "Error string set with 0 result code!");
+    getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
+  }
+
+  if (Res)
+    FailingCommand = &C;
+
+  delete[] Argv;
+  return Res;
+}
+
+int Compilation::ExecuteJob(const Job &J,
+                            const Command *&FailingCommand) const {
+  if (const Command *C = dyn_cast<Command>(&J)) {
+    return ExecuteCommand(*C, FailingCommand);
+  } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
+    // Piped commands with a single job are easy.
+    if (PJ->size() == 1)
+      return ExecuteCommand(**PJ->begin(), FailingCommand);
+
+    FailingCommand = *PJ->begin();
+    getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe";
+    return 1;
+  } else {
+    const JobList *Jobs = cast<JobList>(&J);
+    for (JobList::const_iterator
+           it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
+      if (int Res = ExecuteJob(**it, FailingCommand))
+        return Res;
+    return 0;
+  }
+}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
new file mode 100644
index 0000000..a2fc5aa
--- /dev/null
+++ b/lib/Driver/Driver.cpp
@@ -0,0 +1,1226 @@
+//===--- Driver.cpp - Clang GCC Compatible Driver -----------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Driver.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Types.h"
+
+#include "clang/Basic/Version.h"
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
+
+#include "InputInfo.h"
+
+#include <map>
+
+using namespace clang::driver;
+using namespace clang;
+
+// Used to set values for "production" clang, for releases.
+// #define USE_PRODUCTION_CLANG
+
+Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
+               llvm::StringRef _DefaultHostTriple,
+               llvm::StringRef _DefaultImageName,
+               bool IsProduction, Diagnostic &_Diags)
+  : Opts(createDriverOptTable()), Diags(_Diags),
+    Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
+    DefaultImageName(_DefaultImageName),
+    Host(0),
+    CCCGenericGCCName("gcc"), CCCIsCXX(false), CCCEcho(false),
+    CCCPrintBindings(false), CheckInputsExist(true), CCCUseClang(true),
+    CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true),
+    SuppressMissingInputWarning(false) {
+  if (IsProduction) {
+    // In a "production" build, only use clang on architectures we expect to
+    // work, and don't use clang C++.
+    //
+    // During development its more convenient to always have the driver use
+    // clang, but we don't want users to be confused when things don't work, or
+    // to file bugs for things we don't support.
+    CCCClangArchs.insert(llvm::Triple::x86);
+    CCCClangArchs.insert(llvm::Triple::x86_64);
+    CCCClangArchs.insert(llvm::Triple::arm);
+
+    CCCUseClangCXX = false;
+  }
+
+  // Compute the path to the resource directory.
+  llvm::sys::Path P(Dir);
+  P.eraseComponent(); // Remove /bin from foo/bin
+  P.appendComponent("lib");
+  P.appendComponent("clang");
+  P.appendComponent(CLANG_VERSION_STRING);
+  ResourceDir = P.str();
+}
+
+Driver::~Driver() {
+  delete Opts;
+  delete Host;
+}
+
+InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
+                                      const char **ArgEnd) {
+  llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
+  unsigned MissingArgIndex, MissingArgCount;
+  InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd,
+                                           MissingArgIndex, MissingArgCount);
+
+  // Check for missing argument error.
+  if (MissingArgCount)
+    Diag(clang::diag::err_drv_missing_argument)
+      << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+  // Check for unsupported options.
+  for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
+       it != ie; ++it) {
+    Arg *A = *it;
+    if (A->getOption().isUnsupported()) {
+      Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
+      continue;
+    }
+  }
+
+  return Args;
+}
+
+Compilation *Driver::BuildCompilation(int argc, const char **argv) {
+  llvm::PrettyStackTraceString CrashInfo("Compilation construction");
+
+  // FIXME: Handle environment options which effect driver behavior, somewhere
+  // (client?). GCC_EXEC_PREFIX, COMPILER_PATH, LIBRARY_PATH, LPATH,
+  // CC_PRINT_OPTIONS.
+
+  // FIXME: What are we going to do with -V and -b?
+
+  // FIXME: This stuff needs to go into the Compilation, not the driver.
+  bool CCCPrintOptions = false, CCCPrintActions = false;
+
+  const char **Start = argv + 1, **End = argv + argc;
+  const char *HostTriple = DefaultHostTriple.c_str();
+
+  InputArgList *Args = ParseArgStrings(Start, End);
+
+  // -no-canonical-prefixes is used very early in main.
+  Args->ClaimAllArgs(options::OPT_no_canonical_prefixes);
+
+  // Extract -ccc args.
+  //
+  // FIXME: We need to figure out where this behavior should live. Most of it
+  // should be outside in the client; the parts that aren't should have proper
+  // options, either by introducing new ones or by overloading gcc ones like -V
+  // or -b.
+  CCCPrintOptions = Args->hasArg(options::OPT_ccc_print_options);
+  CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases);
+  CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings);
+  CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX;
+  CCCEcho = Args->hasArg(options::OPT_ccc_echo);
+  if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name))
+    CCCGenericGCCName = A->getValue(*Args);
+  CCCUseClangCXX = Args->hasFlag(options::OPT_ccc_clang_cxx,
+                                 options::OPT_ccc_no_clang_cxx,
+                                 CCCUseClangCXX);
+  CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch,
+                            options::OPT_ccc_pch_is_pth);
+  CCCUseClang = !Args->hasArg(options::OPT_ccc_no_clang);
+  CCCUseClangCPP = !Args->hasArg(options::OPT_ccc_no_clang_cpp);
+  if (const Arg *A = Args->getLastArg(options::OPT_ccc_clang_archs)) {
+    llvm::StringRef Cur = A->getValue(*Args);
+
+    CCCClangArchs.clear();
+    while (!Cur.empty()) {
+      std::pair<llvm::StringRef, llvm::StringRef> Split = Cur.split(',');
+
+      if (!Split.first.empty()) {
+        llvm::Triple::ArchType Arch =
+          llvm::Triple(Split.first, "", "").getArch();
+
+        if (Arch == llvm::Triple::UnknownArch) {
+          Diag(clang::diag::err_drv_invalid_arch_name) << Arch;
+          continue;
+        }
+
+        CCCClangArchs.insert(Arch);
+      }
+
+      Cur = Split.second;
+    }
+  }
+  if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple))
+    HostTriple = A->getValue(*Args);
+  if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
+    Dir = A->getValue(*Args);
+
+  Host = GetHostInfo(HostTriple);
+
+  // The compilation takes ownership of Args.
+  Compilation *C = new Compilation(*this, *Host->CreateToolChain(*Args), Args);
+
+  // FIXME: This behavior shouldn't be here.
+  if (CCCPrintOptions) {
+    PrintOptions(C->getArgs());
+    return C;
+  }
+
+  if (!HandleImmediateArgs(*C))
+    return C;
+
+  // Construct the list of abstract actions to perform for this compilation. We
+  // avoid passing a Compilation here simply to enforce the abstraction that
+  // pipelining is not host or toolchain dependent (other than the driver driver
+  // test).
+  if (Host->useDriverDriver())
+    BuildUniversalActions(C->getArgs(), C->getActions());
+  else
+    BuildActions(C->getArgs(), C->getActions());
+
+  if (CCCPrintActions) {
+    PrintActions(*C);
+    return C;
+  }
+
+  BuildJobs(*C);
+
+  return C;
+}
+
+int Driver::ExecuteCompilation(const Compilation &C) const {
+  // Just print if -### was present.
+  if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
+    C.PrintJob(llvm::errs(), C.getJobs(), "\n", true);
+    return 0;
+  }
+
+  // If there were errors building the compilation, quit now.
+  if (getDiags().getNumErrors())
+    return 1;
+
+  const Command *FailingCommand = 0;
+  int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
+
+  // Remove temp files.
+  C.CleanupFileList(C.getTempFiles());
+
+  // If the compilation failed, remove result files as well.
+  if (Res != 0 && !C.getArgs().hasArg(options::OPT_save_temps))
+    C.CleanupFileList(C.getResultFiles(), true);
+
+  // Print extra information about abnormal failures, if possible.
+  if (Res) {
+    // This is ad-hoc, but we don't want to be excessively noisy. If the result
+    // status was 1, assume the command failed normally. In particular, if it
+    // was the compiler then assume it gave a reasonable error code. Failures in
+    // other tools are less common, and they generally have worse diagnostics,
+    // so always print the diagnostic there.
+    const Action &Source = FailingCommand->getSource();
+    bool IsFriendlyTool = (isa<PreprocessJobAction>(Source) ||
+                           isa<PrecompileJobAction>(Source) ||
+                           isa<AnalyzeJobAction>(Source) ||
+                           isa<CompileJobAction>(Source));
+
+    if (!IsFriendlyTool || Res != 1) {
+      // FIXME: See FIXME above regarding result code interpretation.
+      if (Res < 0)
+        Diag(clang::diag::err_drv_command_signalled)
+          << Source.getClassName() << -Res;
+      else
+        Diag(clang::diag::err_drv_command_failed)
+          << Source.getClassName() << Res;
+    }
+  }
+
+  return Res;
+}
+
+void Driver::PrintOptions(const ArgList &Args) const {
+  unsigned i = 0;
+  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+       it != ie; ++it, ++i) {
+    Arg *A = *it;
+    llvm::errs() << "Option " << i << " - "
+                 << "Name: \"" << A->getOption().getName() << "\", "
+                 << "Values: {";
+    for (unsigned j = 0; j < A->getNumValues(); ++j) {
+      if (j)
+        llvm::errs() << ", ";
+      llvm::errs() << '"' << A->getValue(Args, j) << '"';
+    }
+    llvm::errs() << "}\n";
+  }
+}
+
+// FIXME: Move -ccc options to real options in the .td file (or eliminate), and
+// then move to using OptTable::PrintHelp.
+void Driver::PrintHelp(bool ShowHidden) const {
+  getOpts().PrintHelp(llvm::outs(), Name.c_str(),
+                      "clang \"gcc-compatible\" driver", ShowHidden);
+}
+
+void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
+  // FIXME: The following handlers should use a callback mechanism, we don't
+  // know what the client would like to do.
+  OS << getClangFullVersion() << '\n';
+  const ToolChain &TC = C.getDefaultToolChain();
+  OS << "Target: " << TC.getTripleString() << '\n';
+
+  // Print the threading model.
+  //
+  // FIXME: Implement correctly.
+  OS << "Thread model: " << "posix" << '\n';
+}
+
+bool Driver::HandleImmediateArgs(const Compilation &C) {
+  // The order these options are handled in in gcc is all over the place, but we
+  // don't expect inconsistencies w.r.t. that to matter in practice.
+
+  if (C.getArgs().hasArg(options::OPT_dumpversion)) {
+    llvm::outs() << CLANG_VERSION_STRING "\n";
+    return false;
+  }
+
+  if (C.getArgs().hasArg(options::OPT__help) ||
+      C.getArgs().hasArg(options::OPT__help_hidden)) {
+    PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
+    return false;
+  }
+
+  if (C.getArgs().hasArg(options::OPT__version)) {
+    // Follow gcc behavior and use stdout for --version and stderr for -v.
+    PrintVersion(C, llvm::outs());
+    return false;
+  }
+
+  if (C.getArgs().hasArg(options::OPT_v) ||
+      C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
+    PrintVersion(C, llvm::errs());
+    SuppressMissingInputWarning = true;
+  }
+
+  const ToolChain &TC = C.getDefaultToolChain();
+  if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
+    llvm::outs() << "programs: =";
+    for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(),
+           ie = TC.getProgramPaths().end(); it != ie; ++it) {
+      if (it != TC.getProgramPaths().begin())
+        llvm::outs() << ':';
+      llvm::outs() << *it;
+    }
+    llvm::outs() << "\n";
+    llvm::outs() << "libraries: =";
+    for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
+           ie = TC.getFilePaths().end(); it != ie; ++it) {
+      if (it != TC.getFilePaths().begin())
+        llvm::outs() << ':';
+      llvm::outs() << *it;
+    }
+    llvm::outs() << "\n";
+    return false;
+  }
+
+  // FIXME: The following handlers should use a callback mechanism, we don't
+  // know what the client would like to do.
+  if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
+    llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC) << "\n";
+    return false;
+  }
+
+  if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
+    llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC) << "\n";
+    return false;
+  }
+
+  if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
+    llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
+    return false;
+  }
+
+  if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
+    // FIXME: We need tool chain support for this.
+    llvm::outs() << ".;\n";
+
+    switch (C.getDefaultToolChain().getTriple().getArch()) {
+    default:
+      break;
+
+    case llvm::Triple::x86_64:
+      llvm::outs() << "x86_64;@m64" << "\n";
+      break;
+
+    case llvm::Triple::ppc64:
+      llvm::outs() << "ppc64;@m64" << "\n";
+      break;
+    }
+    return false;
+  }
+
+  // FIXME: What is the difference between print-multi-directory and
+  // print-multi-os-directory?
+  if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
+      C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+    switch (C.getDefaultToolChain().getTriple().getArch()) {
+    default:
+    case llvm::Triple::x86:
+    case llvm::Triple::ppc:
+      llvm::outs() << "." << "\n";
+      break;
+
+    case llvm::Triple::x86_64:
+      llvm::outs() << "x86_64" << "\n";
+      break;
+
+    case llvm::Triple::ppc64:
+      llvm::outs() << "ppc64" << "\n";
+      break;
+    }
+    return false;
+  }
+
+  return true;
+}
+
+static unsigned PrintActions1(const Compilation &C, Action *A,
+                              std::map<Action*, unsigned> &Ids) {
+  if (Ids.count(A))
+    return Ids[A];
+
+  std::string str;
+  llvm::raw_string_ostream os(str);
+
+  os << Action::getClassName(A->getKind()) << ", ";
+  if (InputAction *IA = dyn_cast<InputAction>(A)) {
+    os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\"";
+  } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
+    os << '"' << (BIA->getArchName() ? BIA->getArchName() :
+                  C.getDefaultToolChain().getArchName()) << '"'
+       << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
+  } else {
+    os << "{";
+    for (Action::iterator it = A->begin(), ie = A->end(); it != ie;) {
+      os << PrintActions1(C, *it, Ids);
+      ++it;
+      if (it != ie)
+        os << ", ";
+    }
+    os << "}";
+  }
+
+  unsigned Id = Ids.size();
+  Ids[A] = Id;
+  llvm::errs() << Id << ": " << os.str() << ", "
+               << types::getTypeName(A->getType()) << "\n";
+
+  return Id;
+}
+
+void Driver::PrintActions(const Compilation &C) const {
+  std::map<Action*, unsigned> Ids;
+  for (ActionList::const_iterator it = C.getActions().begin(),
+         ie = C.getActions().end(); it != ie; ++it)
+    PrintActions1(C, *it, Ids);
+}
+
+void Driver::BuildUniversalActions(const ArgList &Args,
+                                   ActionList &Actions) const {
+  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;
+  llvm::SmallVector<const char *, 4> Archs;
+  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+       it != ie; ++it) {
+    Arg *A = *it;
+
+    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 =
+        llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+      if (Arch == llvm::Triple::UnknownArch) {
+        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));
+    }
+  }
+
+  // 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(0);
+
+  // 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"
+  // files they wrote then we could detect the conflict these cause downstream.
+  if (Archs.size() > 1) {
+    // No recovery needed, the point of this is just to prevent
+    // overwriting the same files.
+    if (const Arg *A = Args.getLastArg(options::OPT_save_temps))
+      Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs)
+        << A->getAsString(Args);
+  }
+
+  ActionList SingleActions;
+  BuildActions(Args, SingleActions);
+
+  // Add in arch binding and lipo (if necessary) for every top level action.
+  for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) {
+    Action *Act = SingleActions[i];
+
+    // Make sure we can lipo this kind of output. If not (and it is an actual
+    // output) then we disallow, since we can't create an output file with the
+    // right name without overwriting it. We could remove this oddity by just
+    // changing the output names to include the arch, which would also fix
+    // -save-temps. Compatibility wins for now.
+
+    if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
+      Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
+        << types::getTypeName(Act->getType());
+
+    ActionList Inputs;
+    for (unsigned i = 0, e = Archs.size(); i != e; ++i)
+      Inputs.push_back(new BindArchAction(Act, Archs[i]));
+
+    // Lipo if necessary, we do it this way because we need to set the arch flag
+    // so that -Xarch_ gets overwritten.
+    if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
+      Actions.append(Inputs.begin(), Inputs.end());
+    else
+      Actions.push_back(new LipoJobAction(Inputs, Act->getType()));
+  }
+}
+
+void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
+  llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
+  // Start by constructing the list of inputs and their types.
+
+  // Track the current user specified (-x) input. We also explicitly track the
+  // argument used to set the type; we only want to claim the type when we
+  // actually use it, so we warn about unused -x arguments.
+  types::ID InputType = types::TY_Nothing;
+  Arg *InputTypeArg = 0;
+
+  llvm::SmallVector<std::pair<types::ID, const Arg*>, 16> Inputs;
+  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+       it != ie; ++it) {
+    Arg *A = *it;
+
+    if (isa<InputOption>(A->getOption())) {
+      const char *Value = A->getValue(Args);
+      types::ID Ty = types::TY_INVALID;
+
+      // Infer the input type if necessary.
+      if (InputType == types::TY_Nothing) {
+        // If there was an explicit arg for this, claim it.
+        if (InputTypeArg)
+          InputTypeArg->claim();
+
+        // stdin must be handled specially.
+        if (memcmp(Value, "-", 2) == 0) {
+          // If running with -E, treat as a C input (this changes the builtin
+          // macros, for example). This may be overridden by -ObjC below.
+          //
+          // Otherwise emit an error but still use a valid type to avoid
+          // spurious errors (e.g., no inputs).
+          if (!Args.hasArgNoClaim(options::OPT_E))
+            Diag(clang::diag::err_drv_unknown_stdin_type);
+          Ty = types::TY_C;
+        } else {
+          // Otherwise lookup by extension, and fallback to ObjectType if not
+          // found. We use a host hook here because Darwin at least has its own
+          // idea of what .s is.
+          if (const char *Ext = strrchr(Value, '.'))
+            Ty = Host->lookupTypeForExtension(Ext + 1);
+
+          if (Ty == types::TY_INVALID)
+            Ty = types::TY_Object;
+        }
+
+        // -ObjC and -ObjC++ override the default language, but only for "source
+        // files". We just treat everything that isn't a linker input as a
+        // source file.
+        //
+        // FIXME: Clean this up if we move the phase sequence into the type.
+        if (Ty != types::TY_Object) {
+          if (Args.hasArg(options::OPT_ObjC))
+            Ty = types::TY_ObjC;
+          else if (Args.hasArg(options::OPT_ObjCXX))
+            Ty = types::TY_ObjCXX;
+        }
+      } else {
+        assert(InputTypeArg && "InputType set w/o InputTypeArg");
+        InputTypeArg->claim();
+        Ty = InputType;
+      }
+
+      // Check that the file exists, if enabled.
+      if (CheckInputsExist && memcmp(Value, "-", 2) != 0 &&
+          !llvm::sys::Path(Value).exists())
+        Diag(clang::diag::err_drv_no_such_file) << A->getValue(Args);
+      else
+        Inputs.push_back(std::make_pair(Ty, A));
+
+    } else if (A->getOption().isLinkerInput()) {
+      // Just treat as object type, we could make a special type for this if
+      // necessary.
+      Inputs.push_back(std::make_pair(types::TY_Object, A));
+
+    } else if (A->getOption().matches(options::OPT_x)) {
+      InputTypeArg = A;
+      InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args));
+
+      // Follow gcc behavior and treat as linker input for invalid -x
+      // options. Its not clear why we shouldn't just revert to unknown; but
+      // this isn't very important, we might as well be bug comatible.
+      if (!InputType) {
+        Diag(clang::diag::err_drv_unknown_language) << A->getValue(Args);
+        InputType = types::TY_Object;
+      }
+    }
+  }
+
+  if (!SuppressMissingInputWarning && Inputs.empty()) {
+    Diag(clang::diag::err_drv_no_input_files);
+    return;
+  }
+
+  // Determine which compilation mode we are in. We look for options which
+  // affect the phase, starting with the earliest phases, and record which
+  // option we used to determine the final phase.
+  Arg *FinalPhaseArg = 0;
+  phases::ID FinalPhase;
+
+  // -{E,M,MM} only run the preprocessor.
+  if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) ||
+      (FinalPhaseArg = Args.getLastArg(options::OPT_M)) ||
+      (FinalPhaseArg = Args.getLastArg(options::OPT_MM))) {
+    FinalPhase = phases::Preprocess;
+
+    // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
+  } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) ||
+             (FinalPhaseArg = Args.getLastArg(options::OPT__analyze,
+                                              options::OPT__analyze_auto)) ||
+             (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) ||
+             (FinalPhaseArg = Args.getLastArg(options::OPT_S))) {
+    FinalPhase = phases::Compile;
+
+    // -c only runs up to the assembler.
+  } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) {
+    FinalPhase = phases::Assemble;
+
+    // Otherwise do everything.
+  } else
+    FinalPhase = phases::Link;
+
+  // Reject -Z* at the top level, these options should never have been exposed
+  // by gcc.
+  if (Arg *A = Args.getLastArg(options::OPT_Z_Joined))
+    Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args);
+
+  // Construct the actions to perform.
+  ActionList LinkerInputs;
+  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+    types::ID InputType = Inputs[i].first;
+    const Arg *InputArg = Inputs[i].second;
+
+    unsigned NumSteps = types::getNumCompilationPhases(InputType);
+    assert(NumSteps && "Invalid number of steps!");
+
+    // If the first step comes after the final phase we are doing as part of
+    // this compilation, warn the user about it.
+    phases::ID InitialPhase = types::getCompilationPhase(InputType, 0);
+    if (InitialPhase > FinalPhase) {
+      // Claim here to avoid the more general unused warning.
+      InputArg->claim();
+
+      // Special case '-E' warning on a previously preprocessed file to make
+      // more sense.
+      if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess &&
+          getPreprocessedType(InputType) == types::TY_INVALID)
+        Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
+          << InputArg->getAsString(Args)
+          << FinalPhaseArg->getOption().getName();
+      else
+        Diag(clang::diag::warn_drv_input_file_unused)
+          << InputArg->getAsString(Args)
+          << getPhaseName(InitialPhase)
+          << FinalPhaseArg->getOption().getName();
+      continue;
+    }
+
+    // Build the pipeline for this file.
+    llvm::OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
+    for (unsigned i = 0; i != NumSteps; ++i) {
+      phases::ID Phase = types::getCompilationPhase(InputType, i);
+
+      // We are done if this step is past what the user requested.
+      if (Phase > FinalPhase)
+        break;
+
+      // Queue linker inputs.
+      if (Phase == phases::Link) {
+        assert(i + 1 == NumSteps && "linking must be final compilation step.");
+        LinkerInputs.push_back(Current.take());
+        break;
+      }
+
+      // Some types skip the assembler phase (e.g., llvm-bc), but we can't
+      // encode this in the steps because the intermediate type depends on
+      // arguments. Just special case here.
+      if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm)
+        continue;
+
+      // Otherwise construct the appropriate action.
+      Current.reset(ConstructPhaseAction(Args, Phase, Current.take()));
+      if (Current->getType() == types::TY_Nothing)
+        break;
+    }
+
+    // If we ended with something, add to the output list.
+    if (Current)
+      Actions.push_back(Current.take());
+  }
+
+  // Add a link action if necessary.
+  if (!LinkerInputs.empty())
+    Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+
+  // If we are linking, claim any options which are obviously only used for
+  // compilation.
+  if (FinalPhase == phases::Link)
+    Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
+}
+
+Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+                                     Action *Input) const {
+  llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
+  // Build the appropriate action.
+  switch (Phase) {
+  case phases::Link: assert(0 && "link action invalid here.");
+  case phases::Preprocess: {
+    types::ID OutputTy;
+    // -{M, MM} alter the output type.
+    if (Args.hasArg(options::OPT_M) || Args.hasArg(options::OPT_MM)) {
+      OutputTy = types::TY_Dependencies;
+    } else {
+      OutputTy = types::getPreprocessedType(Input->getType());
+      assert(OutputTy != types::TY_INVALID &&
+             "Cannot preprocess this input type!");
+    }
+    return new PreprocessJobAction(Input, OutputTy);
+  }
+  case phases::Precompile:
+    return new PrecompileJobAction(Input, types::TY_PCH);
+  case phases::Compile: {
+    bool HasO4 = false;
+    if (const Arg *A = Args.getLastArg(options::OPT_O_Group))
+      HasO4 = A->getOption().matches(options::OPT_O4);
+
+    if (Args.hasArg(options::OPT_fsyntax_only)) {
+      return new CompileJobAction(Input, types::TY_Nothing);
+    } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) {
+      return new AnalyzeJobAction(Input, types::TY_Plist);
+    } else if (Args.hasArg(options::OPT_emit_ast)) {
+      return new CompileJobAction(Input, types::TY_AST);
+    } else if (Args.hasArg(options::OPT_emit_llvm) ||
+               Args.hasArg(options::OPT_flto) || HasO4) {
+      types::ID Output =
+        Args.hasArg(options::OPT_S) ? types::TY_LLVMAsm : types::TY_LLVMBC;
+      return new CompileJobAction(Input, Output);
+    } else {
+      return new CompileJobAction(Input, types::TY_PP_Asm);
+    }
+  }
+  case phases::Assemble:
+    return new AssembleJobAction(Input, types::TY_Object);
+  }
+
+  assert(0 && "invalid phase in ConstructPhaseAction");
+  return 0;
+}
+
+void Driver::BuildJobs(Compilation &C) const {
+  llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+  bool SaveTemps = C.getArgs().hasArg(options::OPT_save_temps);
+  bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
+
+  // FIXME: Pipes are forcibly disabled until we support executing them.
+  if (!CCCPrintBindings)
+    UsePipes = false;
+
+  // -save-temps inhibits pipes.
+  if (SaveTemps && UsePipes)
+    Diag(clang::diag::warn_drv_pipe_ignored_with_save_temps);
+
+  Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+
+  // It is an error to provide a -o option if we are making multiple output
+  // files.
+  if (FinalOutput) {
+    unsigned NumOutputs = 0;
+    for (ActionList::const_iterator it = C.getActions().begin(),
+           ie = C.getActions().end(); it != ie; ++it)
+      if ((*it)->getType() != types::TY_Nothing)
+        ++NumOutputs;
+
+    if (NumOutputs > 1) {
+      Diag(clang::diag::err_drv_output_argument_with_multiple_files);
+      FinalOutput = 0;
+    }
+  }
+
+  for (ActionList::const_iterator it = C.getActions().begin(),
+         ie = C.getActions().end(); it != ie; ++it) {
+    Action *A = *it;
+
+    // If we are linking an image for multiple archs then the linker wants
+    // -arch_multiple and -final_output <final image name>. Unfortunately, this
+    // doesn't fit in cleanly because we have to pass this information down.
+    //
+    // FIXME: This is a hack; find a cleaner way to integrate this into the
+    // process.
+    const char *LinkingOutput = 0;
+    if (isa<LipoJobAction>(A)) {
+      if (FinalOutput)
+        LinkingOutput = FinalOutput->getValue(C.getArgs());
+      else
+        LinkingOutput = DefaultImageName.c_str();
+    }
+
+    InputInfo II;
+    BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+                       /*BoundArch*/0,
+                       /*CanAcceptPipe*/ true,
+                       /*AtTopLevel*/ true,
+                       /*LinkingOutput*/ LinkingOutput,
+                       II);
+  }
+
+  // If the user passed -Qunused-arguments or there were errors, don't warn
+  // about any unused arguments.
+  if (Diags.getNumErrors() ||
+      C.getArgs().hasArg(options::OPT_Qunused_arguments))
+    return;
+
+  // Claim -### here.
+  (void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
+
+  for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
+       it != ie; ++it) {
+    Arg *A = *it;
+
+    // FIXME: It would be nice to be able to send the argument to the
+    // Diagnostic, so that extra values, position, and so on could be printed.
+    if (!A->isClaimed()) {
+      if (A->getOption().hasNoArgumentUnused())
+        continue;
+
+      // Suppress the warning automatically if this is just a flag, and it is an
+      // instance of an argument we already claimed.
+      const Option &Opt = A->getOption();
+      if (isa<FlagOption>(Opt)) {
+        bool DuplicateClaimed = false;
+
+        for (arg_iterator it = C.getArgs().filtered_begin(&Opt),
+               ie = C.getArgs().filtered_end(); it != ie; ++it) {
+          if ((*it)->isClaimed()) {
+            DuplicateClaimed = true;
+            break;
+          }
+        }
+
+        if (DuplicateClaimed)
+          continue;
+      }
+
+      Diag(clang::diag::warn_drv_unused_argument)
+        << A->getAsString(C.getArgs());
+    }
+  }
+}
+
+static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
+                                    const JobAction *JA,
+                                    const ActionList *&Inputs) {
+  const Tool *ToolForJob = 0;
+
+  // See if we should look for a compiler with an integrated assembler. We match
+  // bottom up, so what we are actually looking for is an assembler job with a
+  // compiler input.
+  if (C.getArgs().hasArg(options::OPT_integrated_as,
+                         options::OPT_no_integrated_as,
+                         TC->IsIntegratedAssemblerDefault()) &&
+      !C.getArgs().hasArg(options::OPT_save_temps) &&
+      isa<AssembleJobAction>(JA) &&
+      Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
+    const Tool &Compiler = TC->SelectTool(C,cast<JobAction>(**Inputs->begin()));
+    if (Compiler.hasIntegratedAssembler()) {
+      Inputs = &(*Inputs)[0]->getInputs();
+      ToolForJob = &Compiler;
+    }
+  }
+
+  // Otherwise use the tool for the current job.
+  if (!ToolForJob)
+    ToolForJob = &TC->SelectTool(C, *JA);
+
+  // See if we should use an integrated preprocessor. We do so when we have
+  // exactly one input, since this is the only use case we care about
+  // (irrelevant since we don't support combine yet).
+  if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) &&
+      !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
+      !C.getArgs().hasArg(options::OPT_traditional_cpp) &&
+      !C.getArgs().hasArg(options::OPT_save_temps) &&
+      ToolForJob->hasIntegratedCPP())
+    Inputs = &(*Inputs)[0]->getInputs();
+
+  return *ToolForJob;
+}
+
+void Driver::BuildJobsForAction(Compilation &C,
+                                const Action *A,
+                                const ToolChain *TC,
+                                const char *BoundArch,
+                                bool CanAcceptPipe,
+                                bool AtTopLevel,
+                                const char *LinkingOutput,
+                                InputInfo &Result) const {
+  llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+
+  bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
+  // FIXME: Pipes are forcibly disabled until we support executing them.
+  if (!CCCPrintBindings)
+    UsePipes = false;
+
+  if (const InputAction *IA = dyn_cast<InputAction>(A)) {
+    // FIXME: It would be nice to not claim this here; maybe the old scheme of
+    // just using Args was better?
+    const Arg &Input = IA->getInputArg();
+    Input.claim();
+    if (isa<PositionalArg>(Input)) {
+      const char *Name = Input.getValue(C.getArgs());
+      Result = InputInfo(Name, A->getType(), Name);
+    } else
+      Result = InputInfo(&Input, A->getType(), "");
+    return;
+  }
+
+  if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
+    const ToolChain *TC = &C.getDefaultToolChain();
+
+    std::string Arch;
+    if (BAA->getArchName())
+      TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName());
+
+    BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
+                       CanAcceptPipe, AtTopLevel, LinkingOutput, Result);
+    return;
+  }
+
+  const ActionList *Inputs = &A->getInputs();
+
+  const JobAction *JA = cast<JobAction>(A);
+  const Tool &T = SelectToolForJob(C, TC, JA, Inputs);
+
+  // Only use pipes when there is exactly one input.
+  bool TryToUsePipeInput = Inputs->size() == 1 && T.acceptsPipedInput();
+  InputInfoList InputInfos;
+  for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
+       it != ie; ++it) {
+    InputInfo II;
+    BuildJobsForAction(C, *it, TC, BoundArch, TryToUsePipeInput,
+                       /*AtTopLevel*/false, LinkingOutput, II);
+    InputInfos.push_back(II);
+  }
+
+  // Determine if we should output to a pipe.
+  bool OutputToPipe = false;
+  if (CanAcceptPipe && T.canPipeOutput()) {
+    // Some actions default to writing to a pipe if they are the top level phase
+    // and there was no user override.
+    //
+    // FIXME: Is there a better way to handle this?
+    if (AtTopLevel) {
+      if (isa<PreprocessJobAction>(A) && !C.getArgs().hasArg(options::OPT_o))
+        OutputToPipe = true;
+    } else if (UsePipes)
+      OutputToPipe = true;
+  }
+
+  // Figure out where to put the job (pipes).
+  Job *Dest = &C.getJobs();
+  if (InputInfos[0].isPipe()) {
+    assert(TryToUsePipeInput && "Unrequested pipe!");
+    assert(InputInfos.size() == 1 && "Unexpected pipe with multiple inputs.");
+    Dest = &InputInfos[0].getPipe();
+  }
+
+  // Always use the first input as the base input.
+  const char *BaseInput = InputInfos[0].getBaseInput();
+
+  // Determine the place to write output to (nothing, pipe, or filename) and
+  // where to put the new job.
+  if (JA->getType() == types::TY_Nothing) {
+    Result = InputInfo(A->getType(), BaseInput);
+  } else if (OutputToPipe) {
+    // Append to current piped job or create a new one as appropriate.
+    PipedJob *PJ = dyn_cast<PipedJob>(Dest);
+    if (!PJ) {
+      PJ = new PipedJob();
+      // FIXME: Temporary hack so that -ccc-print-bindings work until we have
+      // pipe support. Please remove later.
+      if (!CCCPrintBindings)
+        cast<JobList>(Dest)->addJob(PJ);
+      Dest = PJ;
+    }
+    Result = InputInfo(PJ, A->getType(), BaseInput);
+  } else {
+    Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel),
+                       A->getType(), BaseInput);
+  }
+
+  if (CCCPrintBindings) {
+    llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"'
+                 << " - \"" << T.getName() << "\", inputs: [";
+    for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
+      llvm::errs() << InputInfos[i].getAsString();
+      if (i + 1 != e)
+        llvm::errs() << ", ";
+    }
+    llvm::errs() << "], output: " << Result.getAsString() << "\n";
+  } else {
+    T.ConstructJob(C, *JA, *Dest, Result, InputInfos,
+                   C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
+  }
+}
+
+const char *Driver::GetNamedOutputPath(Compilation &C,
+                                       const JobAction &JA,
+                                       const char *BaseInput,
+                                       bool AtTopLevel) const {
+  llvm::PrettyStackTraceString CrashInfo("Computing output path");
+  // Output to a user requested destination?
+  if (AtTopLevel) {
+    if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
+      return C.addResultFile(FinalOutput->getValue(C.getArgs()));
+  }
+
+  // Output to a temporary file?
+  if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) {
+    std::string TmpName =
+      GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
+    return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+  }
+
+  llvm::sys::Path BasePath(BaseInput);
+  std::string BaseName(BasePath.getLast());
+
+  // Determine what the derived output name should be.
+  const char *NamedOutput;
+  if (JA.getType() == types::TY_Image) {
+    NamedOutput = DefaultImageName.c_str();
+  } else {
+    const char *Suffix = types::getTypeTempSuffix(JA.getType());
+    assert(Suffix && "All types used for output should have a suffix.");
+
+    std::string::size_type End = std::string::npos;
+    if (!types::appendSuffixForType(JA.getType()))
+      End = BaseName.rfind('.');
+    std::string Suffixed(BaseName.substr(0, End));
+    Suffixed += '.';
+    Suffixed += Suffix;
+    NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
+  }
+
+  // As an annoying special case, PCH generation doesn't strip the pathname.
+  if (JA.getType() == types::TY_PCH) {
+    BasePath.eraseComponent();
+    if (BasePath.isEmpty())
+      BasePath = NamedOutput;
+    else
+      BasePath.appendComponent(NamedOutput);
+    return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()));
+  } else {
+    return C.addResultFile(NamedOutput);
+  }
+}
+
+std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
+  const ToolChain::path_list &List = TC.getFilePaths();
+  for (ToolChain::path_list::const_iterator
+         it = List.begin(), ie = List.end(); it != ie; ++it) {
+    llvm::sys::Path P(*it);
+    P.appendComponent(Name);
+    if (P.exists())
+      return P.str();
+  }
+
+  return Name;
+}
+
+std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC,
+                                   bool WantFile) const {
+  const ToolChain::path_list &List = TC.getProgramPaths();
+  for (ToolChain::path_list::const_iterator
+         it = List.begin(), ie = List.end(); it != ie; ++it) {
+    llvm::sys::Path P(*it);
+    P.appendComponent(Name);
+    if (WantFile ? P.exists() : P.canExecute())
+      return P.str();
+  }
+
+  // If all else failed, search the path.
+  llvm::sys::Path P(llvm::sys::Program::FindProgramByName(Name));
+  if (!P.empty())
+    return P.str();
+
+  return Name;
+}
+
+std::string Driver::GetTemporaryPath(const char *Suffix) const {
+  // FIXME: This is lame; sys::Path should provide this function (in particular,
+  // it should know how to find the temporary files dir).
+  std::string Error;
+  const char *TmpDir = ::getenv("TMPDIR");
+  if (!TmpDir)
+    TmpDir = ::getenv("TEMP");
+  if (!TmpDir)
+    TmpDir = ::getenv("TMP");
+  if (!TmpDir)
+    TmpDir = "/tmp";
+  llvm::sys::Path P(TmpDir);
+  P.appendComponent("cc");
+  if (P.makeUnique(false, &Error)) {
+    Diag(clang::diag::err_drv_unable_to_make_temp) << Error;
+    return "";
+  }
+
+  // FIXME: Grumble, makeUnique sometimes leaves the file around!?  PR3837.
+  P.eraseFromDisk(false, 0);
+
+  P.appendSuffix(Suffix);
+  return P.str();
+}
+
+const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
+  llvm::PrettyStackTraceString CrashInfo("Constructing host");
+  llvm::Triple Triple(TripleStr);
+
+  switch (Triple.getOS()) {
+  case llvm::Triple::AuroraUX:
+    return createAuroraUXHostInfo(*this, Triple);
+  case llvm::Triple::Darwin:
+    return createDarwinHostInfo(*this, Triple);
+  case llvm::Triple::DragonFly:
+    return createDragonFlyHostInfo(*this, Triple);
+  case llvm::Triple::OpenBSD:
+    return createOpenBSDHostInfo(*this, Triple);
+  case llvm::Triple::FreeBSD:
+    return createFreeBSDHostInfo(*this, Triple);
+  case llvm::Triple::Linux:
+    return createLinuxHostInfo(*this, Triple);
+  default:
+    return createUnknownHostInfo(*this, Triple);
+  }
+}
+
+bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
+                                    const llvm::Triple &Triple) const {
+  // Check if user requested no clang, or clang doesn't understand this type (we
+  // only handle single inputs for now).
+  if (!CCCUseClang || JA.size() != 1 ||
+      !types::isAcceptedByClang((*JA.begin())->getType()))
+    return false;
+
+  // Otherwise make sure this is an action clang understands.
+  if (isa<PreprocessJobAction>(JA)) {
+    if (!CCCUseClangCPP) {
+      Diag(clang::diag::warn_drv_not_using_clang_cpp);
+      return false;
+    }
+  } else if (!isa<PrecompileJobAction>(JA) && !isa<CompileJobAction>(JA))
+    return false;
+
+  // Use clang for C++?
+  if (!CCCUseClangCXX && types::isCXX((*JA.begin())->getType())) {
+    Diag(clang::diag::warn_drv_not_using_clang_cxx);
+    return false;
+  }
+
+  // Always use clang for precompiling and AST generation, regardless of archs.
+  if (isa<PrecompileJobAction>(JA) || JA.getType() == types::TY_AST)
+    return true;
+
+  // Finally, don't use clang if this isn't one of the user specified archs to
+  // build.
+  if (!CCCClangArchs.empty() && !CCCClangArchs.count(Triple.getArch())) {
+    Diag(clang::diag::warn_drv_not_using_clang_arch) << Triple.getArchName();
+    return false;
+  }
+
+  return true;
+}
+
+/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
+/// grouped values as integers. Numbers which are not provided are set to 0.
+///
+/// \return True if the entire string was parsed (9.2), or all groups were
+/// parsed (10.3.5extrastuff).
+bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
+                               unsigned &Minor, unsigned &Micro,
+                               bool &HadExtra) {
+  HadExtra = false;
+
+  Major = Minor = Micro = 0;
+  if (*Str == '\0')
+    return true;
+
+  char *End;
+  Major = (unsigned) strtol(Str, &End, 10);
+  if (*Str != '\0' && *End == '\0')
+    return true;
+  if (*End != '.')
+    return false;
+
+  Str = End+1;
+  Minor = (unsigned) strtol(Str, &End, 10);
+  if (*Str != '\0' && *End == '\0')
+    return true;
+  if (*End != '.')
+    return false;
+
+  Str = End+1;
+  Micro = (unsigned) strtol(Str, &End, 10);
+  if (*Str != '\0' && *End == '\0')
+    return true;
+  if (Str == End)
+    return false;
+  HadExtra = true;
+  return true;
+}
diff --git a/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp
new file mode 100644
index 0000000..72aaf56
--- /dev/null
+++ b/lib/Driver/DriverOptions.cpp
@@ -0,0 +1,37 @@
+//===--- DriverOptions.cpp - Driver Options Table -----------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+static const OptTable::Info InfoTable[] = {
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+               HELPTEXT, METAVAR)   \
+  { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+    OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/Options.inc"
+};
+
+namespace {
+
+class DriverOptTable : public OptTable {
+public:
+  DriverOptTable()
+    : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createDriverOptTable() {
+  return new DriverOptTable();
+}
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
new file mode 100644
index 0000000..18bb786
--- /dev/null
+++ b/lib/Driver/HostInfo.cpp
@@ -0,0 +1,542 @@
+//===--- HostInfo.cpp - Host specific information -----------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/HostInfo.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ToolChains.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+
+HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple)
+  : TheDriver(D), Triple(_Triple) {
+}
+
+HostInfo::~HostInfo() {
+}
+
+namespace {
+
+// Darwin Host Info
+
+/// DarwinHostInfo - Darwin host information implementation.
+class DarwinHostInfo : public HostInfo {
+  /// Darwin version of host.
+  unsigned DarwinVersion[3];
+
+  /// GCC version to use on this host.
+  unsigned GCCVersion[3];
+
+  /// Cache of tool chains we have created.
+  mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains;
+
+public:
+  DarwinHostInfo(const Driver &D, const llvm::Triple &Triple);
+  ~DarwinHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    types::ID Ty = types::lookupTypeForExtension(Ext);
+
+    // Darwin always preprocesses assembly files (unless -x is used
+    // explicitly).
+    if (Ty == types::TY_PP_Asm)
+      return types::TY_Asm;
+
+    return Ty;
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
+  : HostInfo(D, Triple) {
+
+  assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!");
+  assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
+         "Unknown Darwin platform.");
+  bool HadExtra;
+  if (!Driver::GetReleaseVersion(&getOSName()[6],
+                                 DarwinVersion[0], DarwinVersion[1],
+                                 DarwinVersion[2], HadExtra))
+    D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName();
+
+  // We can only call 4.2.1 for now.
+  GCCVersion[0] = 4;
+  GCCVersion[1] = 2;
+  GCCVersion[2] = 1;
+}
+
+DarwinHostInfo::~DarwinHostInfo() {
+  for (llvm::DenseMap<unsigned, ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool DarwinHostInfo::useDriverDriver() const {
+  return true;
+}
+
+ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
+                                           const char *ArchName) const {
+  llvm::Triple::ArchType Arch;
+
+  if (!ArchName) {
+    // If we aren't looking for a specific arch, infer the default architecture
+    // based on -arch and -m32/-m64 command line options.
+    if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+      // The gcc driver behavior with multiple -arch flags wasn't consistent for
+      // things which rely on a default architecture. We just use the last -arch
+      // to find the default tool chain (assuming it is valid).
+      Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+
+      // If it was invalid just use the host, we will reject this command line
+      // later.
+      if (Arch == llvm::Triple::UnknownArch)
+        Arch = getTriple().getArch();
+    } else {
+      // Otherwise default to the arch of the host.
+      Arch = getTriple().getArch();
+    }
+
+    // Honor -m32 and -m64 when finding the default tool chain.
+    //
+    // FIXME: Should this information be in llvm::Triple?
+    if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+      if (A->getOption().matches(options::OPT_m32)) {
+        if (Arch == llvm::Triple::x86_64)
+          Arch = llvm::Triple::x86;
+        if (Arch == llvm::Triple::ppc64)
+          Arch = llvm::Triple::ppc;
+      } else {
+        if (Arch == llvm::Triple::x86)
+          Arch = llvm::Triple::x86_64;
+        if (Arch == llvm::Triple::ppc)
+          Arch = llvm::Triple::ppc64;
+      }
+    }
+  } else
+    Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName);
+
+  assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!");
+  ToolChain *&TC = ToolChains[Arch];
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArch(Arch);
+
+    // If we recognized the arch, match it to the toolchains we support.
+    if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+      // We still use the legacy DarwinGCC toolchain on X86.
+      TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion,
+                                     GCCVersion);
+    } else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
+      TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion);
+    else
+      TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+// Unknown Host Info
+
+/// UnknownHostInfo - Generic host information to use for unknown hosts.
+class UnknownHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  UnknownHostInfo(const Driver &D, const llvm::Triple& Triple);
+  ~UnknownHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple)
+  : HostInfo(D, Triple) {
+}
+
+UnknownHostInfo::~UnknownHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool UnknownHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args,
+                                            const char *ArchName) const {
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  // Automatically handle some instances of -m32/-m64 we know about.
+  std::string Arch = getArchName();
+  ArchName = Arch.c_str();
+  if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+    if (Triple.getArch() == llvm::Triple::x86 ||
+        Triple.getArch() == llvm::Triple::x86_64) {
+      ArchName =
+        (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+    } else if (Triple.getArch() == llvm::Triple::ppc ||
+               Triple.getArch() == llvm::Triple::ppc64) {
+      ArchName =
+        (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+    }
+  }
+
+  ToolChain *&TC = ToolChains[ArchName];
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(ArchName);
+
+    TC = new toolchains::Generic_GCC(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+// OpenBSD Host Info
+
+/// OpenBSDHostInfo -  OpenBSD host information implementation.
+class OpenBSDHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+    : HostInfo(D, Triple) {}
+  ~OpenBSDHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+OpenBSDHostInfo::~OpenBSDHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool OpenBSDHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args,
+                                            const char *ArchName) const {
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  std::string Arch = getArchName();
+  ArchName = Arch.c_str();
+
+  ToolChain *&TC = ToolChains[ArchName];
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(ArchName);
+
+    TC = new toolchains::OpenBSD(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+// AuroraUX Host Info
+
+/// AuroraUXHostInfo - AuroraUX host information implementation.
+class AuroraUXHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple)
+    : HostInfo(D, Triple) {}
+  ~AuroraUXHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+AuroraUXHostInfo::~AuroraUXHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool AuroraUXHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args,
+                                             const char *ArchName) const {
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  ToolChain *&TC = ToolChains[getArchName()];
+
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(getArchName());
+
+    TC = new toolchains::AuroraUX(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+// FreeBSD Host Info
+
+/// FreeBSDHostInfo -  FreeBSD host information implementation.
+class FreeBSDHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+    : HostInfo(D, Triple) {}
+  ~FreeBSDHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+FreeBSDHostInfo::~FreeBSDHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool FreeBSDHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
+                                            const char *ArchName) const {
+  bool Lib32 = false;
+
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  // On x86_64 we need to be able to compile 32-bits binaries as well.
+  // Compiling 64-bit binaries on i386 is not supported. We don't have a
+  // lib64.
+  std::string Arch = getArchName();
+  ArchName = Arch.c_str();
+  if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
+    ArchName = "i386";
+    Lib32 = true;
+  }
+
+  ToolChain *&TC = ToolChains[ArchName];
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(ArchName);
+
+    TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
+  }
+
+  return TC;
+}
+
+// DragonFly Host Info
+
+/// DragonFlyHostInfo -  DragonFly host information implementation.
+class DragonFlyHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple)
+    : HostInfo(D, Triple) {}
+  ~DragonFlyHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+DragonFlyHostInfo::~DragonFlyHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool DragonFlyHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args,
+                                              const char *ArchName) const {
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  ToolChain *&TC = ToolChains[getArchName()];
+
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(getArchName());
+
+    TC = new toolchains::DragonFly(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+// Linux Host Info
+
+/// LinuxHostInfo -  Linux host information implementation.
+class LinuxHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  LinuxHostInfo(const Driver &D, const llvm::Triple& Triple)
+    : HostInfo(D, Triple) {}
+  ~LinuxHostInfo();
+
+  virtual bool useDriverDriver() const;
+
+  virtual types::ID lookupTypeForExtension(const char *Ext) const {
+    return types::lookupTypeForExtension(Ext);
+  }
+
+  virtual ToolChain *CreateToolChain(const ArgList &Args,
+                                     const char *ArchName) const;
+};
+
+LinuxHostInfo::~LinuxHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool LinuxHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
+                                          const char *ArchName) const {
+
+  assert(!ArchName &&
+         "Unexpected arch name on platform without driver driver support.");
+
+  // Automatically handle some instances of -m32/-m64 we know about.
+  std::string Arch = getArchName();
+  ArchName = Arch.c_str();
+  if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+    if (Triple.getArch() == llvm::Triple::x86 ||
+        Triple.getArch() == llvm::Triple::x86_64) {
+      ArchName =
+        (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+    } else if (Triple.getArch() == llvm::Triple::ppc ||
+               Triple.getArch() == llvm::Triple::ppc64) {
+      ArchName =
+        (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+    }
+  }
+
+  ToolChain *&TC = ToolChains[ArchName];
+
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(ArchName);
+
+    TC = new toolchains::Linux(*this, TCTriple);
+  }
+
+  return TC;
+}
+
+}
+
+const HostInfo *
+clang::driver::createAuroraUXHostInfo(const Driver &D,
+                                      const llvm::Triple& Triple){
+  return new AuroraUXHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createDarwinHostInfo(const Driver &D,
+                                    const llvm::Triple& Triple){
+  return new DarwinHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createOpenBSDHostInfo(const Driver &D,
+                                     const llvm::Triple& Triple) {
+  return new OpenBSDHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createFreeBSDHostInfo(const Driver &D,
+                                     const llvm::Triple& Triple) {
+  return new FreeBSDHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createDragonFlyHostInfo(const Driver &D,
+                                       const llvm::Triple& Triple) {
+  return new DragonFlyHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createLinuxHostInfo(const Driver &D,
+                                   const llvm::Triple& Triple) {
+  return new LinuxHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createUnknownHostInfo(const Driver &D,
+                                     const llvm::Triple& Triple) {
+  return new UnknownHostInfo(D, Triple);
+}
diff --git a/lib/Driver/InputInfo.h b/lib/Driver/InputInfo.h
new file mode 100644
index 0000000..c657bef
--- /dev/null
+++ b/lib/Driver/InputInfo.h
@@ -0,0 +1,101 @@
+//===--- InputInfo.h - Input Source & Type Information ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_INPUTINFO_H_
+#define CLANG_LIB_DRIVER_INPUTINFO_H_
+
+#include "clang/Driver/Types.h"
+
+#include <cassert>
+#include <string>
+
+namespace clang {
+namespace driver {
+  class PipedJob;
+
+/// InputInfo - Wrapper for information about an input source.
+class InputInfo {
+  // FIXME: The distinction between filenames and inputarg here is
+  // gross; we should probably drop the idea of a "linker
+  // input". Doing so means tweaking pipelining to still create link
+  // steps when it sees linker inputs (but not treat them as
+  // arguments), and making sure that arguments get rendered
+  // correctly.
+  enum Class {
+    Nothing,
+    Filename,
+    InputArg,
+    Pipe
+  };
+
+  union {
+    const char *Filename;
+    const Arg *InputArg;
+    PipedJob *Pipe;
+  } Data;
+  Class Kind;
+  types::ID Type;
+  const char *BaseInput;
+
+public:
+  InputInfo() {}
+  InputInfo(types::ID _Type, const char *_BaseInput)
+    : Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
+  }
+  InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput)
+    : Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
+    Data.Filename = _Filename;
+  }
+  InputInfo(const Arg *_InputArg, types::ID _Type, const char *_BaseInput)
+    : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
+    Data.InputArg = _InputArg;
+  }
+  InputInfo(PipedJob *_Pipe, types::ID _Type, const char *_BaseInput)
+    : Kind(Pipe), Type(_Type), BaseInput(_BaseInput) {
+    Data.Pipe = _Pipe;
+  }
+
+  bool isNothing() const { return Kind == Nothing; }
+  bool isFilename() const { return Kind == Filename; }
+  bool isInputArg() const { return Kind == InputArg; }
+  bool isPipe() const { return Kind == Pipe; }
+  types::ID getType() const { return Type; }
+  const char *getBaseInput() const { return BaseInput; }
+
+  const char *getFilename() const {
+    assert(isFilename() && "Invalid accessor.");
+    return Data.Filename;
+  }
+  const Arg &getInputArg() const {
+    assert(isInputArg() && "Invalid accessor.");
+    return *Data.InputArg;
+  }
+  PipedJob &getPipe() const {
+    assert(isPipe() && "Invalid accessor.");
+    return *Data.Pipe;
+  }
+
+  /// getAsString - Return a string name for this input, for
+  /// debugging.
+  std::string getAsString() const {
+    if (isPipe())
+      return "(pipe)";
+    else if (isFilename())
+      return std::string("\"") + getFilename() + '"';
+    else if (isInputArg())
+      return "(input arg)";
+    else
+      return "(nothing)";
+  }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
new file mode 100644
index 0000000..1bd123e
--- /dev/null
+++ b/lib/Driver/Job.cpp
@@ -0,0 +1,34 @@
+//===--- Job.cpp - Command to Execute -----------------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Job.h"
+
+#include <cassert>
+using namespace clang::driver;
+
+Job::~Job() {}
+
+Command::Command(const Action &_Source, const Tool &_Creator,
+                 const char *_Executable, const ArgStringList &_Arguments)
+  : Job(CommandClass), Source(_Source), Creator(_Creator),
+    Executable(_Executable), Arguments(_Arguments)
+{
+}
+
+PipedJob::PipedJob() : Job(PipedJobClass) {}
+
+JobList::JobList() : Job(JobListClass) {}
+
+void Job::addCommand(Command *C) {
+  if (PipedJob *PJ = dyn_cast<PipedJob>(this))
+    PJ->addCommand(C);
+  else
+    cast<JobList>(this)->addJob(C);
+}
+
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
new file mode 100644
index 0000000..371bda7
--- /dev/null
+++ b/lib/Driver/Makefile
@@ -0,0 +1,16 @@
+##===- clang/lib/Driver/Makefile ---------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME := clangDriver
+BUILD_ARCHIVE = 1
+
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
new file mode 100644
index 0000000..f69d5d8
--- /dev/null
+++ b/lib/Driver/OptTable.cpp
@@ -0,0 +1,377 @@
+//===--- OptTable.cpp - Option Table Implementation ---------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Option.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <map>
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+// Ordering on Info. The ordering is *almost* lexicographic, with two
+// exceptions. First, '\0' comes at the end of the alphabet instead of
+// the beginning (thus options preceed any other options which prefix
+// them). Second, for options with the same name, the less permissive
+// version should come first; a Flag option should preceed a Joined
+// option, for example.
+
+static int StrCmpOptionName(const char *A, const char *B) {
+  char a = *A, b = *B;
+  while (a == b) {
+    if (a == '\0')
+      return 0;
+
+    a = *++A;
+    b = *++B;
+  }
+
+  if (a == '\0') // A is a prefix of B.
+    return 1;
+  if (b == '\0') // B is a prefix of A.
+    return -1;
+
+  // Otherwise lexicographic.
+  return (a < b) ? -1 : 1;
+}
+
+namespace clang {
+namespace driver {
+static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
+  if (&A == &B)
+    return false;
+
+  if (int N = StrCmpOptionName(A.Name, B.Name))
+    return N == -1;
+
+  // Names are the same, check that classes are in order; exactly one
+  // should be joined, and it should succeed the other.
+  assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
+         "Unexpected classes for options with same name.");
+  return B.Kind == Option::JoinedClass;
+}
+
+// Support lower_bound between info and an option name.
+static inline bool operator<(const OptTable::Info &I, const char *Name) {
+  return StrCmpOptionName(I.Name, Name) == -1;
+}
+static inline bool operator<(const char *Name, const OptTable::Info &I) {
+  return StrCmpOptionName(Name, I.Name) == -1;
+}
+}
+}
+
+//
+
+OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
+
+//
+
+OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
+  : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
+    Options(new Option*[NumOptionInfos]),
+    TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+{
+  // Explicitly zero initialize the error to work around a bug in array
+  // value-initialization on MinGW with gcc 4.3.5.
+  memset(Options, 0, sizeof(*Options) * NumOptionInfos);
+
+  // Find start of normal options.
+  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+    unsigned Kind = getInfo(i + 1).Kind;
+    if (Kind == Option::InputClass) {
+      assert(!TheInputOption && "Cannot have multiple input options!");
+      TheInputOption = getOption(i + 1);
+    } else if (Kind == Option::UnknownClass) {
+      assert(!TheUnknownOption && "Cannot have multiple input options!");
+      TheUnknownOption = getOption(i + 1);
+    } else if (Kind != Option::GroupClass) {
+      FirstSearchableIndex = i;
+      break;
+    }
+  }
+  assert(FirstSearchableIndex != 0 && "No searchable options?");
+
+#ifndef NDEBUG
+  // Check that everything after the first searchable option is a
+  // regular option class.
+  for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
+    Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
+    assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
+            Kind != Option::GroupClass) &&
+           "Special options should be defined first!");
+  }
+
+  // Check that options are in order.
+  for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+    if (!(getInfo(i) < getInfo(i + 1))) {
+      getOption(i)->dump();
+      getOption(i + 1)->dump();
+      assert(0 && "Options are not in order!");
+    }
+  }
+#endif
+}
+
+OptTable::~OptTable() {
+  for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
+    delete Options[i];
+  delete[] Options;
+}
+
+Option *OptTable::CreateOption(unsigned id) const {
+  const Info &info = getInfo(id);
+  const OptionGroup *Group =
+    cast_or_null<OptionGroup>(getOption(info.GroupID));
+  const Option *Alias = getOption(info.AliasID);
+
+  Option *Opt = 0;
+  switch (info.Kind) {
+  case Option::InputClass:
+    Opt = new InputOption(id); break;
+  case Option::UnknownClass:
+    Opt = new UnknownOption(id); break;
+  case Option::GroupClass:
+    Opt = new OptionGroup(id, info.Name, Group); break;
+  case Option::FlagClass:
+    Opt = new FlagOption(id, info.Name, Group, Alias); break;
+  case Option::JoinedClass:
+    Opt = new JoinedOption(id, info.Name, Group, Alias); break;
+  case Option::SeparateClass:
+    Opt = new SeparateOption(id, info.Name, Group, Alias); break;
+  case Option::CommaJoinedClass:
+    Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
+  case Option::MultiArgClass:
+    Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
+  case Option::JoinedOrSeparateClass:
+    Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
+  case Option::JoinedAndSeparateClass:
+    Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
+  }
+
+  if (info.Flags & DriverOption)
+    Opt->setDriverOption(true);
+  if (info.Flags & LinkerInput)
+    Opt->setLinkerInput(true);
+  if (info.Flags & NoArgumentUnused)
+    Opt->setNoArgumentUnused(true);
+  if (info.Flags & RenderAsInput)
+    Opt->setNoOptAsInput(true);
+  if (info.Flags & RenderJoined) {
+    assert(info.Kind == Option::SeparateClass && "Invalid option.");
+    Opt->setForceJoinedRender(true);
+  }
+  if (info.Flags & RenderSeparate) {
+    assert(info.Kind == Option::JoinedClass && "Invalid option.");
+    Opt->setForceSeparateRender(true);
+  }
+  if (info.Flags & Unsupported)
+    Opt->setUnsupported(true);
+
+  return Opt;
+}
+
+Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
+  unsigned Prev = Index;
+  const char *Str = Args.getArgString(Index);
+
+  // Anything that doesn't start with '-' is an input, as is '-' itself.
+  if (Str[0] != '-' || Str[1] == '\0')
+    return new PositionalArg(TheInputOption, Index++);
+
+  const Info *Start = OptionInfos + FirstSearchableIndex;
+  const Info *End = OptionInfos + getNumOptions();
+
+  // Search for the first next option which could be a prefix.
+  Start = std::lower_bound(Start, End, Str);
+
+  // Options are stored in sorted order, with '\0' at the end of the
+  // alphabet. Since the only options which can accept a string must
+  // prefix it, we iteratively search for the next option which could
+  // be a prefix.
+  //
+  // FIXME: This is searching much more than necessary, but I am
+  // blanking on the simplest way to make it fast. We can solve this
+  // problem when we move to TableGen.
+  for (; Start != End; ++Start) {
+    // Scan for first option which is a proper prefix.
+    for (; Start != End; ++Start)
+      if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0)
+        break;
+    if (Start == End)
+      break;
+
+    // See if this option matches.
+    if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
+      return A;
+
+    // Otherwise, see if this argument was missing values.
+    if (Prev != Index)
+      return 0;
+  }
+
+  return new PositionalArg(TheUnknownOption, Index++);
+}
+
+InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd,
+                                  unsigned &MissingArgIndex,
+                                  unsigned &MissingArgCount) const {
+  InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
+
+  // FIXME: Handle '@' args (or at least error on them).
+
+  MissingArgIndex = MissingArgCount = 0;
+  unsigned Index = 0, End = ArgEnd - ArgBegin;
+  while (Index < End) {
+    // Ignore empty arguments (other things may still take them as arguments).
+    if (Args->getArgString(Index)[0] == '\0') {
+      ++Index;
+      continue;
+    }
+
+    unsigned Prev = Index;
+    Arg *A = ParseOneArg(*Args, Index);
+    assert(Index > Prev && "Parser failed to consume argument.");
+
+    // Check for missing argument error.
+    if (!A) {
+      assert(Index >= End && "Unexpected parser error.");
+      assert(Index - Prev - 1 && "No missing arguments!");
+      MissingArgIndex = Prev;
+      MissingArgCount = Index - Prev - 1;
+      break;
+    }
+
+    Args->append(A);
+  }
+
+  return Args;
+}
+
+static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
+  std::string Name = Opts.getOptionName(Id);
+
+  // Add metavar, if used.
+  switch (Opts.getOptionKind(Id)) {
+  case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
+    assert(0 && "Invalid option with help text.");
+
+  case Option::MultiArgClass: case Option::JoinedAndSeparateClass:
+    assert(0 && "Cannot print metavar for this kind of option.");
+
+  case Option::FlagClass:
+    break;
+
+  case Option::SeparateClass: case Option::JoinedOrSeparateClass:
+    Name += ' ';
+    // FALLTHROUGH
+  case Option::JoinedClass: case Option::CommaJoinedClass:
+    if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
+      Name += MetaVarName;
+    else
+      Name += "<value>";
+    break;
+  }
+
+  return Name;
+}
+
+static void PrintHelpOptionList(llvm::raw_ostream &OS, llvm::StringRef Title,
+                                std::vector<std::pair<std::string,
+                                const char*> > &OptionHelp) {
+  OS << Title << ":\n";
+
+  // Find the maximum option length.
+  unsigned OptionFieldWidth = 0;
+  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+    // Skip titles.
+    if (!OptionHelp[i].second)
+      continue;
+
+    // Limit the amount of padding we are willing to give up for alignment.
+    unsigned Length = OptionHelp[i].first.size();
+    if (Length <= 23)
+      OptionFieldWidth = std::max(OptionFieldWidth, Length);
+  }
+
+  const unsigned InitialPad = 2;
+  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
+    const std::string &Option = OptionHelp[i].first;
+    int Pad = OptionFieldWidth - int(Option.size());
+    OS.indent(InitialPad) << Option;
+
+    // Break on long option names.
+    if (Pad < 0) {
+      OS << "\n";
+      Pad = OptionFieldWidth + InitialPad;
+    }
+    OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
+  }
+}
+
+static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
+  unsigned GroupID = Opts.getOptionGroupID(Id);
+
+  // If not in a group, return the default help group.
+  if (!GroupID)
+    return "OPTIONS";
+
+  // Abuse the help text of the option groups to store the "help group"
+  // name.
+  //
+  // FIXME: Split out option groups.
+  if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
+    return GroupHelp;
+
+  // Otherwise keep looking.
+  return getOptionHelpGroup(Opts, GroupID);
+}
+
+void OptTable::PrintHelp(llvm::raw_ostream &OS, const char *Name,
+                         const char *Title, bool ShowHidden) const {
+  OS << "OVERVIEW: " << Title << "\n";
+  OS << '\n';
+  OS << "USAGE: " << Name << " [options] <inputs>\n";
+  OS << '\n';
+
+  // Render help text into a map of group-name to a list of (option, help)
+  // pairs.
+  typedef std::map<std::string,
+                 std::vector<std::pair<std::string, const char*> > > helpmap_ty;
+  helpmap_ty GroupedOptionHelp;
+
+  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+    unsigned Id = i + 1;
+
+    // FIXME: Split out option groups.
+    if (getOptionKind(Id) == Option::GroupClass)
+      continue;
+
+    if (!ShowHidden && isOptionHelpHidden(Id))
+      continue;
+
+    if (const char *Text = getOptionHelpText(Id)) {
+      const char *HelpGroup = getOptionHelpGroup(*this, Id);
+      const std::string &OptName = getOptionHelpName(*this, Id);
+      GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
+    }
+  }
+
+  for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
+         ie = GroupedOptionHelp.end(); it != ie; ++it) {
+    if (it != GroupedOptionHelp .begin())
+      OS << "\n";
+    PrintHelpOptionList(OS, it->first, it->second);
+  }
+
+  OS.flush();
+}
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
new file mode 100644
index 0000000..17d00f5
--- /dev/null
+++ b/lib/Driver/Option.cpp
@@ -0,0 +1,232 @@
+//===--- Option.cpp - Abstract Driver Options ---------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Option.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <algorithm>
+using namespace clang::driver;
+
+Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
+               const OptionGroup *_Group, const Option *_Alias)
+  : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
+    Unsupported(false), LinkerInput(false), NoOptAsInput(false),
+    ForceSeparateRender(false), ForceJoinedRender(false),
+    DriverOption(false), NoArgumentUnused(false) {
+
+  // Multi-level aliases are not supported, and alias options cannot
+  // have groups. This just simplifies option tracking, it is not an
+  // inherent limitation.
+  assert((!Alias || (!Alias->Alias && !Group)) &&
+         "Multi-level aliases and aliases with groups are unsupported.");
+}
+
+Option::~Option() {
+}
+
+void Option::dump() const {
+  llvm::errs() << "<";
+  switch (Kind) {
+  default:
+    assert(0 && "Invalid kind");
+#define P(N) case N: llvm::errs() << #N; break
+    P(GroupClass);
+    P(InputClass);
+    P(UnknownClass);
+    P(FlagClass);
+    P(JoinedClass);
+    P(SeparateClass);
+    P(CommaJoinedClass);
+    P(MultiArgClass);
+    P(JoinedOrSeparateClass);
+    P(JoinedAndSeparateClass);
+#undef P
+  }
+
+  llvm::errs() << " Name:\"" << Name << '"';
+
+  if (Group) {
+    llvm::errs() << " Group:";
+    Group->dump();
+  }
+
+  if (Alias) {
+    llvm::errs() << " Alias:";
+    Alias->dump();
+  }
+
+  if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
+    llvm::errs() << " NumArgs:" << MOA->getNumArgs();
+
+  llvm::errs() << ">\n";
+}
+
+bool Option::matches(OptSpecifier Opt) const {
+  // Aliases are never considered in matching, look through them.
+  if (Alias)
+    return Alias->matches(Opt);
+
+  // Check exact match.
+  if (ID == Opt)
+    return true;
+
+  if (Group)
+    return Group->matches(Opt);
+  return false;
+}
+
+OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
+                         const OptionGroup *Group)
+  : Option(Option::GroupClass, ID, Name, Group, 0) {
+}
+
+Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const {
+  assert(0 && "accept() should never be called on an OptionGroup");
+  return 0;
+}
+
+InputOption::InputOption(OptSpecifier ID)
+  : Option(Option::InputClass, ID, "<input>", 0, 0) {
+}
+
+Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
+  assert(0 && "accept() should never be called on an InputOption");
+  return 0;
+}
+
+UnknownOption::UnknownOption(OptSpecifier ID)
+  : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
+}
+
+Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
+  assert(0 && "accept() should never be called on an UnknownOption");
+  return 0;
+}
+
+FlagOption::FlagOption(OptSpecifier ID, const char *Name,
+                       const OptionGroup *Group, const Option *Alias)
+  : Option(Option::FlagClass, ID, Name, Group, Alias) {
+}
+
+Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
+  // Matches iff this is an exact match.
+  // FIXME: Avoid strlen.
+  if (strlen(getName()) != strlen(Args.getArgString(Index)))
+    return 0;
+
+  return new FlagArg(this, Index++);
+}
+
+JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
+                           const OptionGroup *Group, const Option *Alias)
+  : Option(Option::JoinedClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
+  // Always matches.
+  return new JoinedArg(this, Index++);
+}
+
+CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
+                                     const OptionGroup *Group,
+                                     const Option *Alias)
+  : Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
+}
+
+Arg *CommaJoinedOption::accept(const InputArgList &Args,
+                               unsigned &Index) const {
+  // Always matches. We count the commas now so we can answer
+  // getNumValues easily.
+
+  // Get the suffix string.
+  // FIXME: Avoid strlen, and move to helper method?
+  const char *Suffix = Args.getArgString(Index) + strlen(getName());
+  return new CommaJoinedArg(this, Index++, Suffix);
+}
+
+SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
+                               const OptionGroup *Group, const Option *Alias)
+  : Option(Option::SeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
+  // Matches iff this is an exact match.
+  // FIXME: Avoid strlen.
+  if (strlen(getName()) != strlen(Args.getArgString(Index)))
+    return 0;
+
+  Index += 2;
+  if (Index > Args.getNumInputArgStrings())
+    return 0;
+
+  return new SeparateArg(this, Index - 2, 1);
+}
+
+MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
+                               const OptionGroup *Group, const Option *Alias,
+                               unsigned _NumArgs)
+  : Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
+  assert(NumArgs > 1  && "Invalid MultiArgOption!");
+}
+
+Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
+  // Matches iff this is an exact match.
+  // FIXME: Avoid strlen.
+  if (strlen(getName()) != strlen(Args.getArgString(Index)))
+    return 0;
+
+  Index += 1 + NumArgs;
+  if (Index > Args.getNumInputArgStrings())
+    return 0;
+
+  return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
+}
+
+JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
+                                               const OptionGroup *Group,
+                                               const Option *Alias)
+  : Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
+                                    unsigned &Index) const {
+  // If this is not an exact match, it is a joined arg.
+  // FIXME: Avoid strlen.
+  if (strlen(getName()) != strlen(Args.getArgString(Index)))
+    return new JoinedArg(this, Index++);
+
+  // Otherwise it must be separate.
+  Index += 2;
+  if (Index > Args.getNumInputArgStrings())
+    return 0;
+
+  return new SeparateArg(this, Index - 2, 1);
+}
+
+JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
+                                                 const char *Name,
+                                                 const OptionGroup *Group,
+                                                 const Option *Alias)
+  : Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
+}
+
+Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
+                                     unsigned &Index) const {
+  // Always matches.
+
+  Index += 2;
+  if (Index > Args.getNumInputArgStrings())
+    return 0;
+
+  return new JoinedAndSeparateArg(this, Index - 2);
+}
+
diff --git a/lib/Driver/Phases.cpp b/lib/Driver/Phases.cpp
new file mode 100644
index 0000000..df4cdee
--- /dev/null
+++ b/lib/Driver/Phases.cpp
@@ -0,0 +1,27 @@
+//===--- Phases.cpp - Transformations on Driver Types -------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Phases.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+
+const char *phases::getPhaseName(ID Id) {
+  switch (Id) {
+  case Preprocess: return "preprocessor";
+  case Precompile: return "precompiler";
+  case Compile: return "compiler";
+  case Assemble: return "assembler";
+  case Link: return "linker";
+  }
+
+  assert(0 && "Invalid phase id.");
+  return 0;
+}
diff --git a/lib/Driver/Tool.cpp b/lib/Driver/Tool.cpp
new file mode 100644
index 0000000..781e0a7
--- /dev/null
+++ b/lib/Driver/Tool.cpp
@@ -0,0 +1,19 @@
+//===--- Tool.cpp - Compilation Tools -----------------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Tool.h"
+
+using namespace clang::driver;
+
+Tool::Tool(const char *_Name, const ToolChain &TC) : Name(_Name),
+                                                     TheToolChain(TC) {
+}
+
+Tool::~Tool() {
+}
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
new file mode 100644
index 0000000..9b6264a
--- /dev/null
+++ b/lib/Driver/ToolChain.cpp
@@ -0,0 +1,39 @@
+//===--- ToolChain.cpp - Collections of tools for one platform ----------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/ToolChain.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/HostInfo.h"
+
+using namespace clang::driver;
+
+ToolChain::ToolChain(const HostInfo &_Host, const llvm::Triple &_Triple)
+  : Host(_Host), Triple(_Triple) {
+}
+
+ToolChain::~ToolChain() {
+}
+
+const Driver &ToolChain::getDriver() const {
+ return Host.getDriver();
+}
+
+std::string ToolChain::GetFilePath(const Compilation &C,
+                                   const char *Name) const {
+  return Host.getDriver().GetFilePath(Name, *this);
+
+}
+
+std::string ToolChain::GetProgramPath(const Compilation &C,
+                                      const char *Name,
+                                      bool WantFile) const {
+  return Host.getDriver().GetProgramPath(Name, *this, WantFile);
+}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
new file mode 100644
index 0000000..a00d8d9
--- /dev/null
+++ b/lib/Driver/ToolChains.cpp
@@ -0,0 +1,886 @@
+//===--- ToolChains.cpp - ToolChain Implementations ---------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ToolChains.h"
+
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+
+#include <cstdlib> // ::getenv
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+
+/// Darwin - Darwin tool chain for i386 and x86_64.
+
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
+               const unsigned (&_DarwinVersion)[3])
+  : ToolChain(Host, Triple), TargetInitialized(false)
+{
+  llvm::raw_string_ostream(MacosxVersionMin)
+    << "10." << std::max(0, (int)_DarwinVersion[0] - 4) << '.'
+    << _DarwinVersion[1];
+}
+
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMArch(llvm::StringRef Value) {
+  if (Value == "armv6k")
+    return "armv6";
+
+  if (Value == "armv5tej")
+    return "armv5";
+
+  if (Value == "xscale")
+    return "xscale";
+
+  if (Value == "armv4t")
+    return "armv4t";
+
+  if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
+      Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
+      Value == "armv7m")
+    return "armv7";
+
+  return 0;
+}
+
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMCpu(llvm::StringRef Value) {
+  if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
+      Value == "arm946e-s" || Value == "arm966e-s" ||
+      Value == "arm968e-s" || Value == "arm10e" ||
+      Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
+      Value == "arm1026ej-s")
+    return "armv5";
+
+  if (Value == "xscale")
+    return "xscale";
+
+  if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
+      Value == "arm1176jz-s" || Value == "arm1176jzf-s")
+    return "armv6";
+
+  if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
+    return "armv7";
+
+  return 0;
+}
+
+llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
+  switch (getTriple().getArch()) {
+  default:
+    return getArchName();
+
+  case llvm::Triple::arm: {
+    if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+      if (const char *Arch = GetArmArchForMArch(A->getValue(Args)))
+        return Arch;
+
+    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+      if (const char *Arch = GetArmArchForMCpu(A->getValue(Args)))
+        return Arch;
+
+    return "arm";
+  }
+  }
+}
+
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
+                     const unsigned (&DarwinVersion)[3],
+                     const unsigned (&_GCCVersion)[3])
+  : Darwin(Host, Triple, DarwinVersion)
+{
+  GCCVersion[0] = _GCCVersion[0];
+  GCCVersion[1] = _GCCVersion[1];
+  GCCVersion[2] = _GCCVersion[2];
+
+  // Set up the tool chain paths to match gcc.
+  ToolChainDir = "i686-apple-darwin";
+  ToolChainDir += llvm::utostr(DarwinVersion[0]);
+  ToolChainDir += "/";
+  ToolChainDir += llvm::utostr(GCCVersion[0]);
+  ToolChainDir += '.';
+  ToolChainDir += llvm::utostr(GCCVersion[1]);
+  ToolChainDir += '.';
+  ToolChainDir += llvm::utostr(GCCVersion[2]);
+
+  // Try the next major version if that tool chain dir is invalid.
+  std::string Tmp = "/usr/lib/gcc/" + ToolChainDir;
+  if (!llvm::sys::Path(Tmp).exists()) {
+    std::string Next = "i686-apple-darwin";
+    Next += llvm::utostr(DarwinVersion[0] + 1);
+    Next += "/";
+    Next += llvm::utostr(GCCVersion[0]);
+    Next += '.';
+    Next += llvm::utostr(GCCVersion[1]);
+    Next += '.';
+    Next += llvm::utostr(GCCVersion[2]);
+
+    // Use that if it exists, otherwise hope the user isn't linking.
+    //
+    // FIXME: Drop dependency on gcc's tool chain.
+    Tmp = "/usr/lib/gcc/" + Next;
+    if (llvm::sys::Path(Tmp).exists())
+      ToolChainDir = Next;
+  }
+
+  std::string Path;
+  if (getArchName() == "x86_64") {
+    Path = getDriver().Dir;
+    Path += "/../lib/gcc/";
+    Path += ToolChainDir;
+    Path += "/x86_64";
+    getFilePaths().push_back(Path);
+
+    Path = "/usr/lib/gcc/";
+    Path += ToolChainDir;
+    Path += "/x86_64";
+    getFilePaths().push_back(Path);
+  }
+
+  Path = getDriver().Dir;
+  Path += "/../lib/gcc/";
+  Path += ToolChainDir;
+  getFilePaths().push_back(Path);
+
+  Path = "/usr/lib/gcc/";
+  Path += ToolChainDir;
+  getFilePaths().push_back(Path);
+
+  Path = getDriver().Dir;
+  Path += "/../libexec/gcc/";
+  Path += ToolChainDir;
+  getProgramPaths().push_back(Path);
+
+  Path = "/usr/libexec/gcc/";
+  Path += ToolChainDir;
+  getProgramPaths().push_back(Path);
+
+  getProgramPaths().push_back(getDriver().Dir);
+}
+
+Darwin::~Darwin() {
+  // Free tool implementations.
+  for (llvm::DenseMap<unsigned, Tool*>::iterator
+         it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
+    delete it->second;
+}
+
+Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::InputClass:
+    case Action::BindArchClass:
+      assert(0 && "Invalid tool kind.");
+    case Action::PreprocessJobClass:
+      T = new tools::darwin::Preprocess(*this); break;
+    case Action::AnalyzeJobClass:
+      T = new tools::Clang(*this); break;
+    case Action::PrecompileJobClass:
+    case Action::CompileJobClass:
+      T = new tools::darwin::Compile(*this); break;
+    case Action::AssembleJobClass:
+      T = new tools::darwin::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::darwin::Link(*this); break;
+    case Action::LipoJobClass:
+      T = new tools::darwin::Lipo(*this); break;
+    }
+  }
+
+  return *T;
+}
+
+void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
+                                      ArgStringList &CmdArgs) const {
+  // FIXME: Derive these correctly.
+  if (getArchName() == "x86_64") {
+    CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+                                         "/x86_64"));
+    // Intentionally duplicated for (temporary) gcc bug compatibility.
+    CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+                                         "/x86_64"));
+  }
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+  // Intentionally duplicated for (temporary) gcc bug compatibility.
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+                                       "/../../../" + ToolChainDir));
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+                                       "/../../.."));
+}
+
+void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
+                                      ArgStringList &CmdArgs) const {
+  // Note that this routine is only used for targetting OS X.
+
+  // Derived from libgcc and lib specs but refactored.
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-lgcc_static");
+  } else {
+    if (Args.hasArg(options::OPT_static_libgcc)) {
+      CmdArgs.push_back("-lgcc_eh");
+    } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
+      // Derived from darwin_iphoneos_libgcc spec.
+      if (isTargetIPhoneOS()) {
+        CmdArgs.push_back("-lgcc_s.1");
+      } else {
+        CmdArgs.push_back("-lgcc_s.10.5");
+      }
+    } else if (Args.hasArg(options::OPT_shared_libgcc) ||
+               Args.hasFlag(options::OPT_fexceptions,
+                            options::OPT_fno_exceptions) ||
+               Args.hasArg(options::OPT_fgnu_runtime)) {
+      // FIXME: This is probably broken on 10.3?
+      if (isMacosxVersionLT(10, 5))
+        CmdArgs.push_back("-lgcc_s.10.4");
+      else if (isMacosxVersionLT(10, 6))
+        CmdArgs.push_back("-lgcc_s.10.5");
+    } else {
+      if (isMacosxVersionLT(10, 3, 9))
+        ; // Do nothing.
+      else if (isMacosxVersionLT(10, 5))
+        CmdArgs.push_back("-lgcc_s.10.4");
+      else if (isMacosxVersionLT(10, 6))
+        CmdArgs.push_back("-lgcc_s.10.5");
+    }
+
+    if (isTargetIPhoneOS() || isMacosxVersionLT(10, 6)) {
+      CmdArgs.push_back("-lgcc");
+      CmdArgs.push_back("-lSystem");
+    } else {
+      CmdArgs.push_back("-lSystem");
+      CmdArgs.push_back("-lgcc");
+    }
+  }
+}
+
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
+                         const unsigned (&DarwinVersion)[3])
+  : Darwin(Host, Triple, DarwinVersion)
+{
+  // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+  getProgramPaths().push_back(getDriver().Dir);
+}
+
+void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
+                                       ArgStringList &CmdArgs) const {
+  // The Clang toolchain uses explicit paths for internal libraries.
+}
+
+void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
+                                        ArgStringList &CmdArgs) const {
+  // Darwin doesn't support real static executables, don't link any runtime
+  // libraries with -static.
+  if (Args.hasArg(options::OPT_static))
+    return;
+
+  // Reject -static-libgcc for now, we can deal with this when and if someone
+  // cares. This is useful in situations where someone wants to statically link
+  // something like libstdc++, and needs its runtime support routines.
+  if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
+    getDriver().Diag(clang::diag::err_drv_unsupported_opt)
+      << A->getAsString(Args);
+    return;
+  }
+
+  // Otherwise link libSystem, then the dynamic runtime library, and finally any
+  // target specific static runtime library.
+  CmdArgs.push_back("-lSystem");
+
+  // Select the dynamic runtime library and the target specific static library.
+  const char *DarwinStaticLib = 0;
+  if (isTargetIPhoneOS()) {
+    CmdArgs.push_back("-lgcc_s.1");
+
+    // We may need some static functions for armv6/thumb which are required to
+    // be in the same linkage unit as their caller.
+    if (getDarwinArchName(Args) == "armv6")
+      DarwinStaticLib = "libclang_rt.armv6.a";
+  } else {
+    // The dynamic runtime library was merged with libSystem for 10.6 and
+    // beyond; only 10.4 and 10.5 need an additional runtime library.
+    if (isMacosxVersionLT(10, 5))
+      CmdArgs.push_back("-lgcc_s.10.4");
+    else if (isMacosxVersionLT(10, 6))
+      CmdArgs.push_back("-lgcc_s.10.5");
+
+    // For OS X, we only need a static runtime library when targetting 10.4, to
+    // provide versions of the static functions which were omitted from
+    // 10.4.dylib.
+    if (isMacosxVersionLT(10, 5))
+      DarwinStaticLib = "libclang_rt.10.4.a";
+  }
+
+  /// Add the target specific static library, if needed.
+  if (DarwinStaticLib) {
+    llvm::sys::Path P(getDriver().ResourceDir);
+    P.appendComponent("lib");
+    P.appendComponent("darwin");
+    P.appendComponent(DarwinStaticLib);
+
+    // For now, allow missing resource libraries to support developers who may
+    // not have compiler-rt checked out or integrated into their build.
+    if (!P.exists())
+      getDriver().Diag(clang::diag::warn_drv_missing_resource_library)
+        << P.str();
+    else
+      CmdArgs.push_back(Args.MakeArgString(P.str()));
+  }
+}
+
+DerivedArgList *Darwin::TranslateArgs(InputArgList &Args,
+                                      const char *BoundArch) const {
+  DerivedArgList *DAL = new DerivedArgList(Args, false);
+  const OptTable &Opts = getDriver().getOpts();
+
+  // FIXME: We really want to get out of the tool chain level argument
+  // translation business, as it makes the driver functionality much
+  // more opaque. For now, we follow gcc closely solely for the
+  // purpose of easily achieving feature parity & testability. Once we
+  // have something that works, we should reevaluate each translation
+  // and try to push it down into tool specific logic.
+
+  Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
+  Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
+  if (OSXVersion && iPhoneVersion) {
+    getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
+          << OSXVersion->getAsString(Args)
+          << iPhoneVersion->getAsString(Args);
+    iPhoneVersion = 0;
+  } else if (!OSXVersion && !iPhoneVersion) {
+    // If neither OS X nor iPhoneOS targets were specified, check for
+    // environment defines.
+    const char *OSXTarget = ::getenv("MACOSX_DEPLOYMENT_TARGET");
+    const char *iPhoneOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET");
+
+    // Ignore empty strings.
+    if (OSXTarget && OSXTarget[0] == '\0')
+      OSXTarget = 0;
+    if (iPhoneOSTarget && iPhoneOSTarget[0] == '\0')
+      iPhoneOSTarget = 0;
+
+    // Diagnose conflicting deployment targets, and choose default platform
+    // based on the tool chain.
+    //
+    // FIXME: Don't hardcode default here.
+    if (OSXTarget && iPhoneOSTarget) {
+      // FIXME: We should see if we can get away with warning or erroring on
+      // this. Perhaps put under -pedantic?
+      if (getTriple().getArch() == llvm::Triple::arm ||
+          getTriple().getArch() == llvm::Triple::thumb)
+        OSXVersion = 0;
+      else
+        iPhoneVersion = 0;
+    }
+
+    if (OSXTarget) {
+      const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+      OSXVersion = DAL->MakeJoinedArg(0, O, OSXTarget);
+      DAL->append(OSXVersion);
+    } else if (iPhoneOSTarget) {
+      const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+      iPhoneVersion = DAL->MakeJoinedArg(0, O, iPhoneOSTarget);
+      DAL->append(iPhoneVersion);
+    } else {
+      // Otherwise, choose a default platform based on the tool chain.
+      //
+      // FIXME: Don't hardcode default here.
+      if (getTriple().getArch() == llvm::Triple::arm ||
+          getTriple().getArch() == llvm::Triple::thumb) {
+        const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+        iPhoneVersion = DAL->MakeJoinedArg(0, O, "3.0");
+        DAL->append(iPhoneVersion);
+      } else {
+        const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+        OSXVersion = DAL->MakeJoinedArg(0, O, MacosxVersionMin);
+        DAL->append(OSXVersion);
+      }
+    }
+  }
+
+  // Set the tool chain target information.
+  unsigned Major, Minor, Micro;
+  bool HadExtra;
+  if (OSXVersion) {
+    assert(!iPhoneVersion && "Unknown target platform!");
+    if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor,
+                                   Micro, HadExtra) || HadExtra ||
+        Major != 10 || Minor >= 10 || Micro >= 10)
+      getDriver().Diag(clang::diag::err_drv_invalid_version_number)
+        << OSXVersion->getAsString(Args);
+  } else {
+    assert(iPhoneVersion && "Unknown target platform!");
+    if (!Driver::GetReleaseVersion(iPhoneVersion->getValue(Args), Major, Minor,
+                                   Micro, HadExtra) || HadExtra ||
+        Major >= 10 || Minor >= 100 || Micro >= 100)
+      getDriver().Diag(clang::diag::err_drv_invalid_version_number)
+        << iPhoneVersion->getAsString(Args);
+  }
+  setTarget(iPhoneVersion, Major, Minor, Micro);
+
+  for (ArgList::iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) {
+    Arg *A = *it;
+
+    if (A->getOption().matches(options::OPT_Xarch__)) {
+      // FIXME: Canonicalize name.
+      if (getArchName() != A->getValue(Args, 0))
+        continue;
+
+      // FIXME: The arg is leaked here, and we should have a nicer
+      // interface for this.
+      unsigned Prev, Index = Prev = A->getIndex() + 1;
+      Arg *XarchArg = Opts.ParseOneArg(Args, Index);
+
+      // If the argument parsing failed or more than one argument was
+      // consumed, the -Xarch_ argument's parameter tried to consume
+      // extra arguments. Emit an error and ignore.
+      //
+      // We also want to disallow any options which would alter the
+      // driver behavior; that isn't going to work in our model. We
+      // use isDriverOption() as an approximation, although things
+      // like -O4 are going to slip through.
+      if (!XarchArg || Index > Prev + 1 ||
+          XarchArg->getOption().isDriverOption()) {
+       getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument)
+          << A->getAsString(Args);
+        continue;
+      }
+
+      XarchArg->setBaseArg(A);
+      A = XarchArg;
+    }
+
+    // Sob. These is strictly gcc compatible for the time being. Apple
+    // gcc translates options twice, which means that self-expanding
+    // options add duplicates.
+    switch ((options::ID) A->getOption().getID()) {
+    default:
+      DAL->append(A);
+      break;
+
+    case options::OPT_mkernel:
+    case options::OPT_fapple_kext:
+      DAL->append(A);
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
+      break;
+
+    case options::OPT_dependency_file:
+      DAL->append(DAL->MakeSeparateArg(A, Opts.getOption(options::OPT_MF),
+                                       A->getValue(Args)));
+      break;
+
+    case options::OPT_gfull:
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag)));
+      DAL->append(DAL->MakeFlagArg(A,
+             Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)));
+      break;
+
+    case options::OPT_gused:
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_g_Flag)));
+      DAL->append(DAL->MakeFlagArg(A,
+             Opts.getOption(options::OPT_feliminate_unused_debug_symbols)));
+      break;
+
+    case options::OPT_fterminated_vtables:
+    case options::OPT_findirect_virtual_calls:
+      DAL->append(DAL->MakeFlagArg(A,
+                                   Opts.getOption(options::OPT_fapple_kext)));
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
+      break;
+
+    case options::OPT_shared:
+      DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_dynamiclib)));
+      break;
+
+    case options::OPT_fconstant_cfstrings:
+      DAL->append(DAL->MakeFlagArg(A,
+                             Opts.getOption(options::OPT_mconstant_cfstrings)));
+      break;
+
+    case options::OPT_fno_constant_cfstrings:
+      DAL->append(DAL->MakeFlagArg(A,
+                          Opts.getOption(options::OPT_mno_constant_cfstrings)));
+      break;
+
+    case options::OPT_Wnonportable_cfstrings:
+      DAL->append(DAL->MakeFlagArg(A,
+                     Opts.getOption(options::OPT_mwarn_nonportable_cfstrings)));
+      break;
+
+    case options::OPT_Wno_nonportable_cfstrings:
+      DAL->append(DAL->MakeFlagArg(A,
+                  Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)));
+      break;
+
+    case options::OPT_fpascal_strings:
+      DAL->append(DAL->MakeFlagArg(A,
+                                 Opts.getOption(options::OPT_mpascal_strings)));
+      break;
+
+    case options::OPT_fno_pascal_strings:
+      DAL->append(DAL->MakeFlagArg(A,
+                              Opts.getOption(options::OPT_mno_pascal_strings)));
+      break;
+    }
+  }
+
+  if (getTriple().getArch() == llvm::Triple::x86 ||
+      getTriple().getArch() == llvm::Triple::x86_64)
+    if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
+      DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ),
+                                     "core2"));
+
+  // Add the arch options based on the particular spelling of -arch, to match
+  // how the driver driver works.
+  if (BoundArch) {
+    llvm::StringRef Name = BoundArch;
+    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")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "601"));
+    else if (Name == "ppc603")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "603"));
+    else if (Name == "ppc604")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "604"));
+    else if (Name == "ppc604e")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "604e"));
+    else if (Name == "ppc750")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "750"));
+    else if (Name == "ppc7400")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "7400"));
+    else if (Name == "ppc7450")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "7450"));
+    else if (Name == "ppc970")
+      DAL->append(DAL->MakeJoinedArg(0, MCpu, "970"));
+
+    else if (Name == "ppc64")
+      DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64)));
+
+    else if (Name == "i386")
+      ;
+    else if (Name == "i486")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "i486"));
+    else if (Name == "i586")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "i586"));
+    else if (Name == "i686")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "i686"));
+    else if (Name == "pentium")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium"));
+    else if (Name == "pentium2")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium2"));
+    else if (Name == "pentpro")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "pentiumpro"));
+    else if (Name == "pentIIm3")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium2"));
+
+    else if (Name == "x86_64")
+      DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64)));
+
+    else if (Name == "arm")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "armv4t"));
+    else if (Name == "armv4t")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "armv4t"));
+    else if (Name == "armv5")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "armv5tej"));
+    else if (Name == "xscale")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "xscale"));
+    else if (Name == "armv6")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "armv6k"));
+    else if (Name == "armv7")
+      DAL->append(DAL->MakeJoinedArg(0, MArch, "armv7a"));
+
+    else
+      llvm_unreachable("invalid Darwin arch");
+  }
+
+  return DAL;
+}
+
+bool Darwin::IsUnwindTablesDefault() const {
+  // FIXME: Gross; we should probably have some separate target
+  // definition, possibly even reusing the one in clang.
+  return getArchName() == "x86_64";
+}
+
+bool Darwin::UseDwarfDebugFlags() const {
+  if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
+    return S[0] != '\0';
+  return false;
+}
+
+const char *Darwin::GetDefaultRelocationModel() const {
+  return "pic";
+}
+
+const char *Darwin::GetForcedPicModel() const {
+  if (getArchName() == "x86_64")
+    return "pic";
+  return 0;
+}
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+
+Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
+  : ToolChain(Host, Triple) {
+  getProgramPaths().push_back(getDriver().Dir);
+}
+
+Generic_GCC::~Generic_GCC() {
+  // Free tool implementations.
+  for (llvm::DenseMap<unsigned, Tool*>::iterator
+         it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
+    delete it->second;
+}
+
+Tool &Generic_GCC::SelectTool(const Compilation &C,
+                              const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::InputClass:
+    case Action::BindArchClass:
+      assert(0 && "Invalid tool kind.");
+    case Action::PreprocessJobClass:
+      T = new tools::gcc::Preprocess(*this); break;
+    case Action::PrecompileJobClass:
+      T = new tools::gcc::Precompile(*this); break;
+    case Action::AnalyzeJobClass:
+      T = new tools::Clang(*this); break;
+    case Action::CompileJobClass:
+      T = new tools::gcc::Compile(*this); break;
+    case Action::AssembleJobClass:
+      T = new tools::gcc::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::gcc::Link(*this); break;
+
+      // This is a bit ungeneric, but the only platform using a driver
+      // driver is Darwin.
+    case Action::LipoJobClass:
+      T = new tools::darwin::Lipo(*this); break;
+    }
+  }
+
+  return *T;
+}
+
+bool Generic_GCC::IsUnwindTablesDefault() const {
+  // FIXME: Gross; we should probably have some separate target
+  // definition, possibly even reusing the one in clang.
+  return getArchName() == "x86_64";
+}
+
+const char *Generic_GCC::GetDefaultRelocationModel() const {
+  return "static";
+}
+
+const char *Generic_GCC::GetForcedPicModel() const {
+  return 0;
+}
+
+DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args,
+                                           const char *BoundArch) const {
+  return new DerivedArgList(Args, true);
+}
+
+/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
+
+OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple)
+  : Generic_GCC(Host, Triple) {
+  getFilePaths().push_back(getDriver().Dir + "/../lib");
+  getFilePaths().push_back("/usr/lib");
+}
+
+Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::AssembleJobClass:
+      T = new tools::openbsd::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::openbsd::Link(*this); break;
+    default:
+      T = &Generic_GCC::SelectTool(C, JA);
+    }
+  }
+
+  return *T;
+}
+
+/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
+
+FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
+  : Generic_GCC(Host, Triple) {
+  if (Lib32) {
+    getFilePaths().push_back(getDriver().Dir + "/../lib32");
+    getFilePaths().push_back("/usr/lib32");
+  } else {
+    getFilePaths().push_back(getDriver().Dir + "/../lib");
+    getFilePaths().push_back("/usr/lib");
+  }
+}
+
+Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::AssembleJobClass:
+      T = new tools::freebsd::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::freebsd::Link(*this); break;
+    default:
+      T = &Generic_GCC::SelectTool(C, JA);
+    }
+  }
+
+  return *T;
+}
+
+/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
+
+AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
+  : Generic_GCC(Host, Triple) {
+
+  getProgramPaths().push_back(getDriver().Dir);
+
+  getFilePaths().push_back(getDriver().Dir + "/../lib");
+  getFilePaths().push_back("/usr/lib");
+  getFilePaths().push_back("/usr/sfw/lib");
+  getFilePaths().push_back("/opt/gcc4/lib");
+  getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
+
+}
+
+Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::AssembleJobClass:
+      T = new tools::auroraux::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::auroraux::Link(*this); break;
+    default:
+      T = &Generic_GCC::SelectTool(C, JA);
+    }
+  }
+
+  return *T;
+}
+
+
+/// Linux toolchain (very bare-bones at the moment).
+
+Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
+  : Generic_GCC(Host, Triple) {
+  getFilePaths().push_back(getDriver().Dir + "/../lib/clang/1.0/");
+  getFilePaths().push_back("/lib/");
+  getFilePaths().push_back("/usr/lib/");
+
+  // Depending on the Linux distribution, any combination of lib{,32,64} is
+  // possible. E.g. Debian uses lib and lib32 for mixed i386/x86-64 systems,
+  // openSUSE uses lib and lib64 for the same purpose.
+  getFilePaths().push_back("/lib32/");
+  getFilePaths().push_back("/usr/lib32/");
+  getFilePaths().push_back("/lib64/");
+  getFilePaths().push_back("/usr/lib64/");
+
+  // FIXME: Figure out some way to get gcc's libdir
+  // (e.g. /usr/lib/gcc/i486-linux-gnu/4.3/ for Ubuntu 32-bit); we need
+  // crtbegin.o/crtend.o/etc., and want static versions of various
+  // libraries. If we had our own crtbegin.o/crtend.o/etc, we could probably
+  // get away with using shared versions in /usr/lib, though.
+  // We could fall back to the approach we used for includes (a massive
+  // list), but that's messy at best.
+}
+
+/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
+
+DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
+  : Generic_GCC(Host, Triple) {
+
+  // Path mangling to find libexec
+  getProgramPaths().push_back(getDriver().Dir);
+
+  getFilePaths().push_back(getDriver().Dir + "/../lib");
+  getFilePaths().push_back("/usr/lib");
+  getFilePaths().push_back("/usr/lib/gcc41");
+}
+
+Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
+  Action::ActionClass Key;
+  if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+    Key = Action::AnalyzeJobClass;
+  else
+    Key = JA.getKind();
+
+  Tool *&T = Tools[Key];
+  if (!T) {
+    switch (Key) {
+    case Action::AssembleJobClass:
+      T = new tools::dragonfly::Assemble(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::dragonfly::Link(*this); break;
+    default:
+      T = &Generic_GCC::SelectTool(C, JA);
+    }
+  }
+
+  return *T;
+}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
new file mode 100644
index 0000000..fbb1136
--- /dev/null
+++ b/lib/Driver/ToolChains.h
@@ -0,0 +1,272 @@
+//===--- ToolChains.h - ToolChain Implementations ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_TOOLCHAINS_H_
+#define CLANG_LIB_DRIVER_TOOLCHAINS_H_
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/ToolChain.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Compiler.h"
+
+#include "Tools.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+class VISIBILITY_HIDDEN Generic_GCC : public ToolChain {
+protected:
+  mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+public:
+  Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple);
+  ~Generic_GCC();
+
+  virtual DerivedArgList *TranslateArgs(InputArgList &Args,
+                                        const char *BoundArch) const;
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+  virtual bool IsUnwindTablesDefault() const;
+  virtual const char *GetDefaultRelocationModel() const;
+  virtual const char *GetForcedPicModel() const;
+};
+
+/// Darwin - The base Darwin tool chain.
+class VISIBILITY_HIDDEN Darwin : public ToolChain {
+  mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+  /// Whether the information on the target has been initialized.
+  //
+  // FIXME: This should be eliminated. What we want to do is make this part of
+  // the "default target for arguments" selection process, once we get out of
+  // the argument translation business.
+  mutable bool TargetInitialized;
+
+  /// Whether we are targetting iPhoneOS target.
+  mutable bool TargetIsIPhoneOS;
+  
+  /// The OS version we are targetting.
+  mutable unsigned TargetVersion[3];
+
+  /// The default macosx-version-min of this tool chain; empty until
+  /// initialized.
+  std::string MacosxVersionMin;
+
+public:
+  Darwin(const HostInfo &Host, const llvm::Triple& Triple,
+         const unsigned (&DarwinVersion)[3]);
+  ~Darwin();
+
+  /// @name Darwin Specific Toolchain API
+  /// {
+
+  // FIXME: Eliminate these ...Target functions and derive separate tool chains
+  // for these targets and put version in constructor.
+  void setTarget(bool isIPhoneOS, unsigned Major, unsigned Minor,
+                 unsigned Micro) const {
+    // FIXME: For now, allow reinitialization as long as values don't
+    // change. This will go away when we move away from argument translation.
+    if (TargetInitialized && TargetIsIPhoneOS == isIPhoneOS &&
+        TargetVersion[0] == Major && TargetVersion[1] == Minor &&
+        TargetVersion[2] == Micro)
+      return;
+
+    assert(!TargetInitialized && "Target already initialized!");
+    TargetInitialized = true;
+    TargetIsIPhoneOS = isIPhoneOS;
+    TargetVersion[0] = Major;
+    TargetVersion[1] = Minor;
+    TargetVersion[2] = Micro;
+  }
+
+  bool isTargetIPhoneOS() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetIsIPhoneOS;
+  }
+
+  void getTargetVersion(unsigned (&Res)[3]) const {
+    assert(TargetInitialized && "Target not initialized!");
+    Res[0] = TargetVersion[0];
+    Res[1] = TargetVersion[1];
+    Res[2] = TargetVersion[2];
+  }
+
+  /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler
+  /// invocation. For example, Darwin treats different ARM variations as
+  /// distinct architectures.
+  llvm::StringRef getDarwinArchName(const ArgList &Args) const;
+
+  static bool isVersionLT(unsigned (&A)[3], unsigned (&B)[3]) {
+    for (unsigned i=0; i < 3; ++i) {
+      if (A[i] > B[i]) return false;
+      if (A[i] < B[i]) return true;
+    }
+    return false;
+  }
+
+  bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+    assert(isTargetIPhoneOS() && "Unexpected call for OS X target!");
+    unsigned B[3] = { V0, V1, V2 };
+    return isVersionLT(TargetVersion, B);
+  }
+
+  bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+    assert(!isTargetIPhoneOS() && "Unexpected call for iPhoneOS target!");
+    unsigned B[3] = { V0, V1, V2 };
+    return isVersionLT(TargetVersion, B);
+  }
+
+  /// AddLinkSearchPathArgs - Add the linker search paths to \arg CmdArgs.
+  ///
+  /// \param Args - The input argument list.
+  /// \param CmdArgs [out] - The command argument list to append the paths
+  /// (prefixed by -L) to.
+  virtual void AddLinkSearchPathArgs(const ArgList &Args,
+                                     ArgStringList &CmdArgs) const = 0;
+
+  /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler
+  /// runtime library.
+  virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+                                     ArgStringList &CmdArgs) const = 0;
+
+  /// }
+  /// @name ToolChain Implementation
+  /// {
+
+  virtual DerivedArgList *TranslateArgs(InputArgList &Args,
+                                        const char *BoundArch) const;
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+  virtual bool IsBlocksDefault() const {
+    // Blocks default to on for OS X 10.6 and iPhoneOS 3.0 and beyond.
+    if (isTargetIPhoneOS())
+      return !isIPhoneOSVersionLT(3);
+    else
+      return !isMacosxVersionLT(10, 6);
+  }
+  virtual bool IsObjCNonFragileABIDefault() const {
+    // Non-fragile ABI default to on for iPhoneOS and x86-64.
+    return isTargetIPhoneOS() || getTriple().getArch() == llvm::Triple::x86_64;
+  }
+  virtual bool IsObjCLegacyDispatchDefault() const {
+    // This is only used with the non-fragile ABI.
+    return (getTriple().getArch() == llvm::Triple::arm ||
+            getTriple().getArch() == llvm::Triple::thumb);
+  }
+  virtual bool IsUnwindTablesDefault() const;
+  virtual unsigned GetDefaultStackProtectorLevel() const {
+    // Stack protectors default to on for 10.6 and beyond.
+    return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 6);
+  }
+  virtual const char *GetDefaultRelocationModel() const;
+  virtual const char *GetForcedPicModel() const;
+
+  virtual bool UseDwarfDebugFlags() const;
+
+  /// }
+};
+
+/// DarwinClang - The Darwin toolchain used by Clang.
+class VISIBILITY_HIDDEN DarwinClang : public Darwin {
+public:
+  DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
+              const unsigned (&DarwinVersion)[3]);
+
+  /// @name Darwin ToolChain Implementation
+  /// {
+
+  virtual void AddLinkSearchPathArgs(const ArgList &Args,
+                                    ArgStringList &CmdArgs) const;
+
+  virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+                                     ArgStringList &CmdArgs) const;
+
+  /// }
+};
+
+/// DarwinGCC - The Darwin toolchain used by GCC.
+class VISIBILITY_HIDDEN DarwinGCC : public Darwin {
+  /// GCC version to use.
+  unsigned GCCVersion[3];
+
+  /// The directory suffix for this tool chain.
+  std::string ToolChainDir;
+
+public:
+  DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
+            const unsigned (&DarwinVersion)[3],
+            const unsigned (&GCCVersion)[3]);
+
+  /// @name Darwin ToolChain Implementation
+  /// {
+
+  virtual void AddLinkSearchPathArgs(const ArgList &Args,
+                                    ArgStringList &CmdArgs) const;
+
+  virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+                                     ArgStringList &CmdArgs) const;
+
+  /// }
+};
+
+/// Darwin_Generic_GCC - Generic Darwin tool chain using gcc.
+class VISIBILITY_HIDDEN Darwin_Generic_GCC : public Generic_GCC {
+public:
+  Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
+    : Generic_GCC(Host, Triple) {}
+
+  virtual const char *GetDefaultRelocationModel() const { return "pic"; }
+};
+
+class VISIBILITY_HIDDEN AuroraUX : public Generic_GCC {
+public:
+  AuroraUX(const HostInfo &Host, const llvm::Triple& Triple);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class VISIBILITY_HIDDEN OpenBSD : public Generic_GCC {
+public:
+  OpenBSD(const HostInfo &Host, const llvm::Triple& Triple);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class VISIBILITY_HIDDEN FreeBSD : public Generic_GCC {
+public:
+  FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class VISIBILITY_HIDDEN DragonFly : public Generic_GCC {
+public:
+  DragonFly(const HostInfo &Host, const llvm::Triple& Triple);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
+class VISIBILITY_HIDDEN Linux : public Generic_GCC {
+public:
+  Linux(const HostInfo &Host, const llvm::Triple& Triple);
+};
+
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
new file mode 100644
index 0000000..2aa7116
--- /dev/null
+++ b/lib/Driver/Tools.cpp
@@ -0,0 +1,2818 @@
+//===--- Tools.cpp - Tools Implementations ------------------------------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Process.h"
+
+#include "InputInfo.h"
+#include "ToolChains.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+
+/// CheckPreprocessingOptions - Perform some validation of preprocessing
+/// arguments that is shared with gcc.
+static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
+  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
+    if (!Args.hasArg(options::OPT_E))
+      D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+        << A->getAsString(Args) << "-E";
+}
+
+/// CheckCodeGenerationOptions - Perform some validation of code generation
+/// arguments that is shared with gcc.
+static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
+  // In gcc, only ARM checks this, but it seems reasonable to check universally.
+  if (Args.hasArg(options::OPT_static))
+    if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
+                                       options::OPT_mdynamic_no_pic))
+      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+        << A->getAsString(Args) << "-static";
+}
+
+void Clang::AddPreprocessingOptions(const Driver &D,
+                                    const ArgList &Args,
+                                    ArgStringList &CmdArgs,
+                                    const InputInfo &Output,
+                                    const InputInfoList &Inputs) const {
+  Arg *A;
+
+  CheckPreprocessingOptions(D, Args);
+
+  Args.AddLastArg(CmdArgs, options::OPT_C);
+  Args.AddLastArg(CmdArgs, options::OPT_CC);
+
+  // Handle dependency file generation.
+  if ((A = Args.getLastArg(options::OPT_M)) ||
+      (A = Args.getLastArg(options::OPT_MM)) ||
+      (A = Args.getLastArg(options::OPT_MD)) ||
+      (A = Args.getLastArg(options::OPT_MMD))) {
+    // Determine the output location.
+    const char *DepFile;
+    if (Output.getType() == types::TY_Dependencies) {
+      if (Output.isPipe())
+        DepFile = "-";
+      else
+        DepFile = Output.getFilename();
+    } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
+      DepFile = MF->getValue(Args);
+    } else if (A->getOption().matches(options::OPT_M) ||
+               A->getOption().matches(options::OPT_MM)) {
+      DepFile = "-";
+    } else {
+      DepFile = darwin::CC1::getDependencyFileName(Args, Inputs);
+    }
+    CmdArgs.push_back("-dependency-file");
+    CmdArgs.push_back(DepFile);
+
+    // Add an -MT option if the user didn't specify their own.
+    //
+    // FIXME: This should use -MQ, when we support it.
+    if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
+      const char *DepTarget;
+
+      // If user provided -o, that is the dependency target, except
+      // when we are only generating a dependency file.
+      Arg *OutputOpt = Args.getLastArg(options::OPT_o);
+      if (OutputOpt && Output.getType() != types::TY_Dependencies) {
+        DepTarget = OutputOpt->getValue(Args);
+      } else {
+        // Otherwise derive from the base input.
+        //
+        // FIXME: This should use the computed output file location.
+        llvm::sys::Path P(Inputs[0].getBaseInput());
+
+        P.eraseSuffix();
+        P.appendSuffix("o");
+        DepTarget = Args.MakeArgString(P.getLast());
+      }
+
+      CmdArgs.push_back("-MT");
+      CmdArgs.push_back(DepTarget);
+    }
+
+    if (A->getOption().matches(options::OPT_M) ||
+        A->getOption().matches(options::OPT_MD))
+      CmdArgs.push_back("-sys-header-deps");
+  }
+
+  Args.AddLastArg(CmdArgs, options::OPT_MP);
+  Args.AddAllArgs(CmdArgs, options::OPT_MT);
+
+  // Add -i* options, and automatically translate to
+  // -include-pch/-include-pth for transparent PCH support. It's
+  // wonky, but we include looking for .gch so we can support seamless
+  // replacement into a build system already set up to be generating
+  // .gch files.
+  for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    const Arg *A = it;
+
+    if (A->getOption().matches(options::OPT_include)) {
+      // Use PCH if the user requested it, except for C++ (for now).
+      bool UsePCH = D.CCCUsePCH;
+      if (types::isCXX(Inputs[0].getType()))
+        UsePCH = false;
+
+      bool FoundPTH = false;
+      bool FoundPCH = false;
+      llvm::sys::Path P(A->getValue(Args));
+      if (UsePCH) {
+        P.appendSuffix("pch");
+        if (P.exists())
+          FoundPCH = true;
+        else
+          P.eraseSuffix();
+      }
+
+      if (!FoundPCH) {
+        P.appendSuffix("pth");
+        if (P.exists())
+          FoundPTH = true;
+        else
+          P.eraseSuffix();
+      }
+
+      if (!FoundPCH && !FoundPTH) {
+        P.appendSuffix("gch");
+        if (P.exists()) {
+          FoundPCH = UsePCH;
+          FoundPTH = !UsePCH;
+        }
+        else
+          P.eraseSuffix();
+      }
+
+      if (FoundPCH || FoundPTH) {
+        A->claim();
+        if (UsePCH)
+          CmdArgs.push_back("-include-pch");
+        else
+          CmdArgs.push_back("-include-pth");
+        CmdArgs.push_back(Args.MakeArgString(P.str()));
+        continue;
+      }
+    }
+
+    // Not translated, render as usual.
+    A->claim();
+    A->render(Args, CmdArgs);
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
+
+  // Add -Wp, and -Xassembler if using the preprocessor.
+
+  // FIXME: There is a very unfortunate problem here, some troubled
+  // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
+  // really support that we would have to parse and then translate
+  // those options. :(
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
+                       options::OPT_Xpreprocessor);
+
+  // -I- is a deprecated GCC feature, reject it.
+  if (Arg *A = Args.getLastArg(options::OPT_I_))
+    D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args) {
+  // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+  // If we have -mcpu=, use that.
+  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+    return A->getValue(Args);
+
+  // Otherwise, if we have -march= choose the base CPU for that arch.
+  if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    llvm::StringRef MArch = A->getValue(Args);
+
+    if (MArch == "armv2" || MArch == "armv2a")
+      return "arm2";
+    if (MArch == "armv3")
+      return "arm6";
+    if (MArch == "armv3m")
+      return "arm7m";
+    if (MArch == "armv4" || MArch == "armv4t")
+      return "arm7tdmi";
+    if (MArch == "armv5" || MArch == "armv5t")
+      return "arm10tdmi";
+    if (MArch == "armv5e" || MArch == "armv5te")
+      return "arm1026ejs";
+    if (MArch == "armv5tej")
+      return "arm926ej-s";
+    if (MArch == "armv6" || MArch == "armv6k")
+      return "arm1136jf-s";
+    if (MArch == "armv6j")
+      return "arm1136j-s";
+    if (MArch == "armv6z" || MArch == "armv6zk")
+      return "arm1176jzf-s";
+    if (MArch == "armv6t2")
+      return "arm1156t2-s";
+    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+      return "cortex-a8";
+    if (MArch == "armv7r" || MArch == "armv7-r")
+      return "cortex-r4";
+    if (MArch == "armv7m" || MArch == "armv7-m")
+      return "cortex-m3";
+    if (MArch == "ep9312")
+      return "ep9312";
+    if (MArch == "iwmmxt")
+      return "iwmmxt";
+    if (MArch == "xscale")
+      return "xscale";
+  }
+
+  // Otherwise return the most base CPU LLVM supports.
+  return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+  if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+      CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+      CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+      CPU == "arm940t" || CPU == "ep9312")
+    return "v4t";
+
+  if (CPU == "arm10tdmi" || CPU == "arm1020t")
+    return "v5";
+
+  if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+      CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+      CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+      CPU == "iwmmxt")
+    return "v5e";
+
+  if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+      CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+    return "v6";
+
+  if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+    return "v6t2";
+
+  if (CPU == "cortex-a8" || CPU == "cortex-a9")
+    return "v7";
+
+  return "";
+}
+
+/// getLLVMTriple - Get the LLVM triple to use for a particular toolchain, which
+/// may depend on command line arguments.
+static std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
+  switch (TC.getTriple().getArch()) {
+  default:
+    return TC.getTripleString();
+
+  case llvm::Triple::arm:
+  case llvm::Triple::thumb: {
+    // FIXME: Factor into subclasses.
+    llvm::Triple Triple = TC.getTriple();
+
+    // Thumb2 is the default for V7 on Darwin.
+    //
+    // FIXME: Thumb should just be another -target-feaure, not in the triple.
+    llvm::StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
+    bool ThumbDefault =
+      (Suffix == "v7" && TC.getTriple().getOS() == llvm::Triple::Darwin);
+    std::string ArchName = "arm";
+    if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+      ArchName = "thumb";
+    Triple.setArchName(ArchName + Suffix.str());
+
+    return Triple.getTriple();
+  }
+  }
+}
+
+// FIXME: Move to target hook.
+static bool isSignedCharDefault(const llvm::Triple &Triple) {
+  switch (Triple.getArch()) {
+  default:
+    return true;
+
+  case llvm::Triple::ppc:
+  case llvm::Triple::ppc64:
+    if (Triple.getOS() == llvm::Triple::Darwin)
+      return true;
+    return false;
+
+  case llvm::Triple::systemz:
+    return false;
+  }
+}
+
+void Clang::AddARMTargetArgs(const ArgList &Args,
+                             ArgStringList &CmdArgs) const {
+  const Driver &D = getToolChain().getDriver();
+
+  // Select the ABI to use.
+  //
+  // FIXME: Support -meabi.
+  const char *ABIName = 0;
+  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+    ABIName = A->getValue(Args);
+  } else {
+    // Select the default based on the platform.
+    switch (getToolChain().getTriple().getOS()) {
+      // FIXME: Is this right for non-Darwin and non-Linux?
+    default:
+      ABIName = "aapcs";
+      break;
+
+    case llvm::Triple::Darwin:
+      ABIName = "apcs-gnu";
+      break;
+
+    case llvm::Triple::Linux:
+      ABIName = "aapcs-linux";
+      break;
+    }
+  }
+  CmdArgs.push_back("-target-abi");
+  CmdArgs.push_back(ABIName);
+
+  // Set the CPU based on -march= and -mcpu=.
+  CmdArgs.push_back("-target-cpu");
+  CmdArgs.push_back(getARMTargetCPU(Args));
+
+  // Select the float ABI as determined by -msoft-float, -mhard-float, and
+  // -mfloat-abi=.
+  llvm::StringRef FloatABI;
+  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+                               options::OPT_mhard_float,
+                               options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(options::OPT_msoft_float))
+      FloatABI = "soft";
+    else if (A->getOption().matches(options::OPT_mhard_float))
+      FloatABI = "hard";
+    else {
+      FloatABI = A->getValue(Args);
+      if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
+        D.Diag(clang::diag::err_drv_invalid_mfloat_abi)
+          << A->getAsString(Args);
+        FloatABI = "soft";
+      }
+    }
+  }
+
+  // If unspecified, choose the default based on the platform.
+  if (FloatABI.empty()) {
+    // FIXME: This is wrong for non-Darwin, we don't have a mechanism yet for
+    // distinguishing things like linux-eabi vs linux-elf.
+    switch (getToolChain().getTriple().getOS()) {
+    case llvm::Triple::Darwin: {
+      // Darwin defaults to "softfp" for v6 and v7.
+      //
+      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
+      llvm::StringRef ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
+      if (ArchName.startswith("v6") || ArchName.startswith("v7"))
+        FloatABI = "softfp";
+      else
+        FloatABI = "soft";
+      break;
+    }
+
+    default:
+      // Assume "soft", but warn the user we are guessing.
+      FloatABI = "soft";
+      D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+      break;
+    }
+  }
+
+  if (FloatABI == "soft") {
+    // Floating point operations and argument passing are soft.
+    //
+    // FIXME: This changes CPP defines, we need -target-soft-float.
+    CmdArgs.push_back("-msoft-float");
+    CmdArgs.push_back("-mfloat-abi");
+    CmdArgs.push_back("soft");
+  } else if (FloatABI == "softfp") {
+    // Floating point operations are hard, but argument passing is soft.
+    CmdArgs.push_back("-mfloat-abi");
+    CmdArgs.push_back("soft");
+  } else {
+    // Floating point operations and argument passing are hard.
+    assert(FloatABI == "hard" && "Invalid float abi!");
+    CmdArgs.push_back("-mfloat-abi");
+    CmdArgs.push_back("hard");
+  }
+
+  // Set appropriate target features for floating point mode.
+  //
+  // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
+  // yet (it uses the -mfloat-abi and -msoft-float options above), and it is
+  // stripped out by the ARM target.
+
+  // Use software floating point operations?
+  if (FloatABI == "soft") {
+    CmdArgs.push_back("-target-feature");
+    CmdArgs.push_back("+soft-float");
+  }
+
+  // Use software floating point argument passing?
+  if (FloatABI != "hard") {
+    CmdArgs.push_back("-target-feature");
+    CmdArgs.push_back("+soft-float-abi");
+  }
+
+  // Honor -mfpu=.
+  //
+  // FIXME: Centralize feature selection, defaulting shouldn't be also in the
+  // frontend target.
+  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
+    llvm::StringRef FPU = A->getValue(Args);
+
+    // Set the target features based on the FPU.
+    if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
+      // Disable any default FPU support.
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-vfp2");
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-vfp3");
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("-neon");
+    } else if (FPU == "vfp") {
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("+vfp2");
+    } else if (FPU == "vfp3") {
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("+vfp3");
+    } else if (FPU == "neon") {
+      CmdArgs.push_back("-target-feature");
+      CmdArgs.push_back("+neon");
+    } else
+      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+  }
+}
+
+void Clang::AddX86TargetArgs(const ArgList &Args,
+                             ArgStringList &CmdArgs) const {
+  if (!Args.hasFlag(options::OPT_mred_zone,
+                    options::OPT_mno_red_zone,
+                    true) ||
+      Args.hasArg(options::OPT_mkernel) ||
+      Args.hasArg(options::OPT_fapple_kext))
+    CmdArgs.push_back("-disable-red-zone");
+
+  if (Args.hasFlag(options::OPT_msoft_float,
+                   options::OPT_mno_soft_float,
+                   false))
+    CmdArgs.push_back("-no-implicit-float");
+
+  const char *CPUName = 0;
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    if (llvm::StringRef(A->getValue(Args)) == "native") {
+      // FIXME: Reject attempts to use -march=native unless the target matches
+      // the host.
+      //
+      // FIXME: We should also incorporate the detected target features for use
+      // with -native.
+      std::string CPU = llvm::sys::getHostCPUName();
+      if (!CPU.empty())
+        CPUName = Args.MakeArgString(CPU);
+    } else
+      CPUName = A->getValue(Args);
+  }
+
+  // Select the default CPU if none was given (or detection failed).
+  if (!CPUName) {
+    // FIXME: Need target hooks.
+    if (getToolChain().getOS().startswith("darwin")) {
+      if (getToolChain().getArchName() == "x86_64")
+        CPUName = "core2";
+      else if (getToolChain().getArchName() == "i386")
+        CPUName = "yonah";
+    } else {
+      if (getToolChain().getArchName() == "x86_64")
+        CPUName = "x86-64";
+      else if (getToolChain().getArchName() == "i386")
+        CPUName = "pentium4";
+    }
+  }
+
+  if (CPUName) {
+    CmdArgs.push_back("-target-cpu");
+    CmdArgs.push_back(CPUName);
+  }
+
+  for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    llvm::StringRef Name = it->getOption().getName();
+    it->claim();
+
+    // Skip over "-m".
+    assert(Name.startswith("-m") && "Invalid feature name.");
+    Name = Name.substr(2);
+
+    bool IsNegative = Name.startswith("no-");
+    if (IsNegative)
+      Name = Name.substr(3);
+
+    CmdArgs.push_back("-target-feature");
+    CmdArgs.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+  }
+}
+
+static bool needsExceptions(const ArgList &Args,  types::ID InputType,
+                            const llvm::Triple &Triple) {
+  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
+                               options::OPT_fno_exceptions)) {
+    if (A->getOption().matches(options::OPT_fexceptions))
+      return true;
+    else
+      return false;
+  }
+  switch (InputType) {
+  case types::TY_CXX: case types::TY_CXXHeader:
+  case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
+  case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
+  case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
+    return true;
+
+  case types::TY_ObjC: case types::TY_ObjCHeader:
+  case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
+    if (Args.hasArg(options::OPT_fobjc_nonfragile_abi))
+      return true;
+    if (Triple.getOS() != llvm::Triple::Darwin)
+      return false;
+    return (Triple.getDarwinMajorNumber() >= 9 &&
+            Triple.getArch() == llvm::Triple::x86_64);
+
+  default:
+    return false;
+  }
+}
+
+/// getEffectiveClangTriple - Get the "effective" target triple, which is the
+/// triple for the target but with the OS version potentially modified for
+/// Darwin's -mmacosx-version-min.
+static std::string getEffectiveClangTriple(const Driver &D,
+                                           const ToolChain &TC,
+                                           const ArgList &Args) {
+  llvm::Triple Triple(getLLVMTriple(TC, Args));
+
+  // Handle -mmacosx-version-min and -miphoneos-version-min.
+  if (Triple.getOS() != llvm::Triple::Darwin) {
+    // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+    // non-Darwin.
+    if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+                                 options::OPT_miphoneos_version_min_EQ))
+      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+  } else {
+    const toolchains::Darwin &DarwinTC(
+      reinterpret_cast<const toolchains::Darwin&>(TC));
+    unsigned Version[3];
+    DarwinTC.getTargetVersion(Version);
+
+    // Mangle the target version into the OS triple component.  For historical
+    // reasons that make little sense, the version passed here is the "darwin"
+    // version, which drops the 10 and offsets by 4. See inverse code when
+    // setting the OS version preprocessor define.
+    if (!DarwinTC.isTargetIPhoneOS()) {
+      Version[0] = Version[1] + 4;
+      Version[1] = Version[2];
+      Version[2] = 0;
+    } else {
+      // Use the environment to communicate that we are targetting iPhoneOS.
+      Triple.setEnvironmentName("iphoneos");
+    }
+
+    llvm::SmallString<16> Str;
+    llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
+                                   << "." << Version[1] << "." << Version[2];
+    Triple.setOSName(Str.str());
+  }
+
+  return Triple.getTriple();
+}
+
+void Clang::ConstructJob(Compilation &C, const JobAction &JA,
+                         Job &Dest,
+                         const InputInfo &Output,
+                         const InputInfoList &Inputs,
+                         const ArgList &Args,
+                         const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+
+  // Invoke ourselves in -cc1 mode.
+  //
+  // FIXME: Implement custom jobs for internal actions.
+  CmdArgs.push_back("-cc1");
+
+  // Add the "effective" target triple.
+  CmdArgs.push_back("-triple");
+  std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+  CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+  // Select the appropriate action.
+  if (isa<AnalyzeJobAction>(JA)) {
+    assert(JA.getType() == types::TY_Plist && "Invalid output type.");
+    CmdArgs.push_back("-analyze");
+  } else if (isa<PreprocessJobAction>(JA)) {
+    if (Output.getType() == types::TY_Dependencies)
+      CmdArgs.push_back("-Eonly");
+    else
+      CmdArgs.push_back("-E");
+  } else if (isa<AssembleJobAction>(JA)) {
+    CmdArgs.push_back("-emit-obj");
+  } else if (isa<PrecompileJobAction>(JA)) {
+    // Use PCH if the user requested it, except for C++ (for now).
+    bool UsePCH = D.CCCUsePCH;
+    if (types::isCXX(Inputs[0].getType()))
+      UsePCH = false;
+
+    if (UsePCH)
+      CmdArgs.push_back("-emit-pch");
+    else
+      CmdArgs.push_back("-emit-pth");
+  } else {
+    assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
+
+    if (JA.getType() == types::TY_Nothing) {
+      CmdArgs.push_back("-fsyntax-only");
+    } else if (JA.getType() == types::TY_LLVMAsm) {
+      CmdArgs.push_back("-emit-llvm");
+    } else if (JA.getType() == types::TY_LLVMBC) {
+      CmdArgs.push_back("-emit-llvm-bc");
+    } else if (JA.getType() == types::TY_PP_Asm) {
+      CmdArgs.push_back("-S");
+    } else if (JA.getType() == types::TY_AST) {
+      CmdArgs.push_back("-emit-pch");
+    }
+  }
+
+  // The make clang go fast button.
+  CmdArgs.push_back("-disable-free");
+
+  // Set the main file name, so that debug info works even with
+  // -save-temps.
+  CmdArgs.push_back("-main-file-name");
+  CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
+
+  // Some flags which affect the language (via preprocessor
+  // defines). See darwin::CC1::AddCPPArgs.
+  if (Args.hasArg(options::OPT_static))
+    CmdArgs.push_back("-static-define");
+
+  if (isa<AnalyzeJobAction>(JA)) {
+    // Enable region store model by default.
+    CmdArgs.push_back("-analyzer-store=region");
+
+    // Treat blocks as analysis entry points.
+    CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
+
+    // Add default argument set.
+    if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
+      CmdArgs.push_back("-analyzer-check-dead-stores");
+      CmdArgs.push_back("-analyzer-check-security-syntactic");
+      CmdArgs.push_back("-analyzer-check-objc-mem");
+      CmdArgs.push_back("-analyzer-eagerly-assume");
+      CmdArgs.push_back("-analyzer-check-objc-methodsigs");
+      // Do not enable the missing -dealloc check.
+      // '-analyzer-check-objc-missing-dealloc',
+      CmdArgs.push_back("-analyzer-check-objc-unused-ivars");
+    }
+
+    // Set the output format. The default is plist, for (lame) historical
+    // reasons.
+    CmdArgs.push_back("-analyzer-output");
+    if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
+      CmdArgs.push_back(A->getValue(Args));
+    else
+      CmdArgs.push_back("plist");
+
+    // Add -Xanalyzer arguments when running as analyzer.
+    Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
+  }
+
+  CheckCodeGenerationOptions(D, Args);
+
+  // Perform argument translation for LLVM backend. This
+  // takes some care in reconciling with llvm-gcc. The
+  // issue is that llvm-gcc translates these options based on
+  // the values in cc1, whereas we are processing based on
+  // the driver arguments.
+
+  // This comes from the default translation the driver + cc1
+  // would do to enable flag_pic.
+  //
+  // FIXME: Centralize this code.
+  bool PICEnabled = (Args.hasArg(options::OPT_fPIC) ||
+                     Args.hasArg(options::OPT_fpic) ||
+                     Args.hasArg(options::OPT_fPIE) ||
+                     Args.hasArg(options::OPT_fpie));
+  bool PICDisabled = (Args.hasArg(options::OPT_mkernel) ||
+                      Args.hasArg(options::OPT_static));
+  const char *Model = getToolChain().GetForcedPicModel();
+  if (!Model) {
+    if (Args.hasArg(options::OPT_mdynamic_no_pic))
+      Model = "dynamic-no-pic";
+    else if (PICDisabled)
+      Model = "static";
+    else if (PICEnabled)
+      Model = "pic";
+    else
+      Model = getToolChain().GetDefaultRelocationModel();
+  }
+  if (llvm::StringRef(Model) != "pic") {
+    CmdArgs.push_back("-mrelocation-model");
+    CmdArgs.push_back(Model);
+  }
+
+  // Infer the __PIC__ value.
+  //
+  // FIXME:  This isn't quite right on Darwin, which always sets
+  // __PIC__=2.
+  if (strcmp(Model, "pic") == 0 || strcmp(Model, "dynamic-no-pic") == 0) {
+    CmdArgs.push_back("-pic-level");
+    CmdArgs.push_back(Args.hasArg(options::OPT_fPIC) ? "2" : "1");
+  }
+  if (!Args.hasFlag(options::OPT_fmerge_all_constants,
+                    options::OPT_fno_merge_all_constants))
+    CmdArgs.push_back("-no-merge-all-constants");
+
+  // LLVM Code Generator Options.
+
+  // FIXME: Set --enable-unsafe-fp-math.
+  if (Args.hasFlag(options::OPT_fno_omit_frame_pointer,
+                   options::OPT_fomit_frame_pointer))
+    CmdArgs.push_back("-mdisable-fp-elim");
+  if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
+                    options::OPT_fno_zero_initialized_in_bss))
+    CmdArgs.push_back("-mno-zero-initialized-in-bss");
+  if (Args.hasArg(options::OPT_dA) || Args.hasArg(options::OPT_fverbose_asm))
+    CmdArgs.push_back("-masm-verbose");
+  if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
+    CmdArgs.push_back("-mdebug-pass");
+    CmdArgs.push_back("Structure");
+  }
+  if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
+    CmdArgs.push_back("-mdebug-pass");
+    CmdArgs.push_back("Arguments");
+  }
+
+  // This is a coarse approximation of what llvm-gcc actually does, both
+  // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
+  // complicated ways.
+  bool AsynchronousUnwindTables =
+    Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
+                 options::OPT_fno_asynchronous_unwind_tables,
+                 getToolChain().IsUnwindTablesDefault() &&
+                 !Args.hasArg(options::OPT_mkernel));
+  if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
+                   AsynchronousUnwindTables))
+    CmdArgs.push_back("-munwind-tables");
+
+  if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+    CmdArgs.push_back("-mlimit-float-precision");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  // FIXME: Handle -mtune=.
+  (void) Args.hasArg(options::OPT_mtune_EQ);
+
+  if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+    CmdArgs.push_back("-mcode-model");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  // Add target specific cpu and features flags.
+  switch(getToolChain().getTriple().getArch()) {
+  default:
+    break;
+
+  case llvm::Triple::arm:
+  case llvm::Triple::thumb:
+    AddARMTargetArgs(Args, CmdArgs);
+    break;
+
+  case llvm::Triple::x86:
+  case llvm::Triple::x86_64:
+    AddX86TargetArgs(Args, CmdArgs);
+    break;
+  }
+
+  // -fno-math-errno is default.
+  if (Args.hasFlag(options::OPT_fmath_errno,
+                   options::OPT_fno_math_errno,
+                   false))
+    CmdArgs.push_back("-fmath-errno");
+
+  Arg *Unsupported;
+  if ((Unsupported = Args.getLastArg(options::OPT_MG)) ||
+      (Unsupported = Args.getLastArg(options::OPT_MQ)) ||
+      (Unsupported = Args.getLastArg(options::OPT_iframework)) ||
+      (Unsupported = Args.getLastArg(options::OPT_fshort_enums)))
+    D.Diag(clang::diag::err_drv_clang_unsupported)
+      << Unsupported->getOption().getName();
+
+  Args.AddAllArgs(CmdArgs, options::OPT_v);
+  Args.AddLastArg(CmdArgs, options::OPT_P);
+  Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
+
+  // Special case debug options to only pass -g to clang. This is
+  // wrong.
+  if (Args.hasArg(options::OPT_g_Group))
+    CmdArgs.push_back("-g");
+
+  Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
+  Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
+
+  // Pass the path to compiler resource files.
+  CmdArgs.push_back("-resource-dir");
+  CmdArgs.push_back(D.ResourceDir.c_str());
+
+  // Add preprocessing options like -I, -D, etc. if we are using the
+  // preprocessor.
+  //
+  // FIXME: Support -fpreprocessed
+  types::ID InputType = Inputs[0].getType();
+  if (types::getPreprocessedType(InputType) != types::TY_INVALID)
+    AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs);
+
+  // Manually translate -O to -O2 and -O4 to -O3; let clang reject
+  // others.
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+    if (A->getOption().matches(options::OPT_O4))
+      CmdArgs.push_back("-O3");
+    else if (A->getValue(Args)[0] == '\0')
+      CmdArgs.push_back("-O2");
+    else
+      A->render(Args, CmdArgs);
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+  Args.AddLastArg(CmdArgs, options::OPT_pedantic);
+  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
+  Args.AddLastArg(CmdArgs, options::OPT_w);
+
+  // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
+  // (-ansi is equivalent to -std=c89).
+  //
+  // If a std is supplied, only add -trigraphs if it follows the
+  // option.
+  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+    if (Std->getOption().matches(options::OPT_ansi))
+      if (types::isCXX(InputType))
+        CmdArgs.push_back("-std=c++98");
+      else
+        CmdArgs.push_back("-std=c89");
+    else
+      Std->render(Args, CmdArgs);
+
+    if (Arg *A = Args.getLastArg(options::OPT_trigraphs))
+      if (A->getIndex() > Std->getIndex())
+        A->render(Args, CmdArgs);
+  } else {
+    // Honor -std-default.
+    //
+    // FIXME: Clang doesn't correctly handle -std= when the input language
+    // doesn't match. For the time being just ignore this for C++ inputs;
+    // eventually we want to do all the standard defaulting here instead of
+    // splitting it between the driver and clang -cc1.
+    if (!types::isCXX(InputType))
+        Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+                                  "-std=", /*Joined=*/true);
+    Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
+  }
+
+  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) {
+    CmdArgs.push_back("-ftemplate-depth");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  if (Args.hasArg(options::OPT__relocatable_pch))
+    CmdArgs.push_back("-relocatable-pch");
+
+  if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+    CmdArgs.push_back("-fconstant-string-class");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
+    CmdArgs.push_back("-ftabstop");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  // Pass -fmessage-length=.
+  CmdArgs.push_back("-fmessage-length");
+  if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
+    CmdArgs.push_back(A->getValue(Args));
+  } else {
+    // If -fmessage-length=N was not specified, determine whether this is a
+    // terminal and, if so, implicitly define -fmessage-length appropriately.
+    unsigned N = llvm::sys::Process::StandardErrColumns();
+    CmdArgs.push_back(Args.MakeArgString(llvm::Twine(N)));
+  }
+
+  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) {
+    CmdArgs.push_back("-fvisibility");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
+  // Forward -f (flag) options which we can pass directly.
+  Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior);
+  Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
+  Args.AddLastArg(CmdArgs, options::OPT_ffreestanding);
+  Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
+  Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions);
+  Args.AddLastArg(CmdArgs, options::OPT_fno_caret_diagnostics);
+  Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
+  Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc_only);
+  Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc);
+  Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
+  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
+  Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
+  Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
+  Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
+
+  Args.AddLastArg(CmdArgs, options::OPT_pthread);
+
+  // -stack-protector=0 is default.
+  unsigned StackProtectorLevel = 0;
+  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+                               options::OPT_fstack_protector_all,
+                               options::OPT_fstack_protector)) {
+    if (A->getOption().matches(options::OPT_fstack_protector))
+      StackProtectorLevel = 1;
+    else if (A->getOption().matches(options::OPT_fstack_protector_all))
+      StackProtectorLevel = 2;
+  } else
+    StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel();
+  if (StackProtectorLevel) {
+    CmdArgs.push_back("-stack-protector");
+    CmdArgs.push_back(Args.MakeArgString(llvm::Twine(StackProtectorLevel)));
+  }
+
+  // Forward -f options with positive and negative forms; we translate
+  // these by hand.
+
+  // -fbuiltin is default.
+  if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
+    CmdArgs.push_back("-fno-builtin");
+
+  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+                    options::OPT_fno_assume_sane_operator_new))
+    CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+  // -fblocks=0 is default.
+  if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
+                   getToolChain().IsBlocksDefault())) {
+    Args.AddLastArg(CmdArgs, options::OPT_fblock_introspection);
+    CmdArgs.push_back("-fblocks");
+  }
+
+  // -fexceptions=0 is default.
+  if (needsExceptions(Args, InputType, getToolChain().getTriple()))
+    CmdArgs.push_back("-fexceptions");
+
+  // -frtti is default.
+  if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
+    CmdArgs.push_back("-fno-rtti");
+
+  // -fsigned-char is default.
+  if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
+                    isSignedCharDefault(getToolChain().getTriple())))
+    CmdArgs.push_back("-fno-signed-char");
+
+  // -fthreadsafe-static is default.
+  if (!Args.hasFlag(options::OPT_fthreadsafe_statics, 
+                    options::OPT_fno_threadsafe_statics))
+    CmdArgs.push_back("-fno-threadsafe-statics");
+
+  // -fms-extensions=0 is default.
+  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
+    CmdArgs.push_back("-fms-extensions");
+
+  // -fnext-runtime is default.
+  if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
+                    getToolChain().getTriple().getOS() == llvm::Triple::Darwin))
+    CmdArgs.push_back("-fgnu-runtime");
+
+  // -fobjc-nonfragile-abi=0 is default.
+  if (types::isObjC(InputType)) {
+    if (Args.hasArg(options::OPT_fobjc_nonfragile_abi) ||
+        getToolChain().IsObjCNonFragileABIDefault()) {
+      CmdArgs.push_back("-fobjc-nonfragile-abi");
+      
+      // -fobjc-legacy-dispatch is only relevant with the nonfragile-abi, and
+      // defaults to off.
+      if (Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
+                       options::OPT_fno_objc_legacy_dispatch,
+                       getToolChain().IsObjCLegacyDispatchDefault()))
+        CmdArgs.push_back("-fobjc-legacy-dispatch");
+    }
+  }
+
+  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+                    options::OPT_fno_assume_sane_operator_new))
+    CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+  // -fshort-wchar default varies depending on platform; only
+  // pass if specified.
+  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) {
+    if (A->getOption().matches(options::OPT_fshort_wchar))
+      CmdArgs.push_back("-fshort-wchar");
+  }
+
+  // -fno-pascal-strings is default, only pass non-default. If the tool chain
+  // happened to translate to -mpascal-strings, we want to back translate here.
+  //
+  // FIXME: This is gross; that translation should be pulled from the
+  // tool chain.
+  if (Args.hasFlag(options::OPT_fpascal_strings,
+                   options::OPT_fno_pascal_strings,
+                   false) ||
+      Args.hasFlag(options::OPT_mpascal_strings,
+                   options::OPT_mno_pascal_strings,
+                   false))
+    CmdArgs.push_back("-fpascal-strings");
+
+  // -fcommon is default, only pass non-default.
+  if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
+    CmdArgs.push_back("-fno-common");
+
+  // -fsigned-bitfields is default, and clang doesn't yet support
+  // --funsigned-bitfields.
+  if (!Args.hasFlag(options::OPT_fsigned_bitfields,
+                    options::OPT_funsigned_bitfields))
+    D.Diag(clang::diag::warn_drv_clang_unsupported)
+      << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
+
+  // -fdiagnostics-fixit-info is default, only pass non-default.
+  if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
+                    options::OPT_fno_diagnostics_fixit_info))
+    CmdArgs.push_back("-fno-diagnostics-fixit-info");
+
+  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_binary);
+
+  // Enable -fdiagnostics-show-option by default.
+  if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
+                   options::OPT_fno_diagnostics_show_option))
+    CmdArgs.push_back("-fdiagnostics-show-option");
+
+  // Color diagnostics are the default, unless the terminal doesn't support
+  // them.
+  if (Args.hasFlag(options::OPT_fcolor_diagnostics,
+                   options::OPT_fno_color_diagnostics) &&
+      llvm::sys::Process::StandardErrHasColors())
+    CmdArgs.push_back("-fcolor-diagnostics");
+
+  if (!Args.hasFlag(options::OPT_fshow_source_location,
+                    options::OPT_fno_show_source_location))
+    CmdArgs.push_back("-fno-show-source-location");
+
+  // -fdollars-in-identifiers default varies depending on platform and
+  // language; only pass if specified.
+  if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
+                               options::OPT_fno_dollars_in_identifiers)) {
+    if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
+      CmdArgs.push_back("-fdollars-in-identifiers");
+    else
+      CmdArgs.push_back("-fno-dollars-in-identifiers");
+  }
+
+  // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
+  // practical purposes.
+  if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
+                               options::OPT_fno_unit_at_a_time)) {
+    if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
+      D.Diag(clang::diag::warn_drv_clang_unsupported) << A->getAsString(Args);
+  }
+
+  // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
+  //
+  // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
+#if 0
+  if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
+      (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+       getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
+    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+      CmdArgs.push_back("-fno-builtin-strcat");
+    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+      CmdArgs.push_back("-fno-builtin-strcpy");
+  }
+#endif
+
+  if (Arg *A = Args.getLastArg(options::OPT_traditional,
+                               options::OPT_traditional_cpp))
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
+  Args.AddLastArg(CmdArgs, options::OPT_dM);
+  Args.AddLastArg(CmdArgs, options::OPT_dD);
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
+  Args.AddAllArgValues(CmdArgs, options::OPT_mllvm);
+
+  if (Output.getType() == types::TY_Dependencies) {
+    // Handled with other dependency code.
+  } else if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    CmdArgs.push_back("-x");
+    CmdArgs.push_back(types::getTypeName(II.getType()));
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_undef);
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "clang"));
+
+  // Optionally embed the -cc1 level arguments into the debug info, for build
+  // analysis.
+  if (getToolChain().UseDwarfDebugFlags()) {
+    llvm::SmallString<256> Flags;
+    Flags += Exec;
+    for (unsigned i = 0, e = CmdArgs.size(); i != e; ++i) {
+      Flags += " ";
+      Flags += CmdArgs[i];
+    }
+    CmdArgs.push_back("-dwarf-debug-flags");
+    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+  }
+
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+  // Explicitly warn that these options are unsupported, even though
+  // we are allowing compilation to continue.
+  for (arg_iterator it = Args.filtered_begin(options::OPT_pg),
+         ie = Args.filtered_end(); it != ie; ++it) {
+    it->claim();
+    D.Diag(clang::diag::warn_drv_clang_unsupported) << it->getAsString(Args);
+  }
+
+  // Claim some arguments which clang supports automatically.
+
+  // -fpch-preprocess is used with gcc to add a special marker in the
+  // -output to include the PCH file. Clang's PTH solution is
+  // -completely transparent, so we do not need to deal with it at
+  // -all.
+  Args.ClaimAllArgs(options::OPT_fpch_preprocess);
+
+  // Claim some arguments which clang doesn't support, but we don't
+  // care to warn the user about.
+  Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
+  Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
+}
+
+void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
+                               Job &Dest,
+                               const InputInfo &Output,
+                               const InputInfoList &Inputs,
+                               const ArgList &Args,
+                               const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  for (ArgList::const_iterator
+         it = Args.begin(), ie = Args.end(); it != ie; ++it) {
+    Arg *A = *it;
+    if (A->getOption().hasForwardToGCC()) {
+      // It is unfortunate that we have to claim here, as this means
+      // we will basically never report anything interesting for
+      // platforms using a generic gcc, even if we are just using gcc
+      // to get to the assembler.
+      A->claim();
+      A->render(Args, CmdArgs);
+    }
+  }
+
+  RenderExtraToolArgs(JA, CmdArgs);
+
+  // If using a driver driver, force the arch.
+  const std::string &Arch = getToolChain().getArchName();
+  if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin) {
+    CmdArgs.push_back("-arch");
+
+    // FIXME: Remove these special cases.
+    if (Arch == "powerpc")
+      CmdArgs.push_back("ppc");
+    else if (Arch == "powerpc64")
+      CmdArgs.push_back("ppc64");
+    else
+      CmdArgs.push_back(Args.MakeArgString(Arch));
+  }
+
+  // Try to force gcc to match the tool chain we want, if we recognize
+  // the arch.
+  //
+  // FIXME: The triple class should directly provide the information we want
+  // here.
+  if (Arch == "i386" || Arch == "powerpc")
+    CmdArgs.push_back("-m32");
+  else if (Arch == "x86_64" || Arch == "powerpc64")
+    CmdArgs.push_back("-m64");
+
+  if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Unexpected output");
+    CmdArgs.push_back("-fsyntax-only");
+  }
+
+
+  // Only pass -x if gcc will understand it; otherwise hope gcc
+  // understands the suffix correctly. The main use case this would go
+  // wrong in is for linker inputs if they happened to have an odd
+  // suffix; really the only way to get this to happen is a command
+  // like '-x foobar a.c' which will treat a.c like a linker input.
+  //
+  // FIXME: For the linker case specifically, can we safely convert
+  // inputs into '-Wl,' options?
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    // Don't try to pass LLVM or AST inputs to a generic gcc.
+    if (II.getType() == types::TY_LLVMBC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+        << getToolChain().getTripleString();
+    else if (II.getType() == types::TY_AST)
+      D.Diag(clang::diag::err_drv_no_ast_support)
+        << getToolChain().getTripleString();
+
+    if (types::canTypeBeUserSpecified(II.getType())) {
+      CmdArgs.push_back("-x");
+      CmdArgs.push_back(types::getTypeName(II.getType()));
+    }
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      // Don't render as input, we need gcc to do the translations.
+      II.getInputArg().render(Args, CmdArgs);
+  }
+
+  const char *GCCName = getToolChain().getDriver().CCCGenericGCCName.c_str();
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
+                                          ArgStringList &CmdArgs) const {
+  CmdArgs.push_back("-E");
+}
+
+void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA,
+                                          ArgStringList &CmdArgs) const {
+  // The type is good enough.
+}
+
+void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
+                                       ArgStringList &CmdArgs) const {
+  // If -flto, etc. are present then make sure not to force assembly output.
+  if (JA.getType() == types::TY_LLVMBC)
+    CmdArgs.push_back("-c");
+  else
+    CmdArgs.push_back("-S");
+}
+
+void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA,
+                                        ArgStringList &CmdArgs) const {
+  CmdArgs.push_back("-c");
+}
+
+void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
+                                    ArgStringList &CmdArgs) const {
+  // The types are (hopefully) good enough.
+}
+
+const char *darwin::CC1::getCC1Name(types::ID Type) const {
+  switch (Type) {
+  default:
+    assert(0 && "Unexpected type for Darwin CC1 tool.");
+  case types::TY_Asm:
+  case types::TY_C: case types::TY_CHeader:
+  case types::TY_PP_C: case types::TY_PP_CHeader:
+    return "cc1";
+  case types::TY_ObjC: case types::TY_ObjCHeader:
+  case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
+    return "cc1obj";
+  case types::TY_CXX: case types::TY_CXXHeader:
+  case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
+    return "cc1plus";
+  case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
+  case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
+    return "cc1objplus";
+  }
+}
+
+const char *darwin::CC1::getBaseInputName(const ArgList &Args,
+                                          const InputInfoList &Inputs) {
+  llvm::sys::Path P(Inputs[0].getBaseInput());
+  return Args.MakeArgString(P.getLast());
+}
+
+const char *darwin::CC1::getBaseInputStem(const ArgList &Args,
+                                          const InputInfoList &Inputs) {
+  const char *Str = getBaseInputName(Args, Inputs);
+
+  if (const char *End = strchr(Str, '.'))
+    return Args.MakeArgString(std::string(Str, End));
+
+  return Str;
+}
+
+const char *
+darwin::CC1::getDependencyFileName(const ArgList &Args,
+                                   const InputInfoList &Inputs) {
+  // FIXME: Think about this more.
+  std::string Res;
+
+  if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+    std::string Str(OutputOpt->getValue(Args));
+
+    Res = Str.substr(0, Str.rfind('.'));
+  } else
+    Res = darwin::CC1::getBaseInputStem(Args, Inputs);
+
+  return Args.MakeArgString(Res + ".d");
+}
+
+void darwin::CC1::AddCC1Args(const ArgList &Args,
+                             ArgStringList &CmdArgs) const {
+  const Driver &D = getToolChain().getDriver();
+
+  CheckCodeGenerationOptions(D, Args);
+
+  // Derived from cc1 spec.
+  if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) &&
+      !Args.hasArg(options::OPT_mdynamic_no_pic))
+    CmdArgs.push_back("-fPIC");
+
+  if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+      getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+      CmdArgs.push_back("-fno-builtin-strcat");
+    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+      CmdArgs.push_back("-fno-builtin-strcpy");
+  }
+
+  // gcc has some code here to deal with when no -mmacosx-version-min
+  // and no -miphoneos-version-min is present, but this never happens
+  // due to tool chain specific argument translation.
+
+  if (Args.hasArg(options::OPT_g_Flag) &&
+      !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols))
+    CmdArgs.push_back("-feliminate-unused-debug-symbols");
+}
+
+void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+                                    const InputInfoList &Inputs,
+                                    const ArgStringList &OutputArgs) const {
+  const Driver &D = getToolChain().getDriver();
+
+  // Derived from cc1_options spec.
+  if (Args.hasArg(options::OPT_fast) ||
+      Args.hasArg(options::OPT_fastf) ||
+      Args.hasArg(options::OPT_fastcp))
+    CmdArgs.push_back("-O3");
+
+  if (Arg *A = Args.getLastArg(options::OPT_pg))
+    if (Args.hasArg(options::OPT_fomit_frame_pointer))
+      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+        << A->getAsString(Args) << "-fomit-frame-pointer";
+
+  AddCC1Args(Args, CmdArgs);
+
+  if (!Args.hasArg(options::OPT_Q))
+    CmdArgs.push_back("-quiet");
+
+  CmdArgs.push_back("-dumpbase");
+  CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs));
+
+  Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
+
+  Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_a_Group);
+
+  // FIXME: The goal is to use the user provided -o if that is our
+  // final output, otherwise to drive from the original input
+  // name. Find a clean way to go about this.
+  if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
+      Args.hasArg(options::OPT_o)) {
+    Arg *OutputOpt = Args.getLastArg(options::OPT_o);
+    CmdArgs.push_back("-auxbase-strip");
+    CmdArgs.push_back(OutputOpt->getValue(Args));
+  } else {
+    CmdArgs.push_back("-auxbase");
+    CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs));
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_g_Group);
+
+  Args.AddAllArgs(CmdArgs, options::OPT_O);
+  // FIXME: -Wall is getting some special treatment. Investigate.
+  Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+  Args.AddLastArg(CmdArgs, options::OPT_w);
+  Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
+                  options::OPT_trigraphs);
+  if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+    // Honor -std-default.
+    Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+                              "-std=", /*Joined=*/true);
+  }
+
+  if (Args.hasArg(options::OPT_v))
+    CmdArgs.push_back("-version");
+  if (Args.hasArg(options::OPT_pg))
+    CmdArgs.push_back("-p");
+  Args.AddLastArg(CmdArgs, options::OPT_p);
+
+  // The driver treats -fsyntax-only specially.
+  if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+      getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+    // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are
+    // used to inhibit the default -fno-builtin-str{cat,cpy}.
+    //
+    // FIXME: Should we grow a better way to deal with "removing" args?
+    for (arg_iterator it = Args.filtered_begin(options::OPT_f_Group,
+                                               options::OPT_fsyntax_only),
+           ie = Args.filtered_end(); it != ie; ++it) {
+      if (!it->getOption().matches(options::OPT_fbuiltin_strcat) &&
+          !it->getOption().matches(options::OPT_fbuiltin_strcpy)) {
+        it->claim();
+        it->render(Args, CmdArgs);
+      }
+    }
+  } else
+    Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
+
+  Args.AddAllArgs(CmdArgs, options::OPT_undef);
+  if (Args.hasArg(options::OPT_Qn))
+    CmdArgs.push_back("-fno-ident");
+
+  // FIXME: This isn't correct.
+  //Args.AddLastArg(CmdArgs, options::OPT__help)
+  //Args.AddLastArg(CmdArgs, options::OPT__targetHelp)
+
+  CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+
+  // FIXME: Still don't get what is happening here. Investigate.
+  Args.AddAllArgs(CmdArgs, options::OPT__param);
+
+  if (Args.hasArg(options::OPT_fmudflap) ||
+      Args.hasArg(options::OPT_fmudflapth)) {
+    CmdArgs.push_back("-fno-builtin");
+    CmdArgs.push_back("-fno-merge-constants");
+  }
+
+  if (Args.hasArg(options::OPT_coverage)) {
+    CmdArgs.push_back("-fprofile-arcs");
+    CmdArgs.push_back("-ftest-coverage");
+  }
+
+  if (types::isCXX(Inputs[0].getType()))
+    CmdArgs.push_back("-D__private_extern__=extern");
+}
+
+void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+                                    const InputInfoList &Inputs,
+                                    const ArgStringList &OutputArgs) const {
+  // Derived from cpp_options
+  AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
+
+  CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+
+  AddCC1Args(Args, CmdArgs);
+
+  // NOTE: The code below has some commonality with cpp_options, but
+  // in classic gcc style ends up sending things in different
+  // orders. This may be a good merge candidate once we drop pedantic
+  // compatibility.
+
+  Args.AddAllArgs(CmdArgs, options::OPT_m_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi,
+                  options::OPT_trigraphs);
+  if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+    // Honor -std-default.
+    Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+                              "-std=", /*Joined=*/true);
+  }
+  Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group);
+  Args.AddLastArg(CmdArgs, options::OPT_w);
+
+  // The driver treats -fsyntax-only specially.
+  Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
+
+  if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) &&
+      !Args.hasArg(options::OPT_fno_working_directory))
+    CmdArgs.push_back("-fworking-directory");
+
+  Args.AddAllArgs(CmdArgs, options::OPT_O);
+  Args.AddAllArgs(CmdArgs, options::OPT_undef);
+  if (Args.hasArg(options::OPT_save_temps))
+    CmdArgs.push_back("-fpch-preprocess");
+}
+
+void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
+                                          ArgStringList &CmdArgs,
+                                          const InputInfoList &Inputs) const {
+  const Driver &D = getToolChain().getDriver();
+
+  CheckPreprocessingOptions(D, Args);
+
+  // Derived from cpp_unique_options.
+  // -{C,CC} only with -E is checked in CheckPreprocessingOptions().
+  Args.AddLastArg(CmdArgs, options::OPT_C);
+  Args.AddLastArg(CmdArgs, options::OPT_CC);
+  if (!Args.hasArg(options::OPT_Q))
+    CmdArgs.push_back("-quiet");
+  Args.AddAllArgs(CmdArgs, options::OPT_nostdinc);
+  Args.AddLastArg(CmdArgs, options::OPT_v);
+  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F);
+  Args.AddLastArg(CmdArgs, options::OPT_P);
+
+  // FIXME: Handle %I properly.
+  if (getToolChain().getArchName() == "x86_64") {
+    CmdArgs.push_back("-imultilib");
+    CmdArgs.push_back("x86_64");
+  }
+
+  if (Args.hasArg(options::OPT_MD)) {
+    CmdArgs.push_back("-MD");
+    CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
+  }
+
+  if (Args.hasArg(options::OPT_MMD)) {
+    CmdArgs.push_back("-MMD");
+    CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs));
+  }
+
+  Args.AddLastArg(CmdArgs, options::OPT_M);
+  Args.AddLastArg(CmdArgs, options::OPT_MM);
+  Args.AddAllArgs(CmdArgs, options::OPT_MF);
+  Args.AddLastArg(CmdArgs, options::OPT_MG);
+  Args.AddLastArg(CmdArgs, options::OPT_MP);
+  Args.AddAllArgs(CmdArgs, options::OPT_MQ);
+  Args.AddAllArgs(CmdArgs, options::OPT_MT);
+  if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) &&
+      (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) {
+    if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+      CmdArgs.push_back("-MQ");
+      CmdArgs.push_back(OutputOpt->getValue(Args));
+    }
+  }
+
+  Args.AddLastArg(CmdArgs, options::OPT_remap);
+  if (Args.hasArg(options::OPT_g3))
+    CmdArgs.push_back("-dD");
+  Args.AddLastArg(CmdArgs, options::OPT_H);
+
+  AddCPPArgs(Args, CmdArgs);
+
+  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A);
+  Args.AddAllArgs(CmdArgs, options::OPT_i_Group);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else
+      CmdArgs.push_back(II.getFilename());
+  }
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
+                       options::OPT_Xpreprocessor);
+
+  if (Args.hasArg(options::OPT_fmudflap)) {
+    CmdArgs.push_back("-D_MUDFLAP");
+    CmdArgs.push_back("-include");
+    CmdArgs.push_back("mf-runtime.h");
+  }
+
+  if (Args.hasArg(options::OPT_fmudflapth)) {
+    CmdArgs.push_back("-D_MUDFLAP");
+    CmdArgs.push_back("-D_MUDFLAPTH");
+    CmdArgs.push_back("-include");
+    CmdArgs.push_back("mf-runtime.h");
+  }
+}
+
+void darwin::CC1::AddCPPArgs(const ArgList &Args,
+                             ArgStringList &CmdArgs) const {
+  // Derived from cpp spec.
+
+  if (Args.hasArg(options::OPT_static)) {
+    // The gcc spec is broken here, it refers to dynamic but
+    // that has been translated. Start by being bug compatible.
+
+    // if (!Args.hasArg(arglist.parser.dynamicOption))
+    CmdArgs.push_back("-D__STATIC__");
+  } else
+    CmdArgs.push_back("-D__DYNAMIC__");
+
+  if (Args.hasArg(options::OPT_pthread))
+    CmdArgs.push_back("-D_REENTRANT");
+}
+
+void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
+                                      Job &Dest, const InputInfo &Output,
+                                      const InputInfoList &Inputs,
+                                      const ArgList &Args,
+                                      const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  assert(Inputs.size() == 1 && "Unexpected number of inputs!");
+
+  CmdArgs.push_back("-E");
+
+  if (Args.hasArg(options::OPT_traditional) ||
+      Args.hasArg(options::OPT_traditional_cpp))
+    CmdArgs.push_back("-traditional-cpp");
+
+  ArgStringList OutputArgs;
+  if (Output.isFilename()) {
+    OutputArgs.push_back("-o");
+    OutputArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isPipe() && "Unexpected CC1 output.");
+  }
+
+  if (Args.hasArg(options::OPT_E)) {
+    AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+  } else {
+    AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+    CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_d_Group);
+
+  const char *CC1Name = getCC1Name(Inputs[0].getType());
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
+                                   Job &Dest, const InputInfo &Output,
+                                   const InputInfoList &Inputs,
+                                   const ArgList &Args,
+                                   const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  assert(Inputs.size() == 1 && "Unexpected number of inputs!");
+
+  types::ID InputType = Inputs[0].getType();
+  const Arg *A;
+  if ((A = Args.getLastArg(options::OPT_traditional)))
+    D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+      << A->getAsString(Args) << "-E";
+
+  if (Output.getType() == types::TY_LLVMAsm)
+    CmdArgs.push_back("-emit-llvm");
+  else if (Output.getType() == types::TY_LLVMBC)
+    CmdArgs.push_back("-emit-llvm-bc");
+  else if (Output.getType() == types::TY_AST)
+    D.Diag(clang::diag::err_drv_no_ast_support)
+      << getToolChain().getTripleString();
+
+  ArgStringList OutputArgs;
+  if (Output.getType() != types::TY_PCH) {
+    OutputArgs.push_back("-o");
+    if (Output.isPipe())
+      OutputArgs.push_back("-");
+    else if (Output.isNothing())
+      OutputArgs.push_back("/dev/null");
+    else
+      OutputArgs.push_back(Output.getFilename());
+  }
+
+  // There is no need for this level of compatibility, but it makes
+  // diffing easier.
+  bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) ||
+                          Args.hasArg(options::OPT_S));
+
+  if (types::getPreprocessedType(InputType) != types::TY_INVALID) {
+    AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs);
+    if (OutputArgsEarly) {
+      AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+    } else {
+      AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+      CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+    }
+  } else {
+    CmdArgs.push_back("-fpreprocessed");
+
+    for (InputInfoList::const_iterator
+           it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+      const InputInfo &II = *it;
+
+      // Reject AST inputs.
+      if (II.getType() == types::TY_AST) {
+        D.Diag(clang::diag::err_drv_no_ast_support)
+          << getToolChain().getTripleString();
+        return;
+      }
+
+      if (II.isPipe())
+        CmdArgs.push_back("-");
+      else
+        CmdArgs.push_back(II.getFilename());
+    }
+
+    if (OutputArgsEarly) {
+      AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
+    } else {
+      AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList());
+      CmdArgs.append(OutputArgs.begin(), OutputArgs.end());
+    }
+  }
+
+  if (Output.getType() == types::TY_PCH) {
+    assert(Output.isFilename() && "Invalid PCH output.");
+
+    CmdArgs.push_back("-o");
+    // NOTE: gcc uses a temp .s file for this, but there doesn't seem
+    // to be a good reason.
+    CmdArgs.push_back("/dev/null");
+
+    CmdArgs.push_back("--output-pch=");
+    CmdArgs.push_back(Output.getFilename());
+  }
+
+  const char *CC1Name = getCC1Name(Inputs[0].getType());
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                    Job &Dest, const InputInfo &Output,
+                                    const InputInfoList &Inputs,
+                                    const ArgList &Args,
+                                    const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+  const InputInfo &Input = Inputs[0];
+
+  // Bit of a hack, this is only used for original inputs.
+  //
+  // FIXME: This is broken for preprocessed .s inputs.
+  if (Input.isFilename() &&
+      strcmp(Input.getFilename(), Input.getBaseInput()) == 0) {
+    if (Args.hasArg(options::OPT_gstabs))
+      CmdArgs.push_back("--gstabs");
+    else if (Args.hasArg(options::OPT_g_Group))
+      CmdArgs.push_back("--gdwarf2");
+  }
+
+  // Derived from asm spec.
+  AddDarwinArch(Args, CmdArgs);
+
+  if (!getDarwinToolChain().isTargetIPhoneOS() ||
+      Args.hasArg(options::OPT_force__cpusubtype__ALL))
+    CmdArgs.push_back("-force_cpusubtype_ALL");
+
+  if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
+      (Args.hasArg(options::OPT_mkernel) ||
+       Args.hasArg(options::OPT_static) ||
+       Args.hasArg(options::OPT_fapple_kext)))
+    CmdArgs.push_back("-static");
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  assert(Output.isFilename() && "Unexpected lipo output.");
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  if (Input.isPipe()) {
+    CmdArgs.push_back("-");
+  } else {
+    assert(Input.isFilename() && "Invalid input.");
+    CmdArgs.push_back(Input.getFilename());
+  }
+
+  // asm_final spec is empty.
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+/// 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.
+static bool isSourceSuffix(const char *Str) {
+  // match: 'C', 'CPP', 'c', 'cc', 'cp', 'c++', 'cpp', 'cxx', 'm',
+  // 'mm'.
+  return llvm::StringSwitch<bool>(Str)
+           .Case("C", true)
+           .Case("c", true)
+           .Case("m", true)
+           .Case("cc", true)
+           .Case("cp", true)
+           .Case("mm", true)
+           .Case("CPP", true)
+           .Case("c++", true)
+           .Case("cpp", true)
+           .Case("cxx", true)
+           .Default(false);
+}
+
+void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
+                                       ArgStringList &CmdArgs) const {
+  llvm::StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);
+
+  // Derived from darwin_arch spec.
+  CmdArgs.push_back("-arch");
+  CmdArgs.push_back(Args.MakeArgString(ArchName));
+
+  // FIXME: Is this needed anymore?
+  if (ArchName == "arm")
+    CmdArgs.push_back("-force_cpusubtype_ALL");
+}
+
+void darwin::Link::AddLinkArgs(const ArgList &Args,
+                               ArgStringList &CmdArgs) const {
+  const Driver &D = getToolChain().getDriver();
+
+  // Derived from the "link" spec.
+  Args.AddAllArgs(CmdArgs, options::OPT_static);
+  if (!Args.hasArg(options::OPT_static))
+    CmdArgs.push_back("-dynamic");
+  if (Args.hasArg(options::OPT_fgnu_runtime)) {
+    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
+    // here. How do we wish to handle such things?
+  }
+
+  if (!Args.hasArg(options::OPT_dynamiclib)) {
+    AddDarwinArch(Args, CmdArgs);
+    // FIXME: Why do this only on this path?
+    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
+
+    Args.AddLastArg(CmdArgs, options::OPT_bundle);
+    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
+    Args.AddAllArgs(CmdArgs, options::OPT_client__name);
+
+    Arg *A;
+    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
+        (A = Args.getLastArg(options::OPT_current__version)) ||
+        (A = Args.getLastArg(options::OPT_install__name)))
+      D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+        << A->getAsString(Args) << "-dynamiclib";
+
+    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
+    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
+    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
+  } else {
+    CmdArgs.push_back("-dylib");
+
+    Arg *A;
+    if ((A = Args.getLastArg(options::OPT_bundle)) ||
+        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
+        (A = Args.getLastArg(options::OPT_client__name)) ||
+        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
+        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
+        (A = Args.getLastArg(options::OPT_private__bundle)))
+      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+        << A->getAsString(Args) << "-dynamiclib";
+
+    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
+                              "-dylib_compatibility_version");
+    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
+                              "-dylib_current_version");
+
+    AddDarwinArch(Args, CmdArgs);
+
+    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
+                              "-dylib_install_name");
+  }
+
+  Args.AddLastArg(CmdArgs, options::OPT_all__load);
+  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
+  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
+  if (getDarwinToolChain().isTargetIPhoneOS())
+    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
+  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
+  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
+  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
+  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
+  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
+  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
+  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
+  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
+  Args.AddAllArgs(CmdArgs, options::OPT_init);
+
+  // Adding all arguments doesn't make sense here but this is what gcc does. One
+  // of this should always be present thanks to argument translation.
+  assert((Args.hasArg(options::OPT_mmacosx_version_min_EQ) ||
+          Args.hasArg(options::OPT_miphoneos_version_min_EQ)) &&
+         "Missing version argument (lost in translation)?");
+  Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
+                            "-macosx_version_min");
+  Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
+                            "-iphoneos_version_min");
+  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
+  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
+  Args.AddLastArg(CmdArgs, options::OPT_single__module);
+  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
+  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
+
+  if (Args.hasArg(options::OPT_fpie))
+    CmdArgs.push_back("-pie");
+
+  Args.AddLastArg(CmdArgs, options::OPT_prebind);
+  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
+  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
+  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
+  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
+  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
+  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
+  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
+  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
+  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
+  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
+  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
+  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
+  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
+  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
+  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
+
+  Args.AddAllArgsTranslated(CmdArgs, options::OPT_isysroot, "-syslibroot");
+  if (getDarwinToolChain().isTargetIPhoneOS()) {
+    if (!Args.hasArg(options::OPT_isysroot)) {
+      CmdArgs.push_back("-syslibroot");
+      CmdArgs.push_back("/Developer/SDKs/Extra");
+    }
+  }
+
+  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
+  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
+  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
+  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
+  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
+  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
+  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
+  Args.AddAllArgs(CmdArgs, options::OPT_y);
+  Args.AddLastArg(CmdArgs, options::OPT_w);
+  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
+  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
+  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
+  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
+  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
+  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
+  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
+  Args.AddLastArg(CmdArgs, options::OPT_whyload);
+  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
+  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
+  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
+  Args.AddLastArg(CmdArgs, options::OPT_Mach);
+}
+
+void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                Job &Dest, const InputInfo &Output,
+                                const InputInfoList &Inputs,
+                                const ArgList &Args,
+                                const char *LinkingOutput) const {
+  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
+
+  // The logic here is derived from gcc's behavior; most of which
+  // comes from specs (starting with link_command). Consult gcc for
+  // more information.
+  ArgStringList CmdArgs;
+
+  // I'm not sure why this particular decomposition exists in gcc, but
+  // we follow suite for ease of comparison.
+  AddLinkArgs(Args, CmdArgs);
+
+  Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
+  Args.AddAllArgs(CmdArgs, options::OPT_s);
+  Args.AddAllArgs(CmdArgs, options::OPT_t);
+  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_A);
+  Args.AddLastArg(CmdArgs, options::OPT_e);
+  Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
+  Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  if (!Args.hasArg(options::OPT_A) &&
+      !Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    // Derived from startfile spec.
+    if (Args.hasArg(options::OPT_dynamiclib)) {
+      // Derived from darwin_dylib1 spec.
+      if (getDarwinToolChain().isTargetIPhoneOS()) {
+        if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+          CmdArgs.push_back("-ldylib1.o");
+      } else {
+        if (getDarwinToolChain().isMacosxVersionLT(10, 5))
+          CmdArgs.push_back("-ldylib1.o");
+        else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+          CmdArgs.push_back("-ldylib1.10.5.o");
+      }
+    } else {
+      if (Args.hasArg(options::OPT_bundle)) {
+        if (!Args.hasArg(options::OPT_static)) {
+          // Derived from darwin_bundle1 spec.
+          if (getDarwinToolChain().isTargetIPhoneOS()) {
+            if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+              CmdArgs.push_back("-lbundle1.o");
+          } else {
+            if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+              CmdArgs.push_back("-lbundle1.o");
+          }
+        }
+      } else {
+        if (Args.hasArg(options::OPT_pg)) {
+          if (Args.hasArg(options::OPT_static) ||
+              Args.hasArg(options::OPT_object) ||
+              Args.hasArg(options::OPT_preload)) {
+            CmdArgs.push_back("-lgcrt0.o");
+          } else {
+            CmdArgs.push_back("-lgcrt1.o");
+
+            // darwin_crt2 spec is empty.
+          }
+        } else {
+          if (Args.hasArg(options::OPT_static) ||
+              Args.hasArg(options::OPT_object) ||
+              Args.hasArg(options::OPT_preload)) {
+            CmdArgs.push_back("-lcrt0.o");
+          } else {
+            // Derived from darwin_crt1 spec.
+            if (getDarwinToolChain().isTargetIPhoneOS()) {
+              if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
+                CmdArgs.push_back("-lcrt1.o");
+              else
+                CmdArgs.push_back("-lcrt1.3.1.o");
+            } else {
+              if (getDarwinToolChain().isMacosxVersionLT(10, 5))
+                CmdArgs.push_back("-lcrt1.o");
+              else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
+                CmdArgs.push_back("-lcrt1.10.5.o");
+              else
+                CmdArgs.push_back("-lcrt1.10.6.o");
+
+              // darwin_crt2 spec is empty.
+            }
+          }
+        }
+      }
+    }
+
+    if (!getDarwinToolChain().isTargetIPhoneOS() &&
+        Args.hasArg(options::OPT_shared_libgcc) &&
+        getDarwinToolChain().isMacosxVersionLT(10, 5)) {
+      const char *Str =
+        Args.MakeArgString(getToolChain().GetFilePath(C, "crt3.o"));
+      CmdArgs.push_back(Str);
+    }
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+
+  if (Args.hasArg(options::OPT_fopenmp))
+    // This is more complicated in gcc...
+    CmdArgs.push_back("-lgomp");
+
+  getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  if (LinkingOutput) {
+    CmdArgs.push_back("-arch_multiple");
+    CmdArgs.push_back("-final_output");
+    CmdArgs.push_back(LinkingOutput);
+  }
+
+  if (Args.hasArg(options::OPT_fprofile_arcs) ||
+      Args.hasArg(options::OPT_fprofile_generate) ||
+      Args.hasArg(options::OPT_fcreate_profile) ||
+      Args.hasArg(options::OPT_coverage))
+    CmdArgs.push_back("-lgcov");
+
+  if (Args.hasArg(options::OPT_fnested_functions))
+    CmdArgs.push_back("-allow_stack_execute");
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    // FIXME: g++ is more complicated here, it tries to put -lstdc++
+    // before -lm, for example.
+    if (getToolChain().getDriver().CCCIsCXX)
+      CmdArgs.push_back("-lstdc++");
+
+    // link_ssp spec is empty.
+
+    // Let the tool chain choose which runtime library to link.
+    getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
+  }
+
+  if (!Args.hasArg(options::OPT_A) &&
+      !Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    // endfile_spec is empty.
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_F);
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+  // Find the first non-empty base input (we want to ignore linker
+  // inputs).
+  const char *BaseInput = "";
+  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+    if (Inputs[i].getBaseInput()[0] != '\0') {
+      BaseInput = Inputs[i].getBaseInput();
+      break;
+    }
+  }
+
+  // Run dsymutil if we are making an executable in a single step.
+  //
+  // FIXME: Currently we don't want to do this when we are part of a
+  // universal build step, as this would end up creating stray temp
+  // files.
+  if (!LinkingOutput &&
+      Args.getLastArg(options::OPT_g_Group) &&
+      !Args.getLastArg(options::OPT_gstabs) &&
+      !Args.getLastArg(options::OPT_g0)) {
+    // FIXME: This is gross, but matches gcc. The test only considers
+    // the suffix (not the -x type), and then only of the first
+    // source input. Awesome.
+    const char *Suffix = strrchr(BaseInput, '.');
+    if (Suffix && isSourceSuffix(Suffix + 1)) {
+      const char *Exec =
+        Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil"));
+      ArgStringList CmdArgs;
+      CmdArgs.push_back(Output.getFilename());
+      C.getJobs().addCommand(new Command(JA, *this, Exec, CmdArgs));
+    }
+  }
+}
+
+void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
+                                Job &Dest, const InputInfo &Output,
+                                const InputInfoList &Inputs,
+                                const ArgList &Args,
+                                const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  CmdArgs.push_back("-create");
+  assert(Output.isFilename() && "Unexpected lipo output.");
+
+  CmdArgs.push_back("-output");
+  CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    assert(II.isFilename() && "Unexpected lipo input.");
+    CmdArgs.push_back(II.getFilename());
+  }
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                      Job &Dest, const InputInfo &Output,
+                                      const InputInfoList &Inputs,
+                                      const ArgList &Args,
+                                      const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  if (Output.isPipe())
+    CmdArgs.push_back("-");
+  else
+    CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else
+      CmdArgs.push_back(II.getFilename());
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "gas"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                  Job &Dest, const InputInfo &Output,
+                                  const InputInfoList &Inputs,
+                                  const ArgList &Args,
+                                  const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  if ((!Args.hasArg(options::OPT_nostdlib)) &&
+      (!Args.hasArg(options::OPT_shared))) {
+    CmdArgs.push_back("-e");
+    CmdArgs.push_back("_start");
+  }
+
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-Bstatic");
+    CmdArgs.push_back("-dn");
+  } else {
+//    CmdArgs.push_back("--eh-frame-hdr");
+    CmdArgs.push_back("-Bdynamic");
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-shared");
+    } else {
+      CmdArgs.push_back("--dynamic-linker");
+      CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
+    }
+  }
+
+  if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
+    } else {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+    }
+    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
+  }
+
+  CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
+                                       + getToolChain().getTripleString()
+                                       + "/4.2.4"));
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    // Don't try to pass LLVM inputs to a generic gcc.
+    if (II.getType() == types::TY_LLVMBC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+        << getToolChain().getTripleString();
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    // FIXME: For some reason GCC passes -lgcc before adding
+    // the default system libraries. Just mimic this for now.
+    CmdArgs.push_back("-lgcc");
+
+    if (Args.hasArg(options::OPT_pthread))
+      CmdArgs.push_back("-pthread");
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back("-lc");
+    CmdArgs.push_back("-lgcc");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
+//    else
+//      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                     Job &Dest, const InputInfo &Output,
+                                     const InputInfoList &Inputs,
+                                     const ArgList &Args,
+                                     const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  if (Output.isPipe())
+    CmdArgs.push_back("-");
+  else
+    CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else
+      CmdArgs.push_back(II.getFilename());
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                 Job &Dest, const InputInfo &Output,
+                                 const InputInfoList &Inputs,
+                                 const ArgList &Args,
+                                 const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  if ((!Args.hasArg(options::OPT_nostdlib)) &&
+      (!Args.hasArg(options::OPT_shared))) {
+    CmdArgs.push_back("-e");
+    CmdArgs.push_back("__start");
+  }
+
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-Bstatic");
+  } else {
+    CmdArgs.push_back("--eh-frame-hdr");
+    CmdArgs.push_back("-Bdynamic");
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-shared");
+    } else {
+      CmdArgs.push_back("-dynamic-linker");
+      CmdArgs.push_back("/usr/libexec/ld.so");
+    }
+  }
+
+  if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
+    } else {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
+    }
+  }
+
+  std::string Triple = getToolChain().getTripleString();
+  if (Triple.substr(0, 6) == "x86_64")
+    Triple.replace(0, 6, "amd64");
+  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
+                                       "/3.3.5"));
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    // Don't try to pass LLVM inputs to a generic gcc.
+    if (II.getType() == types::TY_LLVMBC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+        << getToolChain().getTripleString();
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    // FIXME: For some reason GCC passes -lgcc before adding
+    // the default system libraries. Just mimic this for now.
+    CmdArgs.push_back("-lgcc");
+
+    if (Args.hasArg(options::OPT_pthread))
+      CmdArgs.push_back("-pthread");
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back("-lc");
+    CmdArgs.push_back("-lgcc");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
+    else
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                     Job &Dest, const InputInfo &Output,
+                                     const InputInfoList &Inputs,
+                                     const ArgList &Args,
+                                     const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
+  // instruct as in the base system to assemble 32-bit code.
+  if (getToolChain().getArchName() == "i386")
+    CmdArgs.push_back("--32");
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  if (Output.isPipe())
+    CmdArgs.push_back("-");
+  else
+    CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else
+      CmdArgs.push_back(II.getFilename());
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                 Job &Dest, const InputInfo &Output,
+                                 const InputInfoList &Inputs,
+                                 const ArgList &Args,
+                                 const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-Bstatic");
+  } else {
+    CmdArgs.push_back("--eh-frame-hdr");
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-Bshareable");
+    } else {
+      CmdArgs.push_back("-dynamic-linker");
+      CmdArgs.push_back("/libexec/ld-elf.so.1");
+    }
+  }
+
+  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
+  // instruct ld in the base system to link 32-bit code.
+  if (getToolChain().getArchName() == "i386") {
+    CmdArgs.push_back("-m");
+    CmdArgs.push_back("elf_i386_fbsd");
+  }
+
+  if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
+    } else {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
+    }
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    // Don't try to pass LLVM inputs to a generic gcc.
+    if (II.getType() == types::TY_LLVMBC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+        << getToolChain().getTripleString();
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+    // the default system libraries. Just mimic this for now.
+    CmdArgs.push_back("-lgcc");
+    if (D.CCCIsCXX)
+      CmdArgs.push_back("-lstdc++");
+    if (Args.hasArg(options::OPT_static)) {
+      CmdArgs.push_back("-lgcc_eh");
+    } else {
+      CmdArgs.push_back("--as-needed");
+      CmdArgs.push_back("-lgcc_s");
+      CmdArgs.push_back("--no-as-needed");
+    }
+
+    if (Args.hasArg(options::OPT_pthread))
+      CmdArgs.push_back("-lpthread");
+    CmdArgs.push_back("-lc");
+
+    CmdArgs.push_back("-lgcc");
+    if (Args.hasArg(options::OPT_static)) {
+      CmdArgs.push_back("-lgcc_eh");
+    } else {
+      CmdArgs.push_back("--as-needed");
+      CmdArgs.push_back("-lgcc_s");
+      CmdArgs.push_back("--no-as-needed");
+    }
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
+    else
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+/// DragonFly Tools
+
+// For now, DragonFly Assemble does just about the same as for
+// FreeBSD, but this may change soon.
+void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                       Job &Dest, const InputInfo &Output,
+                                       const InputInfoList &Inputs,
+                                       const ArgList &Args,
+                                       const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  // When building 32-bit code on DragonFly/pc64, we have to explicitly
+  // instruct as in the base system to assemble 32-bit code.
+  if (getToolChain().getArchName() == "i386")
+    CmdArgs.push_back("--32");
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  if (Output.isPipe())
+    CmdArgs.push_back("-");
+  else
+    CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else
+      CmdArgs.push_back(II.getFilename());
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                 Job &Dest, const InputInfo &Output,
+                                 const InputInfoList &Inputs,
+                                 const ArgList &Args,
+                                 const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-Bstatic");
+  } else {
+    if (Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back("-Bshareable");
+    else {
+      CmdArgs.push_back("-dynamic-linker");
+      CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
+    }
+  }
+
+  // When building 32-bit code on DragonFly/pc64, we have to explicitly
+  // instruct ld in the base system to link 32-bit code.
+  if (getToolChain().getArchName() == "i386") {
+    CmdArgs.push_back("-m");
+    CmdArgs.push_back("elf_i386");
+  }
+
+  if (Output.isPipe()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back("-");
+  } else if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
+    } else {
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
+    }
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+  Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+
+    // Don't try to pass LLVM inputs to a generic gcc.
+    if (II.getType() == types::TY_LLVMBC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+        << getToolChain().getTripleString();
+
+    if (II.isPipe())
+      CmdArgs.push_back("-");
+    else if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
+    //         rpaths
+    CmdArgs.push_back("-L/usr/lib/gcc41");
+
+    if (!Args.hasArg(options::OPT_static)) {
+      CmdArgs.push_back("-rpath");
+      CmdArgs.push_back("/usr/lib/gcc41");
+
+      CmdArgs.push_back("-rpath-link");
+      CmdArgs.push_back("/usr/lib/gcc41");
+
+      CmdArgs.push_back("-rpath");
+      CmdArgs.push_back("/usr/lib");
+
+      CmdArgs.push_back("-rpath-link");
+      CmdArgs.push_back("/usr/lib");
+    }
+
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-lgcc_pic");
+    } else {
+      CmdArgs.push_back("-lgcc");
+    }
+
+
+    if (Args.hasArg(options::OPT_pthread))
+      CmdArgs.push_back("-lpthread");
+
+    if (!Args.hasArg(options::OPT_nolibc)) {
+      CmdArgs.push_back("-lc");
+    }
+
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-lgcc_pic");
+    } else {
+      CmdArgs.push_back("-lgcc");
+    }
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nostartfiles)) {
+    if (!Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
+    else
+      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
+  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
new file mode 100644
index 0000000..db59641
--- /dev/null
+++ b/lib/Driver/Tools.h
@@ -0,0 +1,396 @@
+//===--- Tools.h - Tool Implementations -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_DRIVER_TOOLS_H_
+#define CLANG_LIB_DRIVER_TOOLS_H_
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace driver {
+  class Driver;
+
+namespace toolchains {
+  class Darwin;
+}
+
+namespace tools {
+
+  class VISIBILITY_HIDDEN Clang : public Tool {
+    void AddPreprocessingOptions(const Driver &D,
+                                 const ArgList &Args,
+                                 ArgStringList &CmdArgs,
+                                 const InputInfo &Output,
+                                 const InputInfoList &Inputs) const;
+
+    void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+    void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+  public:
+    Clang(const ToolChain &TC) : Tool("clang", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedAssembler() const { return true; }
+    virtual bool hasIntegratedCPP() const { return true; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+
+  /// gcc - Generic GCC tool implementations.
+namespace gcc {
+  class VISIBILITY_HIDDEN Common : public Tool {
+  public:
+    Common(const char *Name, const ToolChain &TC) : Tool(Name, TC) {}
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+
+    /// RenderExtraToolArgs - Render any arguments necessary to force
+    /// the particular tool mode.
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const = 0;
+  };
+
+
+  class VISIBILITY_HIDDEN Preprocess : public Common {
+  public:
+    Preprocess(const ToolChain &TC) : Common("gcc::Preprocess", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const;
+  };
+
+  class VISIBILITY_HIDDEN Precompile : public Common  {
+  public:
+    Precompile(const ToolChain &TC) : Common("gcc::Precompile", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return true; }
+
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const;
+  };
+
+  class VISIBILITY_HIDDEN Compile : public Common  {
+  public:
+    Compile(const ToolChain &TC) : Common("gcc::Compile", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return true; }
+
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const;
+  };
+
+  class VISIBILITY_HIDDEN Assemble : public Common  {
+  public:
+    Assemble(const ToolChain &TC) : Common("gcc::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const;
+  };
+
+  class VISIBILITY_HIDDEN Link : public Common  {
+  public:
+    Link(const ToolChain &TC) : Common("gcc::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return false; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void RenderExtraToolArgs(const JobAction &JA,
+                                     ArgStringList &CmdArgs) const;
+  };
+} // end namespace gcc
+
+namespace darwin {
+  class VISIBILITY_HIDDEN DarwinTool : public Tool {
+  protected:
+    void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+    const toolchains::Darwin &getDarwinToolChain() const {
+      return reinterpret_cast<const toolchains::Darwin&>(getToolChain());
+    }
+
+  public:
+    DarwinTool(const char *Name, const ToolChain &TC) : Tool(Name, TC) {}
+  };
+
+  class VISIBILITY_HIDDEN CC1 : public DarwinTool  {
+  public:
+    static const char *getBaseInputName(const ArgList &Args,
+                                 const InputInfoList &Input);
+    static const char *getBaseInputStem(const ArgList &Args,
+                                 const InputInfoList &Input);
+    static const char *getDependencyFileName(const ArgList &Args,
+                                             const InputInfoList &Inputs);
+
+  protected:
+    const char *getCC1Name(types::ID Type) const;
+
+    void AddCC1Args(const ArgList &Args, ArgStringList &CmdArgs) const;
+    void AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+                           const InputInfoList &Inputs,
+                           const ArgStringList &OutputArgs) const;
+    void AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
+                           const InputInfoList &Inputs,
+                           const ArgStringList &OutputArgs) const;
+    void AddCPPUniqueOptionsArgs(const ArgList &Args,
+                                 ArgStringList &CmdArgs,
+                                 const InputInfoList &Inputs) const;
+    void AddCPPArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+  public:
+    CC1(const char *Name, const ToolChain &TC) : DarwinTool(Name, TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return true; }
+  };
+
+  class VISIBILITY_HIDDEN Preprocess : public CC1  {
+  public:
+    Preprocess(const ToolChain &TC) : CC1("darwin::Preprocess", TC) {}
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+
+  class VISIBILITY_HIDDEN Compile : public CC1  {
+  public:
+    Compile(const ToolChain &TC) : CC1("darwin::Compile", TC) {}
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+
+  class VISIBILITY_HIDDEN Assemble : public DarwinTool  {
+  public:
+    Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+
+  class VISIBILITY_HIDDEN Link : public DarwinTool  {
+    void AddLinkArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+  public:
+    Link(const ToolChain &TC) : DarwinTool("darwin::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return false; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+
+  class VISIBILITY_HIDDEN Lipo : public DarwinTool  {
+  public:
+    Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", TC) {}
+
+    virtual bool acceptsPipedInput() const { return false; }
+    virtual bool canPipeOutput() const { return false; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+}
+
+  /// openbsd -- Directly call GNU Binutils assembler and linker
+namespace openbsd {
+  class VISIBILITY_HIDDEN Assemble : public Tool  {
+  public:
+    Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+  class VISIBILITY_HIDDEN Link : public Tool  {
+  public:
+    Link(const ToolChain &TC) : Tool("openbsd::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+} // end namespace openbsd
+
+  /// freebsd -- Directly call GNU Binutils assembler and linker
+namespace freebsd {
+  class VISIBILITY_HIDDEN Assemble : public Tool  {
+  public:
+    Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+  class VISIBILITY_HIDDEN Link : public Tool  {
+  public:
+    Link(const ToolChain &TC) : Tool("freebsd::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+} // end namespace freebsd
+
+  /// auroraux -- Directly call GNU Binutils assembler and linker
+namespace auroraux {
+  class VISIBILITY_HIDDEN Assemble : public Tool  {
+  public:
+    Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+  class VISIBILITY_HIDDEN Link : public Tool  {
+  public:
+    Link(const ToolChain &TC) : Tool("auroraux::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+} // end namespace auroraux
+
+  /// dragonfly -- Directly call GNU Binutils assembler and linker
+namespace dragonfly {
+  class VISIBILITY_HIDDEN Assemble : public Tool  {
+  public:
+    Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+  class VISIBILITY_HIDDEN Link : public Tool  {
+  public:
+    Link(const ToolChain &TC) : Tool("dragonfly::Link", TC) {}
+
+    virtual bool acceptsPipedInput() const { return true; }
+    virtual bool canPipeOutput() const { return true; }
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              Job &Dest,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+} // end namespace dragonfly
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // CLANG_LIB_DRIVER_TOOLS_H_
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
new file mode 100644
index 0000000..60d86a6
--- /dev/null
+++ b/lib/Driver/Types.cpp
@@ -0,0 +1,215 @@
+//===--- Types.cpp - Driver input & temporary type information ----------*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Types.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include <string.h>
+#include <cassert>
+
+using namespace clang::driver;
+using namespace clang::driver::types;
+
+struct TypeInfo {
+  const char *Name;
+  const char *Flags;
+  const char *TempSuffix;
+  ID PreprocessedType;
+};
+
+static const TypeInfo TypeInfos[] = {
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \
+  { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, },
+#include "clang/Driver/Types.def"
+#undef TYPE
+};
+static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]);
+
+static const TypeInfo &getInfo(unsigned id) {
+  assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
+  return TypeInfos[id - 1];
+}
+
+const char *types::getTypeName(ID Id) {
+  return getInfo(Id).Name;
+}
+
+types::ID types::getPreprocessedType(ID Id) {
+  return getInfo(Id).PreprocessedType;
+}
+
+const char *types::getTypeTempSuffix(ID Id) {
+  return getInfo(Id).TempSuffix;
+}
+
+bool types::onlyAssembleType(ID Id) {
+  return strchr(getInfo(Id).Flags, 'a');
+}
+
+bool types::onlyPrecompileType(ID Id) {
+  return strchr(getInfo(Id).Flags, 'p');
+}
+
+bool types::canTypeBeUserSpecified(ID Id) {
+  return strchr(getInfo(Id).Flags, 'u');
+}
+
+bool types::appendSuffixForType(ID Id) {
+  return strchr(getInfo(Id).Flags, 'A');
+}
+
+bool types::canLipoType(ID Id) {
+  return (Id == TY_Nothing ||
+          Id == TY_Image ||
+          Id == TY_Object);
+}
+
+bool types::isAcceptedByClang(ID Id) {
+  switch (Id) {
+  default:
+    return false;
+
+  case TY_Asm:
+  case TY_C: case TY_PP_C:
+  case TY_CL:
+  case TY_ObjC: case TY_PP_ObjC:
+  case TY_CXX: case TY_PP_CXX:
+  case TY_ObjCXX: case TY_PP_ObjCXX:
+  case TY_CHeader: case TY_PP_CHeader:
+  case TY_ObjCHeader: case TY_PP_ObjCHeader:
+  case TY_CXXHeader: case TY_PP_CXXHeader:
+  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+  case TY_AST:
+    return true;
+  }
+}
+
+bool types::isObjC(ID Id) {
+  switch (Id) {
+  default:
+    return false;
+
+  case TY_ObjC: case TY_PP_ObjC:
+  case TY_ObjCXX: case TY_PP_ObjCXX:
+  case TY_ObjCHeader: case TY_PP_ObjCHeader:
+  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+    return true;
+  }
+}
+
+bool types::isCXX(ID Id) {
+  switch (Id) {
+  default:
+    return false;
+
+  case TY_CXX: case TY_PP_CXX:
+  case TY_ObjCXX: case TY_PP_ObjCXX:
+  case TY_CXXHeader: case TY_PP_CXXHeader:
+  case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+    return true;
+  }
+}
+
+types::ID types::lookupTypeForExtension(const char *Ext) {
+  return llvm::StringSwitch<types::ID>(Ext)
+           .Case("c", TY_C)
+           .Case("i", TY_PP_C)
+           .Case("m", TY_ObjC)
+           .Case("M", TY_ObjCXX)
+           .Case("h", TY_CHeader)
+           .Case("C", TY_CXX)
+           .Case("H", TY_CXXHeader)
+           .Case("f", TY_PP_Fortran)
+           .Case("F", TY_Fortran)
+           .Case("s", TY_PP_Asm)
+           .Case("S", TY_Asm)
+           .Case("ii", TY_PP_CXX)
+           .Case("mi", TY_PP_ObjC)
+           .Case("mm", TY_ObjCXX)
+           .Case("cc", TY_CXX)
+           .Case("CC", TY_CXX)
+           .Case("cl", TY_CL)
+           .Case("cp", TY_CXX)
+           .Case("hh", TY_CXXHeader)
+           .Case("hpp", TY_CXXHeader)
+           .Case("ads", TY_Ada)
+           .Case("adb", TY_Ada)
+           .Case("ast", TY_AST)
+           .Case("cxx", TY_CXX)
+           .Case("cpp", TY_CXX)
+           .Case("CPP", TY_CXX)
+           .Case("CXX", TY_CXX)
+           .Case("for", TY_PP_Fortran)
+           .Case("FOR", TY_PP_Fortran)
+           .Case("fpp", TY_Fortran)
+           .Case("FPP", TY_Fortran)
+           .Case("f90", TY_PP_Fortran)
+           .Case("f95", TY_PP_Fortran)
+           .Case("F90", TY_Fortran)
+           .Case("F95", TY_Fortran)
+           .Case("mii", TY_PP_ObjCXX)
+           .Default(TY_INVALID);
+}
+
+types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
+  unsigned N = strlen(Name);
+
+  for (unsigned i=0; i<numTypes; ++i) {
+    types::ID Id = (types::ID) (i + 1);
+    if (canTypeBeUserSpecified(Id) &&
+        memcmp(Name, getInfo(Id).Name, N + 1) == 0)
+      return Id;
+  }
+
+  return TY_INVALID;
+}
+
+// FIXME: Why don't we just put this list in the defs file, eh.
+
+unsigned types::getNumCompilationPhases(ID Id) {
+  if (Id == TY_Object)
+    return 1;
+
+  unsigned N = 0;
+  if (getPreprocessedType(Id) != TY_INVALID)
+    N += 1;
+
+  if (onlyAssembleType(Id))
+    return N + 2; // assemble, link
+  if (onlyPrecompileType(Id))
+    return N + 1; // precompile
+
+  return N + 3; // compile, assemble, link
+}
+
+phases::ID types::getCompilationPhase(ID Id, unsigned N) {
+  assert(N < getNumCompilationPhases(Id) && "Invalid index.");
+
+  if (Id == TY_Object)
+    return phases::Link;
+
+  if (getPreprocessedType(Id) != TY_INVALID) {
+    if (N == 0)
+      return phases::Preprocess;
+    --N;
+  }
+
+  if (onlyAssembleType(Id))
+    return N == 0 ? phases::Assemble : phases::Link;
+
+  if (onlyPrecompileType(Id))
+    return phases::Precompile;
+
+  if (N == 0)
+    return phases::Compile;
+  if (N == 1)
+    return phases::Assemble;
+
+  return phases::Link;
+}