From 36c49e3f258dced101949edabd72e9bc3f1dedc4 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Fri, 17 Sep 2010 15:54:40 +0000
Subject: Vendor import of clang r114020 (from the release_28 branch):
 http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020

Approved by:	rpaulo (mentor)
---
 lib/Driver/Compilation.cpp |  12 --
 lib/Driver/Driver.cpp      | 126 +++++-------
 lib/Driver/HostInfo.cpp    | 177 ++++++++--------
 lib/Driver/InputInfo.h     |  15 +-
 lib/Driver/Job.cpp         |  12 +-
 lib/Driver/Makefile        |   1 -
 lib/Driver/OptTable.cpp    |   2 +
 lib/Driver/Option.cpp      |   2 +-
 lib/Driver/ToolChain.cpp   | 140 +++++++++++++
 lib/Driver/ToolChains.cpp  | 265 ++++++++++++++++++++----
 lib/Driver/ToolChains.h    |  50 +++--
 lib/Driver/Tools.cpp       | 500 +++++++++++++++++++++------------------------
 lib/Driver/Tools.h         |  95 +++------
 13 files changed, 822 insertions(+), 575 deletions(-)

(limited to 'lib/Driver')

diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 282e9fe..c059afd 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -83,10 +83,6 @@ void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
       OS << '"';
     }
     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
@@ -190,14 +186,6 @@ 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
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 2fc0a53..82f9134 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -25,6 +25,7 @@
 
 #include "clang/Basic/Version.h"
 
+#include "llvm/Config/config.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/PrettyStackTrace.h"
@@ -39,13 +40,13 @@
 using namespace clang::driver;
 using namespace clang;
 
-Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
+Driver::Driver(llvm::StringRef _ClangExecutable,
                llvm::StringRef _DefaultHostTriple,
                llvm::StringRef _DefaultImageName,
                bool IsProduction, bool CXXIsProduction,
                Diagnostic &_Diags)
   : Opts(createDriverOptTable()), Diags(_Diags),
-    Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
+    ClangExecutable(_ClangExecutable), DefaultHostTriple(_DefaultHostTriple),
     DefaultImageName(_DefaultImageName),
     DriverTitle("clang \"gcc-compatible\" driver"),
     Host(0),
@@ -68,6 +69,10 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
       CCCUseClangCXX = false;
   }
 
+  llvm::sys::Path Executable(ClangExecutable);
+  Name = Executable.getBasename();
+  Dir = Executable.getDirname();
+
   // Compute the path to the resource directory.
   llvm::sys::Path P(Dir);
   P.eraseComponent(); // Remove /bin from foo/bin
@@ -75,11 +80,6 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
   P.appendComponent("clang");
   P.appendComponent(CLANG_VERSION_STRING);
   ResourceDir = P.str();
-
-  // Save the original clang executable path.
-  P = Dir;
-  P.appendComponent(Name);
-  ClangExecutable = P.str();
 }
 
 Driver::~Driver() {
@@ -160,6 +160,16 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
     DAL->append(*it);
   }
 
+  // Add a default value of -mlinker-version=, if one was given and the user
+  // didn't specify one.
+#if defined(HOST_LINK_VERSION)
+  if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+    DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
+                      HOST_LINK_VERSION);
+    DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
+  }
+#endif
+
   return DAL;
 }
 
@@ -176,13 +186,15 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
   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);
 
+  // Ignore -pipe.
+  Args->ClaimAllArgs(options::OPT_pipe);
+
   // Extract -ccc args.
   //
   // FIXME: We need to figure out where this behavior should live. Most of it
@@ -223,14 +235,16 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
       Cur = Split.second;
     }
   }
+  // FIXME: We shouldn't overwrite the default host triple here, but we have
+  // nowhere else to put this currently.
   if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple))
-    HostTriple = A->getValue(*Args);
+    DefaultHostTriple = A->getValue(*Args);
   if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
-    Dir = A->getValue(*Args);
+    Dir = InstalledDir = A->getValue(*Args);
   if (const Arg *A = Args->getLastArg(options::OPT_B))
     PrefixDir = A->getValue(*Args);
 
-  Host = GetHostInfo(HostTriple);
+  Host = GetHostInfo(DefaultHostTriple.c_str());
 
   // Perform the default argument translations.
   DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
@@ -248,14 +262,12 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
   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).
+  // Construct the list of abstract actions to perform for this compilation.
   if (Host->useDriverDriver())
-    BuildUniversalActions(C->getArgs(), C->getActions());
+    BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
+                          C->getActions());
   else
-    BuildActions(C->getArgs(), C->getActions());
+    BuildActions(C->getDefaultToolChain(), C->getArgs(), C->getActions());
 
   if (CCCPrintActions) {
     PrintActions(*C);
@@ -525,7 +537,8 @@ static bool ContainsCompileAction(const Action *A) {
   return false;
 }
 
-void Driver::BuildUniversalActions(const ArgList &Args,
+void Driver::BuildUniversalActions(const ToolChain &TC,
+                                   const ArgList &Args,
                                    ActionList &Actions) const {
   llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
   // Collect the list of architectures. Duplicates are allowed, but should only
@@ -570,7 +583,7 @@ void Driver::BuildUniversalActions(const ArgList &Args,
   }
 
   ActionList SingleActions;
-  BuildActions(Args, SingleActions);
+  BuildActions(TC, Args, SingleActions);
 
   // Add in arch bindings for every top level action, as well as lipo and
   // dsymutil steps if needed.
@@ -620,7 +633,8 @@ void Driver::BuildUniversalActions(const ArgList &Args,
   }
 }
 
-void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
+void Driver::BuildActions(const ToolChain &TC, const ArgList &Args,
+                          ActionList &Actions) const {
   llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
   // Start by constructing the list of inputs and their types.
 
@@ -660,7 +674,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
           // 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);
+            Ty = TC.LookupTypeForExtension(Ext + 1);
 
           if (Ty == types::TY_INVALID)
             Ty = types::TY_Object;
@@ -885,16 +899,6 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
 
 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);
 
@@ -934,7 +938,6 @@ void Driver::BuildJobs(Compilation &C) const {
     InputInfo II;
     BuildJobsForAction(C, A, &C.getDefaultToolChain(),
                        /*BoundArch*/0,
-                       /*CanAcceptPipe*/ true,
                        /*AtTopLevel*/ true,
                        /*LinkingOutput*/ LinkingOutput,
                        II);
@@ -1032,17 +1035,11 @@ 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?
@@ -1064,7 +1061,7 @@ void Driver::BuildJobsForAction(Compilation &C,
       TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName());
 
     BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
-                       CanAcceptPipe, AtTopLevel, LinkingOutput, Result);
+                       AtTopLevel, LinkingOutput, Result);
     return;
   }
 
@@ -1074,7 +1071,6 @@ void Driver::BuildJobsForAction(Compilation &C,
   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) {
@@ -1087,33 +1083,11 @@ void Driver::BuildJobsForAction(Compilation &C,
       SubJobAtTopLevel = true;
 
     InputInfo II;
-    BuildJobsForAction(C, *it, TC, BoundArch, TryToUsePipeInput,
+    BuildJobsForAction(C, *it, TC, BoundArch,
                        SubJobAtTopLevel, 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();
 
@@ -1122,22 +1096,9 @@ void Driver::BuildJobsForAction(Compilation &C,
   if (JA->getType() == types::TY_dSYM)
     BaseInput = InputInfos[0].getFilename();
 
-  // Determine the place to write output to (nothing, pipe, or filename) and
-  // where to put the new job.
+  // Determine the place to write output to, if any.
   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);
@@ -1153,7 +1114,7 @@ void Driver::BuildJobsForAction(Compilation &C,
     }
     llvm::errs() << "], output: " << Result.getAsString() << "\n";
   } else {
-    T.ConstructJob(C, *JA, *Dest, Result, InputInfos,
+    T.ConstructJob(C, *JA, Result, InputInfos,
                    C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
   }
 }
@@ -1169,6 +1130,10 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
       return C.addResultFile(FinalOutput->getValue(C.getArgs()));
   }
 
+  // Default to writing to stdout?
+  if (AtTopLevel && isa<PreprocessJobAction>(JA))
+    return "-";
+
   // Output to a temporary file?
   if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) {
     std::string TmpName =
@@ -1307,6 +1272,11 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
     return createMinixHostInfo(*this, Triple);
   case llvm::Triple::Linux:
     return createLinuxHostInfo(*this, Triple);
+  case llvm::Triple::Win32:
+    return createWindowsHostInfo(*this, Triple);
+  case llvm::Triple::MinGW32:
+  case llvm::Triple::MinGW64:
+    return createMinGWHostInfo(*this, Triple);
   default:
     return createUnknownHostInfo(*this, Triple);
   }
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 0636d9e..7c5e430 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -38,12 +38,6 @@ namespace {
 
 /// 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;
 
@@ -53,37 +47,12 @@ public:
 
   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() {
@@ -147,11 +116,10 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
     const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN");
     if (UseNewToolChain || 
         Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
-      TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion);
+      TC = new toolchains::DarwinClang(*this, TCTriple);
     } else 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);
+      TC = new toolchains::DarwinGCC(*this, TCTriple);
     } else
       TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
   }
@@ -170,15 +138,6 @@ public:
 
   virtual bool useDriverDriver() const;
 
-  virtual types::ID lookupTypeForExtension(const char *Ext) const {
-    types::ID Ty = types::lookupTypeForExtension(Ext);
-
-    if (Ty == types::TY_PP_Asm)
-      return types::TY_Asm;
-
-    return Ty;
-  }
-
   virtual ToolChain *CreateToolChain(const ArgList &Args, 
                                      const char *ArchName) const;
 };
@@ -212,10 +171,6 @@ public:
 
   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;
 };
@@ -279,10 +234,6 @@ public:
 
   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;
 };
@@ -330,10 +281,6 @@ public:
 
   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;
 };
@@ -379,10 +326,6 @@ public:
 
   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;
 };
@@ -399,19 +342,22 @@ bool FreeBSDHostInfo::useDriverDriver() const {
 
 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.
+  // Automatically handle some instances of -m32/-m64 we know about.
   std::string Arch = getArchName();
   ArchName = Arch.c_str();
-  if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
-    ArchName = "i386";
-    Lib32 = true;
+  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];
@@ -419,7 +365,7 @@ ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
     llvm::Triple TCTriple(getTriple());
     TCTriple.setArchName(ArchName);
 
-    TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
+    TC = new toolchains::FreeBSD(*this, TCTriple);
   }
 
   return TC;
@@ -439,10 +385,6 @@ public:
 
   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;
 };
@@ -491,10 +433,6 @@ public:
 
   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;
 };
@@ -540,10 +478,6 @@ public:
 
   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;
 };
@@ -591,8 +525,79 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
   return TC;
 }
 
+// Windows Host Info
+
+/// WindowsHostInfo - Host information to use on Microsoft Windows.
+class WindowsHostInfo : public HostInfo {
+  /// Cache of tool chains we have created.
+  mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+  WindowsHostInfo(const Driver &D, const llvm::Triple& Triple);
+  ~WindowsHostInfo();
+
+  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;
+};
+
+WindowsHostInfo::WindowsHostInfo(const Driver &D, const llvm::Triple& Triple)
+  : HostInfo(D, Triple) {
+}
+
+WindowsHostInfo::~WindowsHostInfo() {
+  for (llvm::StringMap<ToolChain*>::iterator
+         it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+    delete it->second;
+}
+
+bool WindowsHostInfo::useDriverDriver() const {
+  return false;
+}
+
+ToolChain *WindowsHostInfo::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";
+    }
+  }
+
+  ToolChain *&TC = ToolChains[ArchName];
+  if (!TC) {
+    llvm::Triple TCTriple(getTriple());
+    TCTriple.setArchName(ArchName);
+
+    TC = new toolchains::Windows(*this, TCTriple);
+  }
+
+  return TC;
 }
 
+// FIXME: This is a placeholder.
+class MinGWHostInfo : public UnknownHostInfo {
+public:
+  MinGWHostInfo(const Driver &D, const llvm::Triple& Triple);
+};
+
+MinGWHostInfo::MinGWHostInfo(const Driver &D, const llvm::Triple& Triple)
+  : UnknownHostInfo(D, Triple) {}
+
+} // end anon namespace
+
 const HostInfo *
 clang::driver::createAuroraUXHostInfo(const Driver &D,
                                       const llvm::Triple& Triple){
@@ -642,6 +647,18 @@ clang::driver::createTCEHostInfo(const Driver &D,
 }
 
 const HostInfo *
+clang::driver::createWindowsHostInfo(const Driver &D,
+                                     const llvm::Triple& Triple) {
+  return new WindowsHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createMinGWHostInfo(const Driver &D,
+                                   const llvm::Triple& Triple) {
+  return new MinGWHostInfo(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
index c657bef..2a2f4b9 100644
--- a/lib/Driver/InputInfo.h
+++ b/lib/Driver/InputInfo.h
@@ -17,7 +17,6 @@
 
 namespace clang {
 namespace driver {
-  class PipedJob;
 
 /// InputInfo - Wrapper for information about an input source.
 class InputInfo {
@@ -37,7 +36,6 @@ class InputInfo {
   union {
     const char *Filename;
     const Arg *InputArg;
-    PipedJob *Pipe;
   } Data;
   Class Kind;
   types::ID Type;
@@ -56,15 +54,10 @@ public:
     : 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; }
 
@@ -76,17 +69,11 @@ public:
     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())
+    if (isFilename())
       return std::string("\"") + getFilename() + '"';
     else if (isInputArg())
       return "(input arg)";
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bfeb41a..fa7d060 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -21,13 +21,6 @@ Command::Command(const Action &_Source, const Tool &_Creator,
 {
 }
 
-PipedJob::PipedJob() : Job(PipedJobClass) {}
-
-PipedJob::~PipedJob() {
-  for (iterator it = begin(), ie = end(); it != ie; ++it)
-    delete *it;
-}
-
 JobList::JobList() : Job(JobListClass) {}
 
 JobList::~JobList() {
@@ -36,9 +29,6 @@ JobList::~JobList() {
 }
 
 void Job::addCommand(Command *C) {
-  if (PipedJob *PJ = dyn_cast<PipedJob>(this))
-    PJ->addCommand(C);
-  else
-    cast<JobList>(this)->addJob(C);
+  cast<JobList>(this)->addJob(C);
 }
 
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
index 7bc340e..454ab86 100644
--- a/lib/Driver/Makefile
+++ b/lib/Driver/Makefile
@@ -9,6 +9,5 @@
 
 CLANG_LEVEL := ../..
 LIBRARYNAME := clangDriver
-BUILD_ARCHIVE = 1
 
 include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index 39530f2..3c36314 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -164,6 +164,8 @@ Option *OptTable::CreateOption(unsigned id) const {
     Opt->setLinkerInput(true);
   if (info.Flags & NoArgumentUnused)
     Opt->setNoArgumentUnused(true);
+  if (info.Flags & NoForward)
+    Opt->setNoForward(true);
   if (info.Flags & RenderAsInput)
     Opt->setNoOptAsInput(true);
   if (info.Flags & RenderJoined) {
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
index dd48af8..5396250 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -20,7 +20,7 @@ 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),
-    DriverOption(false), NoArgumentUnused(false) {
+    DriverOption(false), NoArgumentUnused(false), NoForward(false) {
 
   // Multi-level aliases are not supported, and alias options cannot
   // have groups. This just simplifies option tracking, it is not an
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 9fae67d..94c1c6b 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -10,8 +10,12 @@
 #include "clang/Driver/ToolChain.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/HostInfo.h"
+#include "clang/Driver/Options.h"
 
 using namespace clang::driver;
 
@@ -34,3 +38,139 @@ std::string ToolChain::GetFilePath(const char *Name) const {
 std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const {
   return Host.getDriver().GetProgramPath(Name, *this, WantFile);
 }
+
+types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
+  return types::lookupTypeForExtension(Ext);
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args,
+                                   const llvm::Triple &Triple) {
+  // 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);
+
+  llvm::StringRef MArch;
+  if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    // Otherwise, if we have -march= choose the base CPU for that arch.
+    MArch = A->getValue(Args);
+  } else {
+    // Otherwise, use the Arch from the triple.
+    MArch = Triple.getArchName();
+  }
+
+  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";
+
+  // If all else failed, 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 "";
+}
+
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const {
+  switch (getTriple().getArch()) {
+  default:
+    return getTripleString();
+
+  case llvm::Triple::arm:
+  case llvm::Triple::thumb: {
+    // FIXME: Factor into subclasses.
+    llvm::Triple Triple = 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, Triple));
+    bool ThumbDefault =
+      (Suffix == "v7" && 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();
+  }
+  }
+}
+
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const {
+  // 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))
+    getDriver().Diag(clang::diag::err_drv_clang_unsupported)
+      << A->getAsString(Args);
+
+  return ComputeLLVMTriple(Args);
+}
+
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a78d153..471c47d 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -18,7 +18,9 @@
 #include "clang/Driver/OptTable.h"
 #include "clang/Driver/Option.h"
 #include "clang/Driver/Options.h"
+#include "clang/Basic/Version.h"
 
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
@@ -31,13 +33,30 @@ 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])
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
   : ToolChain(Host, Triple), TargetInitialized(false)
 {
+  // Compute the initial Darwin version based on the host.
+  bool HadExtra;
+  std::string OSName = Triple.getOSName();
+  if (!Driver::GetReleaseVersion(&OSName[6],
+                                 DarwinVersion[0], DarwinVersion[1],
+                                 DarwinVersion[2], HadExtra))
+    getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
+
   llvm::raw_string_ostream(MacosxVersionMin)
-    << "10." << std::max(0, (int)_DarwinVersion[0] - 4) << '.'
-    << _DarwinVersion[1];
+    << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
+    << DarwinVersion[1];
+}
+
+types::ID Darwin::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;
 }
 
 // FIXME: Can we tablegen this?
@@ -103,14 +122,13 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
   }
 }
 
-DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
-                     const unsigned (&DarwinVersion)[3],
-                     const unsigned (&_GCCVersion)[3])
-  : Darwin(Host, Triple, DarwinVersion)
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
+  : Darwin(Host, Triple)
 {
-  GCCVersion[0] = _GCCVersion[0];
-  GCCVersion[1] = _GCCVersion[1];
-  GCCVersion[2] = _GCCVersion[2];
+  // We can only work with 4.2.1 currently.
+  GCCVersion[0] = 4;
+  GCCVersion[1] = 2;
+  GCCVersion[2] = 1;
 
   // Set up the tool chain paths to match gcc.
   ToolChainDir = "i686-apple-darwin";
@@ -174,7 +192,9 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
   Path += ToolChainDir;
   getProgramPaths().push_back(Path);
 
-  getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+  if (getDriver().getInstalledDir() != getDriver().Dir)
+    getProgramPaths().push_back(getDriver().Dir);
 }
 
 Darwin::~Darwin() {
@@ -184,6 +204,38 @@ Darwin::~Darwin() {
     delete it->second;
 }
 
+std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const {
+  llvm::Triple Triple(ComputeLLVMTriple(Args));
+
+  // If the target isn't initialized (e.g., an unknown Darwin platform, return
+  // the default triple).
+  if (!isTargetInitialized())
+    return Triple.getTriple();
+    
+  unsigned Version[3];
+  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 (!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();
+}
+
 Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
   Action::ActionClass Key;
   if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
@@ -245,7 +297,7 @@ void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
     CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
                                          "/x86_64"));
   }
-  
+
   CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
 
   Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir;
@@ -314,12 +366,13 @@ void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
   }
 }
 
-DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
-                         const unsigned (&DarwinVersion)[3])
-  : Darwin(Host, Triple, DarwinVersion)
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple)
+  : Darwin(Host, Triple)
 {
   // We expect 'as', 'ld', etc. to be adjacent to our install dir.
-  getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+  if (getDriver().getInstalledDir() != getDriver().Dir)
+    getProgramPaths().push_back(getDriver().Dir);
 }
 
 void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
@@ -350,6 +403,39 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
     break;
   }
   P.appendComponent("4.2.1");
+
+  // Determine the arch specific GCC subdirectory.
+  const char *ArchSpecificDir = 0;
+  switch (getTriple().getArch()) {
+  default:
+    break;
+  case llvm::Triple::arm:
+  case llvm::Triple::thumb: {
+    std::string Triple = ComputeLLVMTriple(Args);
+    llvm::StringRef TripleStr = Triple;
+    if (TripleStr.startswith("armv5") || TripleStr.startswith("thumbv5"))
+      ArchSpecificDir = "v5";
+    else if (TripleStr.startswith("armv6") || TripleStr.startswith("thumbv6"))
+      ArchSpecificDir = "v6";
+    else if (TripleStr.startswith("armv7") || TripleStr.startswith("thumbv7"))
+      ArchSpecificDir = "v7";
+    break;
+  }
+  case llvm::Triple::ppc64:
+    ArchSpecificDir = "ppc64";
+    break;
+  case llvm::Triple::x86_64:
+    ArchSpecificDir = "x86_64";
+    break;
+  }
+
+  if (ArchSpecificDir) {
+    P.appendComponent(ArchSpecificDir);
+    if (P.exists())
+      CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
+    P.eraseComponent();
+  }
+
   if (P.exists())
     CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
 }
@@ -415,18 +501,9 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
   }
 }
 
-DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
-                                      const char *BoundArch) const {
-  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
   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) {
@@ -462,17 +539,17 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
 
     if (OSXTarget) {
       const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
-      OSXVersion = DAL->MakeJoinedArg(0, O, OSXTarget);
-      DAL->append(OSXVersion);
+      OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
+      Args.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);
+      iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget);
+      Args.append(iPhoneVersion);
     } else {
       // Otherwise, assume we are targeting OS X.
       const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
-      OSXVersion = DAL->MakeJoinedArg(0, O, MacosxVersionMin);
-      DAL->append(OSXVersion);
+      OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
+      Args.append(OSXVersion);
     }
   }
 
@@ -495,6 +572,19 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
         << iPhoneVersion->getAsString(Args);
   }
   setTarget(iPhoneVersion, Major, Minor, Micro);
+}
+
+DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
+                                      const char *BoundArch) const {
+  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+  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.
 
   for (ArgList::const_iterator it = Args.begin(),
          ie = Args.end(); it != ie; ++it) {
@@ -673,6 +763,11 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
       llvm_unreachable("invalid Darwin arch");
   }
 
+  // Add an explicit version min argument for the deployment target. We do this
+  // after argument translation because -Xarch_ arguments may add a version min
+  // argument.
+  AddDeploymentTarget(*DAL);
+
   return DAL;
 }
 
@@ -709,13 +804,20 @@ bool Darwin::SupportsObjCGC() const {
   return !isTargetIPhoneOS();
 }
 
+std::string
+Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const {
+  return ComputeLLVMTriple(Args);
+}
+
 /// 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);
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+  if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+    getProgramPaths().push_back(getDriver().Dir);
 }
 
 Generic_GCC::~Generic_GCC() {
@@ -864,8 +966,16 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
 
 /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
 
-FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
+FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple)
   : Generic_GCC(Host, Triple) {
+
+  // Determine if we are compiling 32-bit code on an x86_64 platform.
+  bool Lib32 = false;
+  if (Triple.getArch() == llvm::Triple::x86 &&
+      llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+        llvm::Triple::x86_64)
+    Lib32 = true;
+    
   getProgramPaths().push_back(getDriver().Dir + "/../libexec");
   getProgramPaths().push_back("/usr/libexec");
   if (Lib32) {
@@ -936,7 +1046,9 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const {
 AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
   : Generic_GCC(Host, Triple) {
 
-  getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+  if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+    getProgramPaths().push_back(getDriver().Dir);
 
   getFilePaths().push_back(getDriver().Dir + "/../lib");
   getFilePaths().push_back("/usr/lib");
@@ -973,7 +1085,8 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
 
 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(getDriver().Dir +
+                           "/../lib/clang/" CLANG_VERSION_STRING "/");
   getFilePaths().push_back("/lib/");
   getFilePaths().push_back("/usr/lib/");
 
@@ -994,13 +1107,35 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
   // list), but that's messy at best.
 }
 
+Tool &Linux::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::linuxtools::Assemble(*this); break;
+    default:
+      T = &Generic_GCC::SelectTool(C, JA);
+    }
+  }
+
+  return *T;
+}
+
 /// 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);
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+  if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+    getProgramPaths().push_back(getDriver().Dir);
 
   getFilePaths().push_back(getDriver().Dir + "/../lib");
   getFilePaths().push_back("/usr/lib");
@@ -1028,3 +1163,57 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
 
   return *T;
 }
+
+Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple)
+  : ToolChain(Host, Triple) {
+}
+
+Tool &Windows::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:
+    case Action::LipoJobClass:
+    case Action::DsymutilJobClass:
+      assert(0 && "Invalid tool kind.");
+    case Action::PreprocessJobClass:
+    case Action::PrecompileJobClass:
+    case Action::AnalyzeJobClass:
+    case Action::CompileJobClass:
+      T = new tools::Clang(*this); break;
+    case Action::AssembleJobClass:
+      T = new tools::ClangAs(*this); break;
+    case Action::LinkJobClass:
+      T = new tools::visualstudio::Link(*this); break;
+    }
+  }
+
+  return *T;
+}
+
+bool Windows::IsIntegratedAssemblerDefault() const {
+  return true;
+}
+
+bool Windows::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 *Windows::GetDefaultRelocationModel() const {
+  return "static";
+}
+
+const char *Windows::GetForcedPicModel() const {
+  if (getArchName() == "x86_64")
+    return "pic";
+  return 0;
+}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 4bdd00f..d1f1556 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -42,6 +42,11 @@ public:
 
 /// Darwin - The base Darwin tool chain.
 class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
+public:
+  /// The host version.
+  unsigned DarwinVersion[3];
+
+private:
   mutable llvm::DenseMap<unsigned, Tool*> Tools;
 
   /// Whether the information on the target has been initialized.
@@ -61,11 +66,15 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
   /// initialized.
   std::string MacosxVersionMin;
 
+private:
+  void AddDeploymentTarget(DerivedArgList &Args) const;
+
 public:
-  Darwin(const HostInfo &Host, const llvm::Triple& Triple,
-         const unsigned (&DarwinVersion)[3]);
+  Darwin(const HostInfo &Host, const llvm::Triple& Triple);
   ~Darwin();
 
+  std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
   /// @name Darwin Specific Toolchain API
   /// {
 
@@ -144,17 +153,17 @@ public:
   /// @name ToolChain Implementation
   /// {
 
+  virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
   virtual DerivedArgList *TranslateArgs(const DerivedArgList &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);
+    // Always allow blocks on Darwin; users interested in versioning are
+    // expected to use /usr/include/Blocks.h.
+    return true;
   }
   virtual bool IsIntegratedAssemblerDefault() const {
 #ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER
@@ -201,8 +210,7 @@ public:
 /// DarwinClang - The Darwin toolchain used by Clang.
 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
 public:
-  DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
-              const unsigned (&DarwinVersion)[3]);
+  DarwinClang(const HostInfo &Host, const llvm::Triple& Triple);
 
   /// @name Darwin ToolChain Implementation
   /// {
@@ -225,9 +233,7 @@ class LLVM_LIBRARY_VISIBILITY DarwinGCC : public Darwin {
   std::string ToolChainDir;
 
 public:
-  DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
-            const unsigned (&DarwinVersion)[3],
-            const unsigned (&GCCVersion)[3]);
+  DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple);
 
   /// @name Darwin ToolChain Implementation
   /// {
@@ -247,6 +253,8 @@ public:
   Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
     : Generic_GCC(Host, Triple) {}
 
+  std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
   virtual const char *GetDefaultRelocationModel() const { return "pic"; }
 };
 
@@ -266,7 +274,7 @@ public:
 
 class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_GCC {
 public:
-  FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32);
+  FreeBSD(const HostInfo &Host, const llvm::Triple& Triple);
 
   virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
 };
@@ -288,6 +296,8 @@ public:
 class LLVM_LIBRARY_VISIBILITY Linux : public Generic_GCC {
 public:
   Linux(const HostInfo &Host, const llvm::Triple& Triple);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
 };
 
 
@@ -309,6 +319,20 @@ private:
 
 };
 
+class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
+  mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+public:
+  Windows(const HostInfo &Host, const llvm::Triple& Triple);
+
+  virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+  virtual bool IsIntegratedAssemblerDefault() const;
+  virtual bool IsUnwindTablesDefault() const;
+  virtual const char *GetDefaultRelocationModel() const;
+  virtual const char *GetForcedPicModel() const;
+};
+
 } // end namespace toolchains
 } // end namespace driver
 } // end namespace clang
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index f423d4e..8436561 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -105,10 +105,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
     // Determine the output location.
     const char *DepFile;
     if (Output.getType() == types::TY_Dependencies) {
-      if (Output.isPipe())
-        DepFile = "-";
-      else
-        DepFile = Output.getFilename();
+      DepFile = Output.getFilename();
     } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
       DepFile = MF->getValue(Args);
     } else if (A->getOption().matches(options::OPT_M) ||
@@ -182,10 +179,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
     const Arg *A = it;
 
     if (A->getOption().matches(options::OPT_include)) {
-      // Use PCH if the user requested it, except for C++ (for now).
+      // Use PCH if the user requested it.
       bool UsePCH = D.CCCUsePCH;
-      if (types::isCXX(Inputs[0].getType()))
-        UsePCH = false;
 
       bool FoundPTH = false;
       bool FoundPCH = false;
@@ -342,35 +337,6 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
   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, Triple));
-    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()) {
@@ -633,6 +599,11 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
         CPUName = "x86-64";
       else if (getToolChain().getArchName() == "i386")
         CPUName = "i586";
+    } else if (getToolChain().getOS().startswith("openbsd"))  {
+      if (getToolChain().getArchName() == "x86_64")
+        CPUName = "x86-64";
+      else if (getToolChain().getArchName() == "i386")
+        CPUName = "i486";
     } else {
       if (getToolChain().getArchName() == "x86_64")
         CPUName = "x86-64";
@@ -694,57 +665,7 @@ static bool needsExceptions(const ArgList &Args,  types::ID InputType,
   }
 }
 
-/// 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));
-
-    // If the target isn't initialized (e.g., an unknown Darwin platform, return
-    // the default triple).
-    if (!DarwinTC.isTargetInitialized())
-      return Triple.getTriple();
-    
-    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,
@@ -763,10 +684,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   // Add the "effective" target triple.
   CmdArgs.push_back("-triple");
-  std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
   CmdArgs.push_back(Args.MakeArgString(TripleStr));
 
   // Select the appropriate action.
+  bool IsRewriter = false;
   if (isa<AnalyzeJobAction>(JA)) {
     assert(JA.getType() == types::TY_Plist && "Invalid output type.");
     CmdArgs.push_back("-analyze");
@@ -786,11 +708,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                       options::OPT_mno_relax_all,
                       !IsOpt))
       CmdArgs.push_back("-mrelax-all");
+
+    // When using an integrated assembler, we send -Wa, and -Xassembler options
+    // to -cc1.
+    Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                         options::OPT_Xassembler);
   } else if (isa<PrecompileJobAction>(JA)) {
-    // Use PCH if the user requested it, except for C++ (for now).
+    // Use PCH if the user requested it.
     bool UsePCH = D.CCCUsePCH;
-    if (types::isCXX(Inputs[0].getType()))
-      UsePCH = false;
 
     if (UsePCH)
       CmdArgs.push_back("-emit-pch");
@@ -813,6 +738,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-emit-pch");
     } else if (JA.getType() == types::TY_RewrittenObjC) {
       CmdArgs.push_back("-rewrite-objc");
+      IsRewriter = true;
     } else {
       assert(JA.getType() == types::TY_PP_Asm &&
              "Unexpected output type!");
@@ -856,6 +782,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       // Do not enable the missing -dealloc check.
       // '-analyzer-check-objc-missing-dealloc',
       CmdArgs.push_back("-analyzer-check-objc-unused-ivars");
+      CmdArgs.push_back("-analyzer-check-idempotent-operations");
     }
 
     // Set the output format. The default is plist, for (lame) historical
@@ -999,6 +926,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     break;
   }
 
+  // Pass the linker version in use.
+  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+    CmdArgs.push_back("-target-linker-version");
+    CmdArgs.push_back(A->getValue(Args));
+  }
+
   // -mno-omit-leaf-frame-pointer is default.
   if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
                    options::OPT_mno_omit_leaf_frame_pointer, false))
@@ -1029,6 +962,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   Args.AddAllArgs(CmdArgs, options::OPT_v);
+  Args.AddLastArg(CmdArgs, options::OPT_H);
   Args.AddLastArg(CmdArgs, options::OPT_P);
   Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
 
@@ -1201,10 +1135,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
   Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
   Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
+  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
   Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
   Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
   Args.AddLastArg(CmdArgs, options::OPT_fwrapv);
   Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
+  Args.AddLastArg(CmdArgs, options::OPT_funroll_loops);
 
   Args.AddLastArg(CmdArgs, options::OPT_pthread);
 
@@ -1279,15 +1215,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                    getToolChain().getTriple().getOS() == llvm::Triple::Win32))
     CmdArgs.push_back("-fms-extensions");
 
+  // -fborland-extensions=0 is default.
+  if (Args.hasFlag(options::OPT_fborland_extensions,
+                   options::OPT_fno_borland_extensions, false))
+    CmdArgs.push_back("-fborland-extensions");
+
   // -fgnu-keywords default varies depending on language; only pass if
   // specified.
   if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
                                options::OPT_fno_gnu_keywords))
     A->render(Args, CmdArgs);
 
-  // -fnext-runtime is default.
+  // -fnext-runtime defaults to on Darwin and when rewriting Objective-C, and is
+  // -the -cc1 default.
+  bool NeXTRuntimeIsDefault = 
+    IsRewriter || getToolChain().getTriple().getOS() == llvm::Triple::Darwin;
   if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
-                    getToolChain().getTriple().getOS() == llvm::Triple::Darwin))
+                    NeXTRuntimeIsDefault))
     CmdArgs.push_back("-fgnu-runtime");
 
   // -fobjc-nonfragile-abi=0 is default.
@@ -1389,7 +1333,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("-fdiagnostics-show-category");
     CmdArgs.push_back(A->getValue(Args));
   }
-  
+
   // Color diagnostics are the default, unless the terminal doesn't support
   // them.
   if (Args.hasFlag(options::OPT_fcolor_diagnostics,
@@ -1404,7 +1348,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   if (!Args.hasFlag(options::OPT_fspell_checking,
                     options::OPT_fno_spell_checking))
     CmdArgs.push_back("-fno-spell-checking");
-  
+
   if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
     A->render(Args, CmdArgs);
 
@@ -1464,9 +1408,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   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());
@@ -1479,9 +1420,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     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())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -1489,7 +1428,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_undef);
 
-  std::string Exec = getToolChain().getDriver().getClangProgramPath();
+  const char *Exec = getToolChain().getDriver().getClangProgramPath();
 
   // Optionally embed the -cc1 level arguments into the debug info, for build
   // analysis.
@@ -1498,7 +1437,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     for (ArgList::const_iterator it = Args.begin(),
            ie = Args.end(); it != ie; ++it)
       (*it)->render(Args, OriginalArgs);
-    
+
     llvm::SmallString<256> Flags;
     Flags += Exec;
     for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
@@ -1509,7 +1448,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(Args.MakeArgString(Flags.str()));
   }
 
-  Dest.addCommand(new Command(JA, *this, Exec.c_str(), CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 
   // Explicitly warn that these options are unsupported, even though
   // we are allowing compilation to continue.
@@ -1533,12 +1472,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 }
 
 void ClangAs::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.");
@@ -1551,7 +1488,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
 
   // Add the "effective" target triple.
   CmdArgs.push_back("-triple");
-  std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
   CmdArgs.push_back(Args.MakeArgString(TripleStr));
 
   // Set the output mode, we currently only expect to be used as a real
@@ -1581,19 +1518,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
   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());
-  }
+  assert(Input.isFilename() && "Invalid input.");
+  CmdArgs.push_back(Input.getFilename());
 
-  std::string Exec = getToolChain().getDriver().getClangProgramPath();
-  Dest.addCommand(new Command(JA, *this, Exec.c_str(), CmdArgs));
+  const char *Exec = getToolChain().getDriver().getClangProgramPath();
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
-                               Job &Dest,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
@@ -1605,6 +1537,11 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
          it = Args.begin(), ie = Args.end(); it != ie; ++it) {
     Arg *A = *it;
     if (A->getOption().hasForwardToGCC()) {
+      // Don't forward any -g arguments to assembly steps.
+      if (isa<AssembleJobAction>(JA) &&
+          A->getOption().matches(options::OPT_g_Group))
+        continue;
+
       // 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
@@ -1640,10 +1577,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
   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()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -1678,9 +1612,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back(types::getTypeName(II.getType()));
     }
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       // Don't render as input, we need gcc to do the translations.
@@ -1690,7 +1622,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
   const char *GCCName = getToolChain().getDriver().CCCGenericGCCName.c_str();
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
@@ -2022,10 +1954,7 @@ void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
          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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
@@ -2063,7 +1992,7 @@ void darwin::CC1::AddCPPArgs(const ArgList &Args,
 }
 
 void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
-                                      Job &Dest, const InputInfo &Output,
+                                      const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
@@ -2078,12 +2007,9 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
     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.");
-  }
+  assert(Output.isFilename() && "Unexpected CC1 output.");
+  OutputArgs.push_back("-o");
+  OutputArgs.push_back(Output.getFilename());
 
   if (Args.hasArg(options::OPT_E)) {
     AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
@@ -2097,11 +2023,11 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
   const char *CC1Name = getCC1Name(Inputs[0].getType());
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
-                                   Job &Dest, const InputInfo &Output,
+                                   const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
@@ -2133,9 +2059,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
   ArgStringList OutputArgs;
   if (Output.getType() != types::TY_PCH) {
     OutputArgs.push_back("-o");
-    if (Output.isPipe())
-      OutputArgs.push_back("-");
-    else if (Output.isNothing())
+    if (Output.isNothing())
       OutputArgs.push_back("/dev/null");
     else
       OutputArgs.push_back(Output.getFilename());
@@ -2168,10 +2092,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
         return;
       }
 
-      if (II.isPipe())
-        CmdArgs.push_back("-");
-      else
-        CmdArgs.push_back(II.getFilename());
+      CmdArgs.push_back(II.getFilename());
     }
 
     if (OutputArgsEarly) {
@@ -2197,11 +2118,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
   const char *CC1Name = getCC1Name(Inputs[0].getType());
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
-                                    Job &Dest, const InputInfo &Output,
+                                    const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
@@ -2224,7 +2145,9 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
   // Derived from asm spec.
   AddDarwinArch(Args, CmdArgs);
 
-  if (!getDarwinToolChain().isTargetIPhoneOS() ||
+  // Use -force_cpusubtype_ALL on x86 by default.
+  if (getToolChain().getTriple().getArch() == llvm::Triple::x86 ||
+      getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
       Args.hasArg(options::OPT_force__cpusubtype__ALL))
     CmdArgs.push_back("-force_cpusubtype_ALL");
 
@@ -2241,18 +2164,14 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
   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());
-  }
+  assert(Input.isFilename() && "Invalid input.");
+  CmdArgs.push_back(Input.getFilename());
 
   // asm_final spec is empty.
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("as"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
@@ -2272,6 +2191,22 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
                                ArgStringList &CmdArgs) const {
   const Driver &D = getToolChain().getDriver();
 
+  unsigned Version[3] = { 0, 0, 0 };
+  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+    bool HadExtra;
+    if (!Driver::GetReleaseVersion(A->getValue(Args), Version[0],
+                                   Version[1], Version[2], HadExtra) ||
+        HadExtra)
+      D.Diag(clang::diag::err_drv_invalid_version_number)
+        << A->getAsString(Args);
+  }
+
+  // Newer linkers support -demangle, pass it if supported and not disabled by
+  // the user.
+  if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) {
+    CmdArgs.push_back("-demangle");
+  }
+
   // Derived from the "link" spec.
   Args.AddAllArgs(CmdArgs, options::OPT_static);
   if (!Args.hasArg(options::OPT_static))
@@ -2413,7 +2348,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
 }
 
 void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
-                                Job &Dest, const InputInfo &Output,
+                                const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
@@ -2571,11 +2506,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("ld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
-                                Job &Dest, const InputInfo &Output,
+                                const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
@@ -2595,11 +2530,11 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
   }
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
-                                    Job &Dest, const InputInfo &Output,
+                                    const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
@@ -2615,11 +2550,11 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
-                                      Job &Dest, const InputInfo &Output,
+                                      const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
@@ -2629,27 +2564,21 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                        options::OPT_Xassembler);
 
   CmdArgs.push_back("-o");
-  if (Output.isPipe())
-    CmdArgs.push_back("-");
-  else
-    CmdArgs.push_back(Output.getFilename());
+  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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("gas"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
-                                  Job &Dest, const InputInfo &Output,
+                                  const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
@@ -2676,10 +2605,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  if (Output.isPipe()) {
-    CmdArgs.push_back("-o");
-    CmdArgs.push_back("-");
-  } else if (Output.isFilename()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -2721,9 +2647,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
         << getToolChain().getTripleString();
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -2751,11 +2675,11 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("ld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
-                                     Job &Dest, const InputInfo &Output,
+                                     const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
@@ -2765,27 +2689,21 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                        options::OPT_Xassembler);
 
   CmdArgs.push_back("-o");
-  if (Output.isPipe())
-    CmdArgs.push_back("-");
-  else
-    CmdArgs.push_back(Output.getFilename());
+  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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("as"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
-                                 Job &Dest, const InputInfo &Output,
+                                 const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
@@ -2811,10 +2729,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  if (Output.isPipe()) {
-    CmdArgs.push_back("-o");
-    CmdArgs.push_back("-");
-  } else if (Output.isFilename()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -2838,7 +2753,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
   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"));
+                                       "/4.2.1"));
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2854,9 +2769,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
         << getToolChain().getTripleString();
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -2864,6 +2777,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
+    if (D.CCCIsCXX) {
+      CmdArgs.push_back("-lstdc++");
+      CmdArgs.push_back("-lm");
+    }
+
     // FIXME: For some reason GCC passes -lgcc before adding
     // the default system libraries. Just mimic this for now.
     CmdArgs.push_back("-lgcc");
@@ -2887,11 +2805,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("ld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
-                                     Job &Dest, const InputInfo &Output,
+                                     const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
@@ -2913,27 +2831,21 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                        options::OPT_Xassembler);
 
   CmdArgs.push_back("-o");
-  if (Output.isPipe())
-    CmdArgs.push_back("-");
-  else
-    CmdArgs.push_back(Output.getFilename());
+  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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("as"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
-                                 Job &Dest, const InputInfo &Output,
+                                 const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
@@ -2959,10 +2871,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("elf_i386_fbsd");
   }
 
-  if (Output.isPipe()) {
-    CmdArgs.push_back("-o");
-    CmdArgs.push_back("-");
-  } else if (Output.isFilename()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -2989,6 +2898,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddAllArgs(CmdArgs, options::OPT_L);
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_e);
+  Args.AddAllArgs(CmdArgs, options::OPT_s);
+  Args.AddAllArgs(CmdArgs, options::OPT_t);
+  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+  Args.AddAllArgs(CmdArgs, options::OPT_r);
 
   for (InputInfoList::const_iterator
          it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
@@ -3000,9 +2913,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
         << getToolChain().getTripleString();
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3053,51 +2964,79 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("ld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
+void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+                                        const InputInfo &Output,
+                                        const InputInfoList &Inputs,
+                                        const ArgList &Args,
+                                        const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  // Add --32/--64 to make sure we get the format we want.
+  // This is incomplete
+  if (getToolChain().getArch() == llvm::Triple::x86) {
+    CmdArgs.push_back("--32");
+  } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+    CmdArgs.push_back("--64");
+  } else if (getToolChain().getArch() == llvm::Triple::arm) {
+    llvm::StringRef MArch = getToolChain().getArchName();
+    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+      CmdArgs.push_back("-mfpu=neon");
+  }
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+                       options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  for (InputInfoList::const_iterator
+         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+    const InputInfo &II = *it;
+    CmdArgs.push_back(II.getFilename());
+  }
+
+  const char *Exec =
+    Args.MakeArgString(getToolChain().GetProgramPath("as"));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+
 void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
-                                     Job &Dest, const InputInfo &Output,
-                                     const InputInfoList &Inputs,
-                                     const ArgList &Args,
-                                     const char *LinkingOutput) const {
+                                   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());
+  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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("gas"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
-                                 Job &Dest, const InputInfo &Output,
-                                 const InputInfoList &Inputs,
-                                 const ArgList &Args,
-                                 const char *LinkingOutput) const {
+                               const InputInfo &Output,
+                               const InputInfoList &Inputs,
+                               const ArgList &Args,
+                               const char *LinkingOutput) const {
   const Driver &D = getToolChain().getDriver();
   ArgStringList CmdArgs;
 
-  if (Output.isPipe()) {
-    CmdArgs.push_back("-o");
-    CmdArgs.push_back("-");
-  } else if (Output.isFilename()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -3123,9 +3062,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
         << getToolChain().getTripleString();
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3156,7 +3093,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("/usr/gnu/bin/gld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
 /// DragonFly Tools
@@ -3164,7 +3101,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
 // 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 InputInfo &Output,
                                        const InputInfoList &Inputs,
                                        const ArgList &Args,
                                        const char *LinkingOutput) const {
@@ -3179,30 +3116,24 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                        options::OPT_Xassembler);
 
   CmdArgs.push_back("-o");
-  if (Output.isPipe())
-    CmdArgs.push_back("-");
-  else
-    CmdArgs.push_back(Output.getFilename());
+  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());
+    CmdArgs.push_back(II.getFilename());
   }
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("as"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.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 InputInfo &Output,
+                                   const InputInfoList &Inputs,
+                                   const ArgList &Args,
+                                   const char *LinkingOutput) const {
   const Driver &D = getToolChain().getDriver();
   ArgStringList CmdArgs;
 
@@ -3224,10 +3155,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back("elf_i386");
   }
 
-  if (Output.isPipe()) {
-    CmdArgs.push_back("-o");
-    CmdArgs.push_back("-");
-  } else if (Output.isFilename()) {
+  if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
   } else {
@@ -3265,9 +3193,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
         << getToolChain().getTripleString();
 
-    if (II.isPipe())
-      CmdArgs.push_back("-");
-    else if (II.isFilename())
+    if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
     else
       II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3293,6 +3219,11 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("/usr/lib");
     }
 
+    if (D.CCCIsCXX) {
+      CmdArgs.push_back("-lstdc++");
+      CmdArgs.push_back("-lm");
+    }
+
     if (Args.hasArg(options::OPT_shared)) {
       CmdArgs.push_back("-lgcc_pic");
     } else {
@@ -3328,5 +3259,46 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   const char *Exec =
     Args.MakeArgString(getToolChain().GetProgramPath("ld"));
-  Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
+                                      const InputInfo &Output,
+                                      const InputInfoList &Inputs,
+                                      const ArgList &Args,
+                                      const char *LinkingOutput) const {
+  const Driver &D = getToolChain().getDriver();
+  ArgStringList CmdArgs;
+
+  if (Output.isFilename()) {
+    CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + Output.getFilename()));
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+    !Args.hasArg(options::OPT_nostartfiles)) {
+    CmdArgs.push_back("-defaultlib:libcmt");
+  }
+
+  CmdArgs.push_back("-nologo");
+
+  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 visual studio linker.
+    if (II.getType() == types::TY_LLVM_BC)
+      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+      << getToolChain().getTripleString();
+
+    if (II.isFilename())
+      CmdArgs.push_back(II.getFilename());
+    else
+      II.getInputArg().renderAsInput(Args, CmdArgs);
+  }
+
+  const char *Exec =
+  Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
+  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 2a18103..b5defa4 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -41,14 +41,11 @@ namespace tools {
   public:
     Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return true; }
     virtual bool hasGoodDiagnostics() 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,
@@ -61,14 +58,11 @@ namespace tools {
     ClangAs(const ToolChain &TC) : Tool("clang::as",
                                         "clang integrated assembler", TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return true; }
     virtual bool hasGoodDiagnostics() const { return true; }
     virtual bool hasIntegratedAssembler() 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,
@@ -83,7 +77,6 @@ namespace gcc {
            const ToolChain &TC) : Tool(Name, ShortName, TC) {}
 
     virtual void ConstructJob(Compilation &C, const JobAction &JA,
-                              Job &Dest,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &TCArgs,
@@ -101,8 +94,6 @@ namespace gcc {
     Preprocess(const ToolChain &TC) : Common("gcc::Preprocess",
                                              "gcc preprocessor", TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return true; }
     virtual bool hasGoodDiagnostics() const { return true; }
     virtual bool hasIntegratedCPP() const { return false; }
 
@@ -115,8 +106,6 @@ namespace gcc {
     Precompile(const ToolChain &TC) : Common("gcc::Precompile",
                                              "gcc precompile", TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return false; }
     virtual bool hasGoodDiagnostics() const { return true; }
     virtual bool hasIntegratedCPP() const { return true; }
 
@@ -129,8 +118,6 @@ namespace gcc {
     Compile(const ToolChain &TC) : Common("gcc::Compile",
                                           "gcc frontend", TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return true; }
     virtual bool hasGoodDiagnostics() const { return true; }
     virtual bool hasIntegratedCPP() const { return true; }
 
@@ -143,8 +130,6 @@ namespace gcc {
     Assemble(const ToolChain &TC) : Common("gcc::Assemble",
                                            "assembler (via gcc)", 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,
@@ -156,8 +141,6 @@ namespace gcc {
     Link(const ToolChain &TC) : Common("gcc::Link",
                                        "linker (via gcc)", 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,
@@ -207,8 +190,6 @@ namespace darwin {
     CC1(const char *Name, const char *ShortName,
         const ToolChain &TC) : DarwinTool(Name, ShortName, TC) {}
 
-    virtual bool acceptsPipedInput() const { return true; }
-    virtual bool canPipeOutput() const { return true; }
     virtual bool hasGoodDiagnostics() const { return true; }
     virtual bool hasIntegratedCPP() const { return true; }
   };
@@ -219,7 +200,6 @@ namespace darwin {
                                           "gcc preprocessor", TC) {}
 
     virtual void ConstructJob(Compilation &C, const JobAction &JA,
-                              Job &Dest,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &TCArgs,
@@ -231,7 +211,6 @@ namespace darwin {
     Compile(const ToolChain &TC) : CC1("darwin::Compile", "gcc frontend", TC) {}
 
     virtual void ConstructJob(Compilation &C, const JobAction &JA,
-                              Job &Dest,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &TCArgs,
@@ -243,12 +222,9 @@ namespace darwin {
     Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble",
                                                "assembler", 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,
@@ -261,12 +237,9 @@ namespace darwin {
   public:
     Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", 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,
@@ -277,12 +250,9 @@ namespace darwin {
   public:
     Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", "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,
@@ -294,12 +264,9 @@ namespace darwin {
     Dsymutil(const ToolChain &TC) : DarwinTool("darwin::Dsymutil",
                                                "dsymutil", 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,
@@ -314,12 +281,9 @@ namespace openbsd {
     Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler",
                                          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,
@@ -329,12 +293,9 @@ namespace openbsd {
   public:
     Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", 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,
@@ -349,12 +310,9 @@ namespace freebsd {
     Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler",
                                          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,
@@ -364,12 +322,9 @@ namespace freebsd {
   public:
     Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", 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,
@@ -377,6 +332,22 @@ namespace freebsd {
   };
 } // end namespace freebsd
 
+  /// linux -- Directly call GNU Binutils assembler and linker
+namespace linuxtools {
+  class LLVM_LIBRARY_VISIBILITY Assemble : public Tool  {
+  public:
+    Assemble(const ToolChain &TC) : Tool("linux::Assemble", "assembler",
+                                         TC) {}
+
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+}
   /// minix -- Directly call GNU Binutils assembler and linker
 namespace minix {
   class LLVM_LIBRARY_VISIBILITY Assemble : public Tool  {
@@ -384,12 +355,9 @@ namespace minix {
     Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler",
                                          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,
@@ -399,12 +367,9 @@ namespace minix {
   public:
     Link(const ToolChain &TC) : Tool("minix::Link", "linker", 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,
@@ -419,12 +384,9 @@ namespace auroraux {
     Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler",
                                          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,
@@ -434,12 +396,9 @@ namespace auroraux {
   public:
     Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", 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,
@@ -454,12 +413,9 @@ namespace dragonfly {
     Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler",
                                          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,
@@ -469,12 +425,9 @@ namespace dragonfly {
   public:
     Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", 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,
@@ -482,6 +435,22 @@ namespace dragonfly {
   };
 } // end namespace dragonfly
 
+  /// Visual studio tools.
+namespace visualstudio {
+  class LLVM_LIBRARY_VISIBILITY Link : public Tool  {
+  public:
+    Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {}
+
+    virtual bool hasIntegratedCPP() const { return false; }
+
+    virtual void ConstructJob(Compilation &C, const JobAction &JA,
+                              const InputInfo &Output,
+                              const InputInfoList &Inputs,
+                              const ArgList &TCArgs,
+                              const char *LinkingOutput) const;
+  };
+} // end namespace visualstudio
+
 } // end namespace toolchains
 } // end namespace driver
 } // end namespace clang
-- 
cgit v1.1