head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.15
	netbsd-11-0-RC3:1.1.1.15
	netbsd-11-0-RC2:1.1.1.15
	netbsd-11-0-RC1:1.1.1.15
	perseant-exfatfs-base-20250801:1.1.1.15
	netbsd-11:1.1.1.15.0.14
	netbsd-11-base:1.1.1.15
	netbsd-10-1-RELEASE:1.1.1.15
	perseant-exfatfs-base-20240630:1.1.1.15
	perseant-exfatfs:1.1.1.15.0.12
	perseant-exfatfs-base:1.1.1.15
	netbsd-8-3-RELEASE:1.1.1.14
	netbsd-9-4-RELEASE:1.1.1.15
	netbsd-10-0-RELEASE:1.1.1.15
	netbsd-10-0-RC6:1.1.1.15
	netbsd-10-0-RC5:1.1.1.15
	netbsd-10-0-RC4:1.1.1.15
	netbsd-10-0-RC3:1.1.1.15
	netbsd-10-0-RC2:1.1.1.15
	netbsd-10-0-RC1:1.1.1.15
	netbsd-10:1.1.1.15.0.10
	netbsd-10-base:1.1.1.15
	netbsd-9-3-RELEASE:1.1.1.15
	cjep_sun2x:1.1.1.15.0.8
	cjep_sun2x-base:1.1.1.15
	cjep_staticlib_x-base1:1.1.1.15
	netbsd-9-2-RELEASE:1.1.1.15
	cjep_staticlib_x:1.1.1.15.0.6
	cjep_staticlib_x-base:1.1.1.15
	netbsd-9-1-RELEASE:1.1.1.15
	phil-wifi-20200421:1.1.1.15
	phil-wifi-20200411:1.1.1.15
	phil-wifi-20200406:1.1.1.15
	netbsd-8-2-RELEASE:1.1.1.14
	netbsd-9-0-RELEASE:1.1.1.15
	netbsd-9-0-RC2:1.1.1.15
	netbsd-9-0-RC1:1.1.1.15
	netbsd-9:1.1.1.15.0.4
	netbsd-9-base:1.1.1.15
	netbsd-8-1-RELEASE:1.1.1.14
	netbsd-8-1-RC1:1.1.1.14
	pgoyette-compat-merge-20190127:1.1.1.15
	pgoyette-compat-20190127:1.1.1.15
	pgoyette-compat-20190118:1.1.1.15
	pgoyette-compat-1226:1.1.1.15
	pgoyette-compat-1126:1.1.1.15
	pgoyette-compat-1020:1.1.1.15
	pgoyette-compat-0930:1.1.1.15
	pgoyette-compat-0906:1.1.1.15
	netbsd-7-2-RELEASE:1.1.1.8.2.1
	pgoyette-compat-0728:1.1.1.15
	netbsd-8-0-RELEASE:1.1.1.14
	pgoyette-compat-0625:1.1.1.15
	netbsd-8-0-RC2:1.1.1.14
	pgoyette-compat-0521:1.1.1.15
	pgoyette-compat-0502:1.1.1.15
	pgoyette-compat-0422:1.1.1.15
	netbsd-8-0-RC1:1.1.1.14
	pgoyette-compat-0415:1.1.1.15
	pgoyette-compat-0407:1.1.1.15
	pgoyette-compat-0330:1.1.1.15
	pgoyette-compat-0322:1.1.1.15
	pgoyette-compat-0315:1.1.1.15
	netbsd-7-1-2-RELEASE:1.1.1.8.2.1
	pgoyette-compat:1.1.1.15.0.2
	pgoyette-compat-base:1.1.1.15
	netbsd-7-1-1-RELEASE:1.1.1.8.2.1
	matt-nb8-mediatek:1.1.1.14.0.8
	matt-nb8-mediatek-base:1.1.1.14
	perseant-stdc-iso10646:1.1.1.14.0.6
	perseant-stdc-iso10646-base:1.1.1.14
	netbsd-8:1.1.1.14.0.4
	netbsd-8-base:1.1.1.14
	prg-localcount2-base3:1.1.1.14
	prg-localcount2-base2:1.1.1.14
	prg-localcount2-base1:1.1.1.14
	prg-localcount2:1.1.1.14.0.2
	prg-localcount2-base:1.1.1.14
	pgoyette-localcount-20170426:1.1.1.14
	bouyer-socketcan-base1:1.1.1.14
	pgoyette-localcount-20170320:1.1.1.14
	netbsd-7-1:1.1.1.8.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.8.2.1
	netbsd-7-1-RC2:1.1.1.8.2.1
	clang-294123:1.1.1.14
	netbsd-7-nhusb-base-20170116:1.1.1.8.2.1
	bouyer-socketcan:1.1.1.13.0.2
	bouyer-socketcan-base:1.1.1.13
	clang-291444:1.1.1.13
	pgoyette-localcount-20170107:1.1.1.12
	netbsd-7-1-RC1:1.1.1.8.2.1
	pgoyette-localcount-20161104:1.1.1.12
	netbsd-7-0-2-RELEASE:1.1.1.8.2.1
	localcount-20160914:1.1.1.12
	netbsd-7-nhusb:1.1.1.8.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.8.2.1
	clang-280599:1.1.1.12
	pgoyette-localcount-20160806:1.1.1.11
	pgoyette-localcount-20160726:1.1.1.11
	pgoyette-localcount:1.1.1.11.0.2
	pgoyette-localcount-base:1.1.1.11
	netbsd-7-0-1-RELEASE:1.1.1.8.2.1
	clang-261930:1.1.1.11
	netbsd-7-0:1.1.1.8.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.8.2.1
	netbsd-7-0-RC3:1.1.1.8.2.1
	netbsd-7-0-RC2:1.1.1.8.2.1
	netbsd-7-0-RC1:1.1.1.8.2.1
	clang-237755:1.1.1.10
	clang-232565:1.1.1.10
	clang-227398:1.1.1.9
	tls-maxphys-base:1.1.1.8
	tls-maxphys:1.1.1.8.0.4
	netbsd-7:1.1.1.8.0.2
	netbsd-7-base:1.1.1.8
	clang-215315:1.1.1.8
	clang-209886:1.1.1.7
	yamt-pagecache:1.1.1.6.0.4
	yamt-pagecache-base9:1.1.1.6
	tls-earlyentropy:1.1.1.6.0.2
	tls-earlyentropy-base:1.1.1.7
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.6
	riastradh-drm2-base3:1.1.1.6
	clang-202566:1.1.1.6
	clang-201163:1.1.1.5
	clang-199312:1.1.1.4
	clang-198450:1.1.1.3
	clang-196603:1.1.1.2
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2013.12.06.23.17.02;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	oIJdta8D25nvY7gx;

1.1.1.3
date	2014.01.05.15.39.28;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	wh3aCSIWykURqWjx;

1.1.1.4
date	2014.01.15.21.26.24;	author joerg;	state Exp;
branches;
next	1.1.1.5;
commitid	NQXlzzA0SPkc5glx;

1.1.1.5
date	2014.02.14.20.07.25;	author joerg;	state Exp;
branches;
next	1.1.1.6;
commitid	annVkZ1sc17rF6px;

1.1.1.6
date	2014.03.04.19.54.56;	author joerg;	state Exp;
branches
	1.1.1.6.2.1
	1.1.1.6.4.1;
next	1.1.1.7;
commitid	29z1hJonZISIXprx;

1.1.1.7
date	2014.05.30.18.14.41;	author joerg;	state Exp;
branches;
next	1.1.1.8;
commitid	8q0kdlBlCn09GACx;

1.1.1.8
date	2014.08.10.17.08.34;	author joerg;	state Exp;
branches
	1.1.1.8.2.1
	1.1.1.8.4.1;
next	1.1.1.9;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.9
date	2015.01.29.19.57.30;	author joerg;	state Exp;
branches;
next	1.1.1.10;
commitid	mlISSizlPKvepX7y;

1.1.1.10
date	2015.03.18.17.26.38;	author joerg;	state Exp;
branches;
next	1.1.1.11;
commitid	uc5pyJVphALN17ey;

1.1.1.11
date	2016.02.27.22.12.05;	author joerg;	state Exp;
branches
	1.1.1.11.2.1;
next	1.1.1.12;
commitid	tIimz3oDlh1NpBWy;

1.1.1.12
date	2016.09.03.23.12.03;	author joerg;	state Exp;
branches;
next	1.1.1.13;
commitid	fN8JuO7v94GspTkz;

1.1.1.13
date	2017.01.11.10.33.42;	author joerg;	state Exp;
branches
	1.1.1.13.2.1;
next	1.1.1.14;
commitid	CNnUNfII1jgNmxBz;

1.1.1.14
date	2017.02.09.17.38.05;	author joerg;	state Exp;
branches;
next	1.1.1.15;
commitid	UxB8JMFWM7xyMiFz;

1.1.1.15
date	2017.08.01.10.54.02;	author joerg;	state dead;
branches;
next	;
commitid	8fbWrGIjoiyAZu1A;

1.1.1.6.2.1
date	2014.08.10.07.08.08;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.6.4.1
date	2014.03.04.19.54.56;	author yamt;	state dead;
branches;
next	1.1.1.6.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.6.4.2
date	2014.05.22.16.18.27;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.8.2.1
date	2015.06.04.20.04.28;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.8.4.1
date	2014.08.10.17.08.34;	author tls;	state dead;
branches;
next	1.1.1.8.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.8.4.2
date	2014.08.19.23.47.28;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.11.2.1
date	2017.03.20.06.52.37;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.13.2.1
date	2017.04.21.16.51.38;	author bouyer;	state Exp;
branches;
next	;
commitid	dUG7nkTKALCadqOz;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- Tools.cpp - Tools Implementations --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
    if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP())
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "-E";
}

/// CheckCodeGenerationOptions - Perform some validation of code generation
/// arguments that is shared with gcc.
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
  // In gcc, only ARM checks this, but it seems reasonable to check universally.
  if (Args.hasArg(options::OPT_static))
    if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
                                       options::OPT_mdynamic_no_pic))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-static";
}

// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
static void QuoteTarget(StringRef Target,
                        SmallVectorImpl<char> &Res) {
  for (unsigned i = 0, e = Target.size(); i != e; ++i) {
    switch (Target[i]) {
    case ' ':
    case '\t':
      // Escape the preceding backslashes
      for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
        Res.push_back('\\');

      // Escape the space/tab
      Res.push_back('\\');
      break;
    case '$':
      Res.push_back('$');
      break;
    case '#':
      Res.push_back('\\');
      break;
    default:
      break;
    }

    Res.push_back(Target[i]);
  }
}

static void addDirectoryList(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             const char *ArgName,
                             const char *EnvVar) {
  const char *DirList = ::getenv(EnvVar);
  bool CombinedArg = false;

  if (!DirList)
    return; // Nothing to do.

  StringRef Name(ArgName);
  if (Name.equals("-I") || Name.equals("-L"))
    CombinedArg = true;

  StringRef Dirs(DirList);
  if (Dirs.empty()) // Empty string should not add '.'.
    return;

  StringRef::size_type Delim;
  while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
    if (Delim == 0) { // Leading colon.
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(".");
      }
    } else {
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
      }
    }
    Dirs = Dirs.substr(Delim + 1);
  }

  if (Dirs.empty()) { // Trailing colon.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(".");
    }
  } else { // Add the last path.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(Args.MakeArgString(Dirs));
    }
  }
}

static void AddLinkerInputs(const ToolChain &TC,
                            const InputInfoList &Inputs, const ArgList &Args,
                            ArgStringList &CmdArgs) {
  const Driver &D = TC.getDriver();

  // Add extra linker input arguments which are not treated as inputs
  // (constructed via -Xarch_).
  Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    if (!TC.HasNativeLLVMSupport()) {
      // Don't try to pass LLVM inputs unless we have native support.
      if (II.getType() == types::TY_LLVM_IR ||
          II.getType() == types::TY_LTO_IR ||
          II.getType() == types::TY_LLVM_BC ||
          II.getType() == types::TY_LTO_BC)
        D.Diag(diag::err_drv_no_linker_llvm_support)
          << TC.getTripleString();
    }

    // Add filenames immediately.
    if (II.isFilename()) {
      CmdArgs.push_back(II.getFilename());
      continue;
    }

    // Otherwise, this is a linker input argument.
    const Arg &A = II.getInputArg();

    // Handle reserved library options.
    if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
      TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) {
      TC.AddCCKextLibArgs(Args, CmdArgs);
    } else
      A.renderAsInput(Args, CmdArgs);
  }

  // LIBRARY_PATH - included following the user specified library paths.
  addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
}

/// \brief Determine whether Objective-C automated reference counting is
/// enabled.
static bool isObjCAutoRefCount(const ArgList &Args) {
  return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
}

/// \brief Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
  if (isObjCAutoRefCount(Args)) {
    Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
    return true;
  }
  return Args.hasArg(options::OPT_fobjc_link_runtime);
}

static void addProfileRT(const ToolChain &TC, const ArgList &Args,
                         ArgStringList &CmdArgs,
                         llvm::Triple Triple) {
  if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
        Args.hasArg(options::OPT_fprofile_generate) ||
        Args.hasArg(options::OPT_fcreate_profile) ||
        Args.hasArg(options::OPT_coverage)))
    return;

  // GCC links libgcov.a by adding -L<inst>/gcc/lib/gcc/<triple>/<ver> -lgcov to
  // the link line. We cannot do the same thing because unlike gcov there is a
  // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is
  // not supported by old linkers.
  std::string ProfileRT =
    std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a";

  CmdArgs.push_back(Args.MakeArgString(ProfileRT));
}

static bool forwardToGCC(const Option &O) {
  // Don't forward inputs from the original command line.  They are added from
  // InputInfoList.
  return O.getKind() != Option::InputClass &&
         !O.hasFlag(options::DriverOption) &&
         !O.hasFlag(options::LinkerInput);
}

void Clang::AddPreprocessingOptions(Compilation &C,
                                    const JobAction &JA,
                                    const Driver &D,
                                    const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs) const {
  Arg *A;

  CheckPreprocessingOptions(D, Args);

  Args.AddLastArg(CmdArgs, options::OPT_C);
  Args.AddLastArg(CmdArgs, options::OPT_CC);

  // Handle dependency file generation.
  if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
      (A = Args.getLastArg(options::OPT_MD)) ||
      (A = Args.getLastArg(options::OPT_MMD))) {
    // Determine the output location.
    const char *DepFile;
    if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
      DepFile = MF->getValue();
      C.addFailureResultFile(DepFile, &JA);
    } else if (Output.getType() == types::TY_Dependencies) {
      DepFile = Output.getFilename();
    } else if (A->getOption().matches(options::OPT_M) ||
               A->getOption().matches(options::OPT_MM)) {
      DepFile = "-";
    } else {
      DepFile = getDependencyFileName(Args, Inputs);
      C.addFailureResultFile(DepFile, &JA);
    }
    CmdArgs.push_back("-dependency-file");
    CmdArgs.push_back(DepFile);

    // Add a default target if one wasn't specified.
    if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
      const char *DepTarget;

      // If user provided -o, that is the dependency target, except
      // when we are only generating a dependency file.
      Arg *OutputOpt = Args.getLastArg(options::OPT_o);
      if (OutputOpt && Output.getType() != types::TY_Dependencies) {
        DepTarget = OutputOpt->getValue();
      } else {
        // Otherwise derive from the base input.
        //
        // FIXME: This should use the computed output file location.
        SmallString<128> P(Inputs[0].getBaseInput());
        llvm::sys::path::replace_extension(P, "o");
        DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
      }

      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(DepTarget, Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));
    }

    if (A->getOption().matches(options::OPT_M) ||
        A->getOption().matches(options::OPT_MD))
      CmdArgs.push_back("-sys-header-deps");
  }

  if (Args.hasArg(options::OPT_MG)) {
    if (!A || A->getOption().matches(options::OPT_MD) ||
              A->getOption().matches(options::OPT_MMD))
      D.Diag(diag::err_drv_mg_requires_m_or_mm);
    CmdArgs.push_back("-MG");
  }

  Args.AddLastArg(CmdArgs, options::OPT_MP);

  // Convert all -MQ <target> args to -MT <quoted target>
  for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
                                             options::OPT_MQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = *it;
    A->claim();

    if (A->getOption().matches(options::OPT_MQ)) {
      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(A->getValue(), Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));

    // -MT flag - no change
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Add -i* options, and automatically translate to
  // -include-pch/-include-pth for transparent PCH support. It's
  // wonky, but we include looking for .gch so we can support seamless
  // replacement into a build system already set up to be generating
  // .gch files.
  bool RenderedImplicitInclude = false;
  for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = it;

    if (A->getOption().matches(options::OPT_include)) {
      bool IsFirstImplicitInclude = !RenderedImplicitInclude;
      RenderedImplicitInclude = true;

      // Use PCH if the user requested it.
      bool UsePCH = D.CCCUsePCH;

      bool FoundPTH = false;
      bool FoundPCH = false;
      SmallString<128> P(A->getValue());
      // We want the files to have a name like foo.h.pch. Add a dummy extension
      // so that replace_extension does the right thing.
      P += ".dummy";
      if (UsePCH) {
        llvm::sys::path::replace_extension(P, "pch");
        if (llvm::sys::fs::exists(P.str()))
          FoundPCH = true;
      }

      if (!FoundPCH) {
        llvm::sys::path::replace_extension(P, "pth");
        if (llvm::sys::fs::exists(P.str()))
          FoundPTH = true;
      }

      if (!FoundPCH && !FoundPTH) {
        llvm::sys::path::replace_extension(P, "gch");
        if (llvm::sys::fs::exists(P.str())) {
          FoundPCH = UsePCH;
          FoundPTH = !UsePCH;
        }
      }

      if (FoundPCH || FoundPTH) {
        if (IsFirstImplicitInclude) {
          A->claim();
          if (UsePCH)
            CmdArgs.push_back("-include-pch");
          else
            CmdArgs.push_back("-include-pth");
          CmdArgs.push_back(Args.MakeArgString(P.str()));
          continue;
        } else {
          // Ignore the PCH if not first on command line and emit warning.
          D.Diag(diag::warn_drv_pch_not_first_include)
              << P.str() << A->getAsString(Args);
        }
      }
    }

    // Not translated, render as usual.
    A->claim();
    A->render(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F,
                  options::OPT_index_header_map);

  // Add -Wp, and -Xassembler if using the preprocessor.

  // FIXME: There is a very unfortunate problem here, some troubled
  // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
  // really support that we would have to parse and then translate
  // those options. :(
  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
                       options::OPT_Xpreprocessor);

  // -I- is a deprecated GCC feature, reject it.
  if (Arg *A = Args.getLastArg(options::OPT_I_))
    D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args);

  // If we have a --sysroot, and don't have an explicit -isysroot flag, add an
  // -isysroot to the CC1 invocation.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    if (!Args.hasArg(options::OPT_isysroot)) {
      CmdArgs.push_back("-isysroot");
      CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
    }
  }

  // Parse additional include paths from environment variables.
  // FIXME: We should probably sink the logic for handling these from the
  // frontend into the driver. It will allow deleting 4 otherwise unused flags.
  // CPATH - included following the user specified includes (but prior to
  // builtin and standard includes).
  addDirectoryList(Args, CmdArgs, "-I", "CPATH");
  // C_INCLUDE_PATH - system includes enabled when compiling C.
  addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH");
  // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
  addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH");
  // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
  addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH");
  // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
  addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");

  // Add C++ include arguments, if needed.
  if (types::isCXX(Inputs[0].getType()))
    getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);

  // Add system include arguments.
  getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
}

/// 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(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Case("strongarm", "v4")
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
    .Cases("cortex-r4", "cortex-r5", "v7r")
    .Case("cortex-m0", "v6m")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7em")
    .Case("cortex-a9-mp", "v7f")
    .Case("swift", "v7s")
    .Cases("cortex-a53", "cortex-a57", "v8")
    .Default("");
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
//
// FIXME: tblgen this.
static std::string 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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  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();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  // Handle -march=native.
  std::string NativeMArch;
  if (MArch == "native") {
    std::string CPU = llvm::sys::getHostCPUName();
    if (CPU != "generic") {
      // Translate the native cpu into the architecture. The switch below will
      // then chose the minimum cpu for that arch.
      NativeMArch = std::string("arm") + getLLVMArchSuffixForARM(CPU);
      MArch = NativeMArch;
    }
  }

  return llvm::StringSwitch<const char *>(MArch)
    .Cases("armv2", "armv2a","arm2")
    .Case("armv3", "arm6")
    .Case("armv3m", "arm7m")
    .Case("armv4", "strongarm")
    .Case("armv4t", "arm7tdmi")
    .Cases("armv5", "armv5t", "arm10tdmi")
    .Cases("armv5e", "armv5te", "arm1022e")
    .Case("armv5tej", "arm926ej-s")
    .Cases("armv6", "armv6k", "arm1136jf-s")
    .Case("armv6j", "arm1136j-s")
    .Cases("armv6z", "armv6zk", "arm1176jzf-s")
    .Case("armv6t2", "arm1156t2-s")
    .Cases("armv6m", "armv6-m", "cortex-m0")
    .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
    .Cases("armv7em", "armv7e-m", "cortex-m4")
    .Cases("armv7f", "armv7-f", "cortex-a9-mp")
    .Cases("armv7s", "armv7-s", "swift")
    .Cases("armv7r", "armv7-r", "cortex-r4")
    .Cases("armv7m", "armv7-m", "cortex-m3")
    .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
    .Case("ep9312", "ep9312")
    .Case("iwmmxt", "iwmmxt")
    .Case("xscale", "xscale")
    // If all else failed, return the most base CPU with thumb interworking
    // supported by LLVM.
    .Default("arm7tdmi");
}

/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting.
//
// FIXME: tblgen this.
static std::string getAArch64TargetCPU(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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  return "generic";
}

// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return true;

  case llvm::Triple::aarch64:
  case llvm::Triple::arm:
  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
    if (Triple.isOSDarwin())
      return true;
    return false;

  case llvm::Triple::ppc64le:
  case llvm::Triple::systemz:
  case llvm::Triple::xcore:
    return false;
  }
}

static bool isNoCommonDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return false;

  case llvm::Triple::xcore:
    return true;
  }
}

// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
static void getAArch64FPUFeatures(const Driver &D, const Arg *A,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
  StringRef FPU = A->getValue();
  if (FPU == "fp-armv8") {
    Features.push_back("+fp-armv8");
  } else if (FPU == "neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
  } else if (FPU == "crypto-neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("+crypto");
  } else if (FPU == "neon") {
    Features.push_back("+neon");
  } else if (FPU == "none") {
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Handle -mhwdiv=.
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef HWDiv = A->getValue();
  if (HWDiv == "arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("-hwdiv");
  } else if (HWDiv == "thumb") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "none") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("-hwdiv");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
 
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
static void getARMFPUFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef FPU = A->getValue();

  // Set the target features based on the FPU.
  if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
    // Disable any default FPU support.
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-neon");
  } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
    Features.push_back("+vfp3");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp") {
    Features.push_back("+vfp2");
    Features.push_back("-neon");
  } else if (FPU == "vfp3" || FPU == "vfpv3") {
    Features.push_back("+vfp3");
    Features.push_back("-neon");
  } else if (FPU == "fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("-neon");
    Features.push_back("-crypto");
  } else if (FPU == "neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("-crypto");
  } else if (FPU == "crypto-neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("+crypto");
  } else if (FPU == "neon") {
    Features.push_back("+neon");
  } else if (FPU == "none") {
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-vfp4");
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
static StringRef getARMFloatABI(const Driver &D,
                                const ArgList &Args,
                                const llvm::Triple &Triple) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi)
          << A->getAsString(Args);
        FloatABI = "soft";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    switch (Triple.getOS()) {
    case llvm::Triple::Darwin:
    case llvm::Triple::MacOSX:
    case llvm::Triple::IOS: {
      // Darwin defaults to "softfp" for v6 and v7.
      //
      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
      std::string ArchName =
        getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
      if (StringRef(ArchName).startswith("v6") ||
          StringRef(ArchName).startswith("v7"))
        FloatABI = "softfp";
      else
        FloatABI = "soft";
      break;
    }

    case llvm::Triple::FreeBSD:
      // FreeBSD defaults to soft float
      FloatABI = "soft";
      break;

    default:
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      case llvm::Triple::GNUEABI:
        FloatABI = "softfp";
        break;
      case llvm::Triple::EABI:
        // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
        FloatABI = "softfp";
        break;
      case llvm::Triple::Android: {
        std::string ArchName =
          getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
        if (StringRef(ArchName).startswith("v7"))
          FloatABI = "softfp";
        else
          FloatABI = "soft";
        break;
      }
      default:
        // Assume "soft", but warn the user we are guessing.
        FloatABI = "soft";
        D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
        break;
      }
    }
  }

  return FloatABI;
}

static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features) {
  StringRef FloatABI = getARMFloatABI(D, Args, Triple);
  // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
  // yet (it uses the -mfloat-abi and -msoft-float options), and it is
  // stripped out by the ARM target.
  // Use software floating point operations?
  if (FloatABI == "soft")
    Features.push_back("+soft-float");

  // Use software floating point argument passing?
  if (FloatABI != "hard")
    Features.push_back("+soft-float-abi");

  // Honor -mfpu=.
  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
    getARMFPUFeatures(D, A, Args, Features);
  if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
    getARMHWDivFeatures(D, A, Args, Features);

  // Setting -msoft-float effectively disables NEON because of the GCC
  // implementation, although the same isn't true of VFP or VFP3.
  if (FloatABI == "soft")
    Features.push_back("-neon");

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
}

void Clang::AddARMTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             bool KernelOrKext) const {
  const Driver &D = getToolChain().getDriver();
  // Get the effective triple, which takes into account the deployment target.
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);
  std::string CPUName = getARMTargetCPU(Args, Triple);

  // Select the ABI to use.
  //
  // FIXME: Support -meabi.
  const char *ABIName = 0;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
  } else if (Triple.isOSDarwin()) {
    // The backend is hardwired to assume AAPCS for M-class processors, ensure
    // the frontend matches that.
    if (Triple.getEnvironment() == llvm::Triple::EABI ||
        StringRef(CPUName).startswith("cortex-m")) {
      ABIName = "aapcs";
    } else {
      ABIName = "apcs-gnu";
    }
  } else {
    // Select the default based on the platform.
    switch(Triple.getEnvironment()) {
    case llvm::Triple::Android:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::GNUEABIHF:
      ABIName = "aapcs-linux";
      break;
    case llvm::Triple::EABI:
      ABIName = "aapcs";
      break;
    default:
      ABIName = "apcs-gnu";
    }
  }
  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  // Determine floating point ABI from the options & target defaults.
  StringRef FloatABI = getARMFloatABI(D, Args, Triple);
  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else if (FloatABI == "softfp") {
    // Floating point operations are hard, but argument passing is soft.
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  // Kernel code has more strict alignment requirements.
  if (KernelOrKext) {
    if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-long-calls");
    }

    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-strict-align");

    // The kext linker doesn't know how to deal with movw/movt.
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-use-movt=0");
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting 
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float,
                    true))
    CmdArgs.push_back("-no-implicit-float");

    // llvm does not support reserving registers in general. There is support
    // for reserving r9 on ARM though (defined as a platform-specific register
    // in ARM EABI).
    if (Args.hasArg(options::OPT_ffixed_r9)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-reserve-r9");
    }
}

// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
static void getMipsCPUAndABI(const ArgList &Args,
                             const llvm::Triple &Triple,
                             StringRef &CPUName,
                             StringRef &ABIName) {
  const char *DefMips32CPU = "mips32";
  const char *DefMips64CPU = "mips64";

  if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
                               options::OPT_mcpu_EQ))
    CPUName = A->getValue();

  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
    // Convert a GNU style Mips ABI name to the name
    // accepted by LLVM Mips backend.
    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
      .Case("32", "o32")
      .Case("64", "n64")
      .Default(ABIName);
  }

  // Setup default CPU and ABI names.
  if (CPUName.empty() && ABIName.empty()) {
    switch (Triple.getArch()) {
    default:
      llvm_unreachable("Unexpected triple arch name");
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
      CPUName = DefMips32CPU;
      break;
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      CPUName = DefMips64CPU;
      break;
    }
  }

  if (!ABIName.empty()) {
    // Deduce CPU name from ABI name.
    CPUName = llvm::StringSwitch<const char *>(ABIName)
      .Cases("32", "o32", "eabi", DefMips32CPU)
      .Cases("n32", "n64", "64", DefMips64CPU)
      .Default("");
  }
  else if (!CPUName.empty()) {
    // Deduce ABI name from CPU name.
    ABIName = llvm::StringSwitch<const char *>(CPUName)
      .Cases("mips32", "mips32r2", "o32")
      .Cases("mips64", "mips64r2", "n64")
      .Default("");
  }

  // FIXME: Warn on inconsistent cpu and abi usage.
}

// Convert ABI name to the GNU tools acceptable variant.
static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
  return llvm::StringSwitch<llvm::StringRef>(ABI)
    .Case("o32", "32")
    .Case("n64", "64")
    .Default(ABI);
}

// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        FloatABI = "hard";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "hard", because it's a default value used by gcc.
    // When we start to recognize specific target MIPS processors,
    // we will be able to select the default more correctly.
    FloatABI = "hard";
  }

  return FloatABI;
}

static void AddTargetFeature(const ArgList &Args,
                             std::vector<const char *> &Features,
                             OptSpecifier OnOpt, OptSpecifier OffOpt,
                             StringRef FeatureName) {
  if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
    if (A->getOption().matches(OnOpt))
      Features.push_back(Args.MakeArgString("+" + FeatureName));
    else
      Features.push_back(Args.MakeArgString("-" + FeatureName));
  }
}

static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
                                  std::vector<const char *> &Features) {
  StringRef FloatABI = getMipsFloatABI(D, Args);
  bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;
  if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
    // FIXME: Note, this is a hack. We need to pass the selected float
    // mode to the MipsTargetInfoBase to define appropriate macros there.
    // Now it is the only method.
    Features.push_back("+soft-float");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
    if (StringRef(A->getValue()) == "2008")
      Features.push_back("+nan2008");
  }

  AddTargetFeature(Args, Features, options::OPT_msingle_float,
                   options::OPT_mdouble_float, "single-float");
  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
                   "mips16");
  AddTargetFeature(Args, Features, options::OPT_mmicromips,
                   options::OPT_mno_micromips, "micromips");
  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
                   "dsp");
  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
                   "dspr2");
  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
                   "msa");
  AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32,
                   "fp64");
}

void Clang::AddMIPSTargetArgs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();
  StringRef CPUName;
  StringRef ABIName;
  const llvm::Triple &Triple = getToolChain().getTriple();
  getMipsCPUAndABI(Args, Triple, CPUName, ABIName);

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName.data());

  StringRef FloatABI = getMipsFloatABI(D, Args);

  bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;

  if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");

    if (FloatABI == "hard" && IsMips16) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mips16-hard-float");
    }
  }
  else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
    if (A->getOption().matches(options::OPT_mxgot)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mxgot");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
                               options::OPT_mno_ldc1_sdc1)) {
    if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-ldc1-sdc1");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
                               options::OPT_mno_check_zero_division)) {
    if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-check-zero-division");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_G)) {
    StringRef v = A->getValue();
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v));
    A->claim();
  }
}

/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
static std::string getPPCTargetCPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPUName = A->getValue();

    if (CPUName == "native") {
      std::string CPU = llvm::sys::getHostCPUName();
      if (!CPU.empty() && CPU != "generic")
        return CPU;
      else
        return "";
    }

    return llvm::StringSwitch<const char *>(CPUName)
      .Case("common", "generic")
      .Case("440", "440")
      .Case("440fp", "440")
      .Case("450", "450")
      .Case("601", "601")
      .Case("602", "602")
      .Case("603", "603")
      .Case("603e", "603e")
      .Case("603ev", "603ev")
      .Case("604", "604")
      .Case("604e", "604e")
      .Case("620", "620")
      .Case("630", "pwr3")
      .Case("G3", "g3")
      .Case("7400", "7400")
      .Case("G4", "g4")
      .Case("7450", "7450")
      .Case("G4+", "g4+")
      .Case("750", "750")
      .Case("970", "970")
      .Case("G5", "g5")
      .Case("a2", "a2")
      .Case("a2q", "a2q")
      .Case("e500mc", "e500mc")
      .Case("e5500", "e5500")
      .Case("power3", "pwr3")
      .Case("power4", "pwr4")
      .Case("power5", "pwr5")
      .Case("power5x", "pwr5x")
      .Case("power6", "pwr6")
      .Case("power6x", "pwr6x")
      .Case("power7", "pwr7")
      .Case("pwr3", "pwr3")
      .Case("pwr4", "pwr4")
      .Case("pwr5", "pwr5")
      .Case("pwr5x", "pwr5x")
      .Case("pwr6", "pwr6")
      .Case("pwr6x", "pwr6x")
      .Case("pwr7", "pwr7")
      .Case("powerpc", "ppc")
      .Case("powerpc64", "ppc64")
      .Case("powerpc64le", "ppc64le")
      .Default("");
  }

  return "";
}

static void getPPCTargetFeatures(const ArgList &Args,
                                 std::vector<const char *> &Features) {
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
    // pass the correct option to the backend while calling the frontend
    // option the same.
    // TODO: Change the LLVM backend option maybe?
    if (Name == "mfcrf")
      Name = "mfocrf";

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }

  // Altivec is a bit weird, allow overriding of the Altivec feature here.
  AddTargetFeature(Args, Features, options::OPT_faltivec,
                   options::OPT_fno_altivec, "altivec");
}

/// Get the (LLVM) name of the R600 gpu we are targeting.
static std::string getR600TargetGPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    const char *GPUName = A->getValue();
    return llvm::StringSwitch<const char *>(GPUName)
      .Cases("rv630", "rv635", "r600")
      .Cases("rv610", "rv620", "rs780", "rs880")
      .Case("rv740", "rv770")
      .Case("palm", "cedar")
      .Cases("sumo", "sumo2", "sumo")
      .Case("hemlock", "cypress")
      .Case("aruba", "cayman")
      .Default(GPUName);
  }
  return "";
}

static void getSparcTargetFeatures(const ArgList &Args,
                                   std::vector<const char *> Features) {
  bool SoftFloatABI = true;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_mhard_float))
      SoftFloatABI = false;
  }
  if (SoftFloatABI)
    Features.push_back("+soft-float");
}

void Clang::AddSparcTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // Select the float ABI as determined by -msoft-float, -mhard-float, and
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "soft", but warn the user we are guessing.
    FloatABI = "soft";
    D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
  }

  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
  } else {
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mhard-float");
  }
}

static const char *getSystemZTargetCPU(const ArgList &Args) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
    return A->getValue();
  return "z10";
}

static const char *getX86TargetCPU(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    if (StringRef(A->getValue()) != "native") {
      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
        return "core-avx2";

      return A->getValue();
    }

    // FIXME: Reject attempts to use -march=native unless the target matches
    // the host.
    //
    // FIXME: We should also incorporate the detected target features for use
    // with -native.
    std::string CPU = llvm::sys::getHostCPUName();
    if (!CPU.empty() && CPU != "generic")
      return Args.MakeArgString(CPU);
  }

  // Select the default CPU if none was given (or detection failed).

  if (Triple.getArch() != llvm::Triple::x86_64 &&
      Triple.getArch() != llvm::Triple::x86)
    return 0; // This routine is only handling x86 targets.

  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;

  // FIXME: Need target hooks.
  if (Triple.isOSDarwin()) {
    if (Triple.getArchName() == "x86_64h")
      return "core-avx2";
    return Is64Bit ? "core2" : "yonah";
  }

  // All x86 devices running Android have core2 as their common
  // denominator. This makes a better choice than pentium4.
  if (Triple.getEnvironment() == llvm::Triple::Android)
    return "core2";

  // Everything else goes to x86-64 in 64-bit mode.
  if (Is64Bit)
    return "x86-64";

  switch (Triple.getOS()) {
  case llvm::Triple::FreeBSD:
  case llvm::Triple::NetBSD:
  case llvm::Triple::OpenBSD:
    return "i486";
  case llvm::Triple::Haiku:
    return "i586";
  case llvm::Triple::Bitrig:
    return "i686";
  default:
    // Fallback to p4.
    return "pentium4";
  }
}

static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
  switch(T.getArch()) {
  default:
    return "";

  case llvm::Triple::aarch64:
    return getAArch64TargetCPU(Args, T);

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    return getARMTargetCPU(Args, T);

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, T, CPUName, ABIName);
    return CPUName;
  }

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le: {
    std::string TargetCPUName = getPPCTargetCPU(Args);
    // LLVM may default to generating code for the native CPU,
    // but, like gcc, we default to a more generic option for
    // each architecture. (except on Darwin)
    if (TargetCPUName.empty() && !T.isOSDarwin()) {
      if (T.getArch() == llvm::Triple::ppc64)
        TargetCPUName = "ppc64";
      else if (T.getArch() == llvm::Triple::ppc64le)
        TargetCPUName = "ppc64le";
      else
        TargetCPUName = "ppc";
    }
    return TargetCPUName;
  }

  case llvm::Triple::sparc:
    if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
      return A->getValue();
    return "";

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    return getX86TargetCPU(Args, T);

  case llvm::Triple::hexagon:
    return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();

  case llvm::Triple::systemz:
    return getSystemZTargetCPU(Args);

  case llvm::Triple::r600:
    return getR600TargetGPU(Args);
  }
}

static void getX86TargetFeatures(const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features) {
  if (Triple.getArchName() == "x86_64h") {
    // x86_64h implies quite a few of the more modern subtarget features
    // for Haswell class CPUs, but not all of them. Opt-out of a few.
    Features.push_back("-rdrnd");
    Features.push_back("-aes");
    Features.push_back("-pclmul");
    Features.push_back("-rtm");
    Features.push_back("-hle");
    Features.push_back("-fsgsbase");
  }

  // Now add any that the user explicitly requested on the command line,
  // which may override the defaults.
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }
}

void Clang::AddX86TargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  if (!Args.hasFlag(options::OPT_mred_zone,
                    options::OPT_mno_red_zone,
                    true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  // Default to avoid implicit floating-point for kernel/kext code, but allow
  // that to be overridden with -mno-soft-float.
  bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
                          Args.hasArg(options::OPT_fapple_kext));
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mno_soft_float,
                               options::OPT_mimplicit_float,
                               options::OPT_mno_implicit_float)) {
    const Option &O = A->getOption();
    NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
                       O.matches(options::OPT_msoft_float));
  }
  if (NoImplicitFloat)
    CmdArgs.push_back("-no-implicit-float");
}

static inline bool HasPICArg(const ArgList &Args) {
  return Args.hasArg(options::OPT_fPIC)
    || Args.hasArg(options::OPT_fpic);
}

static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) {
  return Args.getLastArg(options::OPT_G,
                         options::OPT_G_EQ,
                         options::OPT_msmall_data_threshold_EQ);
}

static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
  std::string value;
  if (HasPICArg(Args))
    value = "0";
  else if (Arg *A = GetLastSmallDataThresholdArg(Args)) {
    value = A->getValue();
    A->claim();
  }
  return value;
}

void Clang::AddHexagonTargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-fno-signed-char");
  CmdArgs.push_back("-mqdsp6-compat");
  CmdArgs.push_back("-Wreturn-type");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back(Args.MakeArgString(
                        "-hexagon-small-data-threshold=" + SmallDataThreshold));
  }

  if (!Args.hasArg(options::OPT_fno_short_enums))
    CmdArgs.push_back("-fshort-enums");
  if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
  }
  CmdArgs.push_back ("-mllvm");
  CmdArgs.push_back ("-machine-sink-split=0");
}

static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
                                     std::vector<const char *> &Features) {
  // Honor -mfpu=.
  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
    getAArch64FPUFeatures(D, A, Args, Features);
}

static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args, ArgStringList &CmdArgs) {
  std::vector<const char *> Features;
  switch (Triple.getArch()) {
  default:
    break;
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    getMIPSTargetFeatures(D, Args, Features);
    break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    getARMTargetFeatures(D, Triple, Args, Features);
    break;

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    getPPCTargetFeatures(Args, Features);
    break;
  case llvm::Triple::sparc:
    getSparcTargetFeatures(Args, Features);
    break;
  case llvm::Triple::aarch64:
    getAArch64TargetFeatures(D, Args, Features);
    break;
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    getX86TargetFeatures(Triple, Args, Features);
    break;
  }

  // Find the last of each feature.
  llvm::StringMap<unsigned> LastOpt;
  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    const char *Name = Features[I];
    assert(Name[0] == '-' || Name[0] == '+');
    LastOpt[Name + 1] = I;
  }

  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    // If this feature was overridden, ignore it.
    const char *Name = Features[I];
    llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
    assert(LastI != LastOpt.end());
    unsigned Last = LastI->second;
    if (Last != I)
      continue;

    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back(Name);
  }
}

static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
                                          const llvm::Triple &Triple) {
  // We use the zero-cost exception tables for Objective-C if the non-fragile
  // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
  // later.
  if (runtime.isNonFragile())
    return true;

  if (!Triple.isOSDarwin())
    return false;

  return (!Triple.isMacOSXVersionLT(10,5) &&
          (Triple.getArch() == llvm::Triple::x86_64 ||
           Triple.getArch() == llvm::Triple::arm));
}

/// addExceptionArgs - Adds exception related arguments to the driver command
/// arguments. There's a master flag, -fexceptions and also language specific
/// flags to enable/disable C++ and Objective-C exceptions.
/// This makes it possible to for example disable C++ exceptions but enable
/// Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
                             const llvm::Triple &Triple,
                             bool KernelOrKext,
                             const ObjCRuntime &objcRuntime,
                             ArgStringList &CmdArgs) {
  if (KernelOrKext) {
    // -mkernel and -fapple-kext imply no exceptions, so claim exception related
    // arguments now to avoid warnings about unused arguments.
    Args.ClaimAllArgs(options::OPT_fexceptions);
    Args.ClaimAllArgs(options::OPT_fno_exceptions);
    Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
    Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
    return;
  }

  // Exceptions are enabled by default.
  bool ExceptionsEnabled = true;

  // This keeps track of whether exceptions were explicitly turned on or off.
  bool DidHaveExplicitExceptionFlag = false;

  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
                               options::OPT_fno_exceptions)) {
    if (A->getOption().matches(options::OPT_fexceptions))
      ExceptionsEnabled = true;
    else
      ExceptionsEnabled = false;

    DidHaveExplicitExceptionFlag = true;
  }

  bool ShouldUseExceptionTables = false;

  // Exception tables and cleanups can be enabled with -fexceptions even if the
  // language itself doesn't support exceptions.
  if (ExceptionsEnabled && DidHaveExplicitExceptionFlag)
    ShouldUseExceptionTables = true;

  // Obj-C exceptions are enabled by default, regardless of -fexceptions. This
  // is not necessarily sensible, but follows GCC.
  if (types::isObjC(InputType) &&
      Args.hasFlag(options::OPT_fobjc_exceptions,
                   options::OPT_fno_objc_exceptions,
                   true)) {
    CmdArgs.push_back("-fobjc-exceptions");

    ShouldUseExceptionTables |=
      shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
  }

  if (types::isCXX(InputType)) {
    bool CXXExceptionsEnabled = ExceptionsEnabled;

    if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
                                 options::OPT_fno_cxx_exceptions,
                                 options::OPT_fexceptions,
                                 options::OPT_fno_exceptions)) {
      if (A->getOption().matches(options::OPT_fcxx_exceptions))
        CXXExceptionsEnabled = true;
      else if (A->getOption().matches(options::OPT_fno_cxx_exceptions))
        CXXExceptionsEnabled = false;
    }

    if (CXXExceptionsEnabled) {
      CmdArgs.push_back("-fcxx-exceptions");

      ShouldUseExceptionTables = true;
    }
  }

  if (ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");
}

static bool ShouldDisableAutolink(const ArgList &Args,
                             const ToolChain &TC) {
  bool Default = true;
  if (TC.getTriple().isOSDarwin()) {
    // The native darwin assembler doesn't support the linker_option directives,
    // so we disable them if we think the .s file will be passed to it.
    Default = TC.useIntegratedAs();
  }
  return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
                       Default);
}

static bool ShouldDisableCFI(const ArgList &Args,
                             const ToolChain &TC) {
  bool Default = true;
  if (TC.getTriple().isOSDarwin()) {
    // The native darwin assembler doesn't support cfi directives, so
    // we disable them if we think the .s file will be passed to it.
    Default = TC.useIntegratedAs();
  }
  return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
                       options::OPT_fno_dwarf2_cfi_asm,
                       Default);
}

static bool ShouldDisableDwarfDirectory(const ArgList &Args,
                                        const ToolChain &TC) {
  bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
                                        options::OPT_fno_dwarf_directory_asm,
                                        TC.useIntegratedAs());
  return !UseDwarfDirectory;
}

/// \brief Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
  if (isa<CompileJobAction>(A))
    return true;

  for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
    if (ContainsCompileAction(*it))
      return true;

  return false;
}

/// \brief Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
  bool RelaxDefault = true;

  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    RelaxDefault = A->getOption().matches(options::OPT_O0);

  if (RelaxDefault) {
    RelaxDefault = false;
    for (ActionList::const_iterator it = C.getActions().begin(),
           ie = C.getActions().end(); it != ie; ++it) {
      if (ContainsCompileAction(*it)) {
        RelaxDefault = true;
        break;
      }
    }
  }

  return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
    RelaxDefault);
}

static void CollectArgsForIntegratedAssembler(Compilation &C,
                                              const ArgList &Args,
                                              ArgStringList &CmdArgs,
                                              const Driver &D) {
    if (UseRelaxAll(C, Args))
      CmdArgs.push_back("-mrelax-all");

    // When passing -I arguments to the assembler we sometimes need to
    // unconditionally take the next argument.  For example, when parsing
    // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
    // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
    // arg after parsing the '-I' arg.
    bool TakeNextArg = false;

    // When using an integrated assembler, translate -Wa, and -Xassembler
    // options.
    for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
                                               options::OPT_Xassembler),
           ie = Args.filtered_end(); it != ie; ++it) {
      const Arg *A = *it;
      A->claim();

      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
        StringRef Value = A->getValue(i);
        if (TakeNextArg) {
          CmdArgs.push_back(Value.data());
          TakeNextArg = false;
          continue;
        }

        if (Value == "-force_cpusubtype_ALL") {
          // Do nothing, this is the default and we don't support anything else.
        } else if (Value == "-L") {
          CmdArgs.push_back("-msave-temp-labels");
        } else if (Value == "--fatal-warnings") {
          CmdArgs.push_back("-mllvm");
          CmdArgs.push_back("-fatal-assembler-warnings");
        } else if (Value == "--noexecstack") {
          CmdArgs.push_back("-mnoexecstack");
        } else if (Value.startswith("-I")) {
          CmdArgs.push_back(Value.data());
          // We need to consume the next argument if the current arg is a plain
          // -I. The next arg will be the include directory.
          if (Value == "-I")
            TakeNextArg = true;
        } else {
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
        }
      }
    }
}

static void addProfileRTLinux(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
        Args.hasArg(options::OPT_fprofile_generate) ||
        Args.hasArg(options::OPT_fcreate_profile) ||
        Args.hasArg(options::OPT_coverage)))
    return;

  // The profile runtime is located in the Linux library directory and has name
  // "libclang_rt.profile-<ArchName>.a".
  SmallString<128> LibProfile(TC.getDriver().ResourceDir);
  llvm::sys::path::append(
      LibProfile, "lib", "linux",
      Twine("libclang_rt.profile-") + TC.getArchName() + ".a");

  CmdArgs.push_back(Args.MakeArgString(LibProfile));
}

static void addSanitizerRTLinkFlagsLinux(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
    const StringRef Sanitizer, bool BeforeLibStdCXX,
    bool ExportSymbols = true) {
  // Sanitizer runtime is located in the Linux library directory and
  // has name "libclang_rt.<Sanitizer>-<ArchName>.a".
  SmallString<128> LibSanitizer(TC.getDriver().ResourceDir);
  llvm::sys::path::append(
      LibSanitizer, "lib", "linux",
      (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a"));

  // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
  // etc.) so that the linker picks custom versions of the global 'operator
  // new' and 'operator delete' symbols. We take the extreme (but simple)
  // strategy of inserting it at the front of the link command. It also
  // needs to be forced to end up in the executable, so wrap it in
  // whole-archive.
  SmallVector<const char *, 3> LibSanitizerArgs;
  LibSanitizerArgs.push_back("-whole-archive");
  LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
  LibSanitizerArgs.push_back("-no-whole-archive");

  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());

  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-ldl");
  CmdArgs.push_back("-lm");

  // If possible, use a dynamic symbols file to export the symbols from the
  // runtime library. If we can't do so, use -export-dynamic instead to export
  // all symbols from the binary.
  if (ExportSymbols) {
    if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
      CmdArgs.push_back(
          Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
    else
      CmdArgs.push_back("-export-dynamic");
  }
}

/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (TC.getTriple().getEnvironment() == llvm::Triple::Android) {
    SmallString<128> LibAsan(TC.getDriver().ResourceDir);
    llvm::sys::path::append(LibAsan, "lib", "linux",
        (Twine("libclang_rt.asan-") +
            TC.getArchName() + "-android.so"));
    CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
  } else {
    if (!Args.hasArg(options::OPT_shared))
      addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
  }
}

/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
}

/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
}

/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addLsanRTLinux(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true);
}

/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
                            ArgStringList &CmdArgs, bool IsCXX,
                            bool HasOtherSanitizerRt) {
  // Need a copy of sanitizer_common. This could come from another sanitizer
  // runtime; if we're not including one, include our own copy.
  if (!HasOtherSanitizerRt)
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false);

  addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false);

  // Only include the bits of the runtime which need a C++ ABI library if
  // we're linking in C++ mode.
  if (IsCXX)
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
}

static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args,
                            ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true);
}

static bool shouldUseFramePointerForTarget(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  // Don't use a frame pointer on linux if optimizing for certain targets.
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::systemz:
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    if (Triple.isOSLinux())
      if (Arg *A = Args.getLastArg(options::OPT_O_Group))
        if (!A->getOption().matches(options::OPT_O0))
          return false;
    return true;
  case llvm::Triple::xcore:
    return false;
  default:
    return true;
  }
}

static bool shouldUseFramePointer(const ArgList &Args,
                                  const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
                               options::OPT_fomit_frame_pointer))
    return A->getOption().matches(options::OPT_fno_omit_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

static bool shouldUseLeafFramePointer(const ArgList &Args,
                                      const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
                               options::OPT_momit_leaf_frame_pointer))
    return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> cwd;
  if (!llvm::sys::fs::current_path(cwd)) {
    CmdArgs.push_back("-fdebug-compilation-dir");
    CmdArgs.push_back(Args.MakeArgString(cwd));
  }
}

static const char *SplitDebugName(const ArgList &Args,
                                  const InputInfoList &Inputs) {
  Arg *FinalOutput = Args.getLastArg(options::OPT_o);
  if (FinalOutput && Args.hasArg(options::OPT_c)) {
    SmallString<128> T(FinalOutput->getValue());
    llvm::sys::path::replace_extension(T, "dwo");
    return Args.MakeArgString(T);
  } else {
    // Use the compilation dir.
    SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
    SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
    llvm::sys::path::replace_extension(F, "dwo");
    T += F;
    return Args.MakeArgString(F);
  }
}

static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
                           const Tool &T, const JobAction &JA,
                           const ArgList &Args, const InputInfo &Output,
                           const char *OutFile) {
  ArgStringList ExtractArgs;
  ExtractArgs.push_back("--extract-dwo");

  ArgStringList StripArgs;
  StripArgs.push_back("--strip-dwo");

  // Grabbing the output of the earlier compile step.
  StripArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(OutFile);

  const char *Exec =
    Args.MakeArgString(TC.GetProgramPath("objcopy"));

  // First extract the dwo sections.
  C.addCommand(new Command(JA, T, Exec, ExtractArgs));

  // Then remove them from the original .o file.
  C.addCommand(new Command(JA, T, Exec, StripArgs));
}

static bool isOptimizationLevelFast(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    if (A->getOption().matches(options::OPT_Ofast))
      return true;
  return false;
}

/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      return true;

    if (A->getOption().matches(options::OPT_O0))
      return false;

    assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");

    // Vectorize -Os.
    StringRef S(A->getValue());
    if (S == "s")
      return true;

    // Don't vectorize -Oz.
    if (S == "z")
      return false;

    unsigned OptLevel = 0;
    if (S.getAsInteger(10, OptLevel))
      return false;

    return OptLevel > 1;
  }

  return false;
}

void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                         const InputInfo &Output,
                         const InputInfoList &Inputs,
                         const ArgList &Args,
                         const char *LinkingOutput) const {
  bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
                                  options::OPT_fapple_kext);
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");

  // Invoke ourselves in -cc1 mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  // Select the appropriate action.
  RewriteKind rewriteKind = RK_None;
  
  if (isa<AnalyzeJobAction>(JA)) {
    assert(JA.getType() == types::TY_Plist && "Invalid output type.");
    CmdArgs.push_back("-analyze");
  } else if (isa<MigrateJobAction>(JA)) {
    CmdArgs.push_back("-migrate");
  } else if (isa<PreprocessJobAction>(JA)) {
    if (Output.getType() == types::TY_Dependencies)
      CmdArgs.push_back("-Eonly");
    else {
      CmdArgs.push_back("-E");
      if (Args.hasArg(options::OPT_rewrite_objc) &&
          !Args.hasArg(options::OPT_g_Group))
        CmdArgs.push_back("-P");
    }
  } else if (isa<AssembleJobAction>(JA)) {
    CmdArgs.push_back("-emit-obj");

    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);

    // Also ignore explicit -force_cpusubtype_ALL option.
    (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
  } else if (isa<PrecompileJobAction>(JA)) {
    // Use PCH if the user requested it.
    bool UsePCH = D.CCCUsePCH;

    if (JA.getType() == types::TY_Nothing)
      CmdArgs.push_back("-fsyntax-only");
    else if (UsePCH)
      CmdArgs.push_back("-emit-pch");
    else
      CmdArgs.push_back("-emit-pth");
  } else {
    assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");

    if (JA.getType() == types::TY_Nothing) {
      CmdArgs.push_back("-fsyntax-only");
    } else if (JA.getType() == types::TY_LLVM_IR ||
               JA.getType() == types::TY_LTO_IR) {
      CmdArgs.push_back("-emit-llvm");
    } else if (JA.getType() == types::TY_LLVM_BC ||
               JA.getType() == types::TY_LTO_BC) {
      CmdArgs.push_back("-emit-llvm-bc");
    } else if (JA.getType() == types::TY_PP_Asm) {
      CmdArgs.push_back("-S");
    } else if (JA.getType() == types::TY_AST) {
      CmdArgs.push_back("-emit-pch");
    } else if (JA.getType() == types::TY_ModuleFile) {
      CmdArgs.push_back("-module-file-info");
    } else if (JA.getType() == types::TY_RewrittenObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_NonFragile;
    } else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_Fragile;
    } else {
      assert(JA.getType() == types::TY_PP_Asm &&
             "Unexpected output type!");
    }
  }

  // The make clang go fast button.
  CmdArgs.push_back("-disable-free");

  // Disable the verification pass in -asserts builds.
#ifdef NDEBUG
  CmdArgs.push_back("-disable-llvm-verifier");
#endif

  // Set the main file name, so that debug info works even with
  // -save-temps.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(getBaseInputName(Args, Inputs));

  // Some flags which affect the language (via preprocessor
  // defines).
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-static-define");

  if (isa<AnalyzeJobAction>(JA)) {
    // Enable region store model by default.
    CmdArgs.push_back("-analyzer-store=region");

    // Treat blocks as analysis entry points.
    CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");

    CmdArgs.push_back("-analyzer-eagerly-assume");

    // Add default argument set.
    if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
      CmdArgs.push_back("-analyzer-checker=core");

      if (getToolChain().getTriple().getOS() != llvm::Triple::Win32)
        CmdArgs.push_back("-analyzer-checker=unix");

      if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
        CmdArgs.push_back("-analyzer-checker=osx");
      
      CmdArgs.push_back("-analyzer-checker=deadcode");
      
      if (types::isCXX(Inputs[0].getType()))
        CmdArgs.push_back("-analyzer-checker=cplusplus");

      // Enable the following experimental checkers for testing. 
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");      
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
    }

    // Set the output format. The default is plist, for (lame) historical
    // reasons.
    CmdArgs.push_back("-analyzer-output");
    if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
      CmdArgs.push_back(A->getValue());
    else
      CmdArgs.push_back("plist");

    // Disable the presentation of standard compiler warnings when
    // using --analyze.  We only want to show static analyzer diagnostics
    // or frontend errors.
    CmdArgs.push_back("-w");

    // Add -Xanalyzer arguments when running as analyzer.
    Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
  }

  CheckCodeGenerationOptions(D, Args);

  bool PIE = getToolChain().isPIEDefault();
  bool PIC = PIE || getToolChain().isPICDefault();
  bool IsPICLevelTwo = PIC;

  // For the PIC and PIE flag options, this logic is different from the
  // legacy logic in very old versions of GCC, as that logic was just
  // a bug no one had ever fixed. This logic is both more rational and
  // consistent with GCC's new logic now that the bugs are fixed. The last
  // argument relating to either PIC or PIE wins, and no other argument is
  // used. If the last argument is any flavor of the '-fno-...' arguments,
  // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
  // at the same level.
  Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                 options::OPT_fpic, options::OPT_fno_pic,
                                 options::OPT_fPIE, options::OPT_fno_PIE,
                                 options::OPT_fpie, options::OPT_fno_pie);
  // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
  // is forced, then neither PIC nor PIE flags will have no effect.
  if (!getToolChain().isPICDefaultForced()) {
    if (LastPICArg) {
      Option O = LastPICArg->getOption();
      if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
          O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
        PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
        PIC = PIE || O.matches(options::OPT_fPIC) ||
              O.matches(options::OPT_fpic);
        IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
                        O.matches(options::OPT_fPIC);
      } else {
        PIE = PIC = false;
      }
    }
  }

  // Introduce a Darwin-specific hack. If the default is PIC but the flags
  // specified while enabling PIC enabled level 1 PIC, just force it back to
  // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
  // informal testing).
  if (PIC && getToolChain().getTriple().isOSDarwin())
    IsPICLevelTwo |= getToolChain().isPICDefault();

  // Note that these flags are trump-cards. Regardless of the order w.r.t. the
  // PIC or PIE options above, if these show up, PIC is disabled.
  llvm::Triple Triple(TripleStr);
  if (KernelOrKext &&
      (!Triple.isiOS() || Triple.isOSVersionLT(6)))
    PIC = PIE = false;
  if (Args.hasArg(options::OPT_static))
    PIC = PIE = false;

  if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
    // This is a very special mode. It trumps the other modes, almost no one
    // uses it, and it isn't even valid on any OS but Darwin.
    if (!getToolChain().getTriple().isOSDarwin())
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();

    // FIXME: Warn when this flag trumps some other PIC or PIE flag.

    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back("dynamic-no-pic");

    // Only a forced PIC mode can cause the actual compile to have PIC defines
    // etc., no flags are sufficient. This behavior was selected to closely
    // match that of llvm-gcc and Apple GCC before that.
    if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back("2");
    }
  } else {
    // Currently, LLVM only knows about PIC vs. static; the PIE differences are
    // handled in Clang's IRGen by the -pie-level flag.
    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back(PIC ? "pic" : "static");

    if (PIC) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      if (PIE) {
        CmdArgs.push_back("-pie-level");
        CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      }
    }
  }

  if (!Args.hasFlag(options::OPT_fmerge_all_constants,
                    options::OPT_fno_merge_all_constants))
    CmdArgs.push_back("-fno-merge-all-constants");

  // LLVM Code Generator Options.

  if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
    CmdArgs.push_back("-mregparm");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
                               options::OPT_freg_struct_return)) {
    if (getToolChain().getArch() != llvm::Triple::x86) {
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();
    } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
      CmdArgs.push_back("-fpcc-struct-return");
    } else {
      assert(A->getOption().matches(options::OPT_freg_struct_return));
      CmdArgs.push_back("-freg-struct-return");
    }
  }

  if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
    CmdArgs.push_back("-mrtd");

  if (shouldUseFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-mdisable-fp-elim");
  if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
                    options::OPT_fno_zero_initialized_in_bss))
    CmdArgs.push_back("-mno-zero-initialized-in-bss");

  bool OFastEnabled = isOptimizationLevelFast(Args);
  // If -Ofast is the optimization level, then -fstrict-aliasing should be
  // enabled.  This alias option is being used to simplify the hasFlag logic.
  OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_fstrict_aliasing;
  if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
                    options::OPT_fno_strict_aliasing, true))
    CmdArgs.push_back("-relaxed-aliasing");
  if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
                    options::OPT_fno_struct_path_tbaa))
    CmdArgs.push_back("-no-struct-path-tbaa");
  if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
                   false))
    CmdArgs.push_back("-fstrict-enums");
  if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
                    options::OPT_fno_optimize_sibling_calls))
    CmdArgs.push_back("-mdisable-tail-calls");

  // Handle segmented stacks.
  if (Args.hasArg(options::OPT_fsplit_stack))
    CmdArgs.push_back("-split-stacks");

  // If -Ofast is the optimization level, then -ffast-math should be enabled.
  // This alias option is being used to simplify the getLastArg logic.
  OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_ffast_math;
  
  // Handle various floating point optimization flags, mapping them to the
  // appropriate LLVM code generation flags. The pattern for all of these is to
  // default off the codegen optimizations, and if any flag enables them and no
  // flag disables them after the flag enabling them, enable the codegen
  // optimization. This is complicated by several "umbrella" flags.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_infinities,
                               options::OPT_fno_honor_infinities))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_infinities)
      CmdArgs.push_back("-menable-no-infs");
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_nans,
                               options::OPT_fno_honor_nans))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_nans)
      CmdArgs.push_back("-menable-no-nans");

  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
  bool MathErrno = getToolChain().IsMathErrnoDefault();
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_fmath_errno,
                               options::OPT_fno_math_errno)) {
    // Turning on -ffast_math (with either flag) removes the need for MathErrno.
    // However, turning *off* -ffast_math merely restores the toolchain default
    // (which may be false).
    if (A->getOption().getID() == options::OPT_fno_math_errno ||
        A->getOption().getID() == options::OPT_ffast_math ||
        A->getOption().getID() == options::OPT_Ofast)
      MathErrno = false;
    else if (A->getOption().getID() == options::OPT_fmath_errno)
      MathErrno = true;
  }
  if (MathErrno)
    CmdArgs.push_back("-fmath-errno");

  // There are several flags which require disabling very specific
  // optimizations. Any of these being disabled forces us to turn off the
  // entire set of LLVM optimizations, so collect them through all the flag
  // madness.
  bool AssociativeMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fassociative_math,
                               options::OPT_fno_associative_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_associative_math)
      AssociativeMath = true;
  bool ReciprocalMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_freciprocal_math,
                               options::OPT_fno_reciprocal_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_reciprocal_math)
      ReciprocalMath = true;
  bool SignedZeros = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fsigned_zeros,
                               options::OPT_fno_signed_zeros))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fsigned_zeros)
      SignedZeros = false;
  bool TrappingMath = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_ftrapping_math,
                               options::OPT_fno_trapping_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_ftrapping_math)
      TrappingMath = false;
  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
      !TrappingMath)
    CmdArgs.push_back("-menable-unsafe-fp-math");


  // Validate and pass through -fp-contract option. 
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffp_contract)) {
    if (A->getOption().getID() == options::OPT_ffp_contract) {
      StringRef Val = A->getValue();
      if (Val == "fast" || Val == "on" || Val == "off") {
        CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
      }
    } else if (A->getOption().matches(options::OPT_ffast_math) ||
               (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
      // If fast-math is set then set the fp-contract mode to fast.
      CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
    }
  }

  // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
  // and if we find them, tell the frontend to provide the appropriate
  // preprocessor macros. This is distinct from enabling any optimizations as
  // these options induce language changes which must survive serialization
  // and deserialization, etc.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math))
      if (!A->getOption().matches(options::OPT_fno_fast_math))
        CmdArgs.push_back("-ffast-math");
  if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math))
    if (A->getOption().matches(options::OPT_ffinite_math_only))
      CmdArgs.push_back("-ffinite-math-only");

  // Decide whether to use verbose asm. Verbose assembly is the default on
  // toolchains which have the integrated assembler on by default.
  bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault();
  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   IsVerboseAsmDefault) ||
      Args.hasArg(options::OPT_dA))
    CmdArgs.push_back("-masm-verbose");

  if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Structure");
  }
  if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Arguments");
  }

  // Enable -mconstructor-aliases except on darwin, where we have to
  // work around a linker bug;  see <rdar://problem/7651567>.
  if (!getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-mconstructor-aliases");

  // Darwin's kernel doesn't support guard variables; just die if we
  // try to use them.
  if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-fforbid-guard-variables");

  if (Args.hasArg(options::OPT_mms_bitfields)) {
    CmdArgs.push_back("-mms-bitfields");
  }

  // This is a coarse approximation of what llvm-gcc actually does, both
  // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
  // complicated ways.
  bool AsynchronousUnwindTables =
    Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
                 options::OPT_fno_asynchronous_unwind_tables,
                 getToolChain().IsUnwindTablesDefault() &&
                 !KernelOrKext);
  if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
                   AsynchronousUnwindTables))
    CmdArgs.push_back("-munwind-tables");

  getToolChain().addClangTargetOptions(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
    CmdArgs.push_back("-mlimit-float-precision");
    CmdArgs.push_back(A->getValue());
  }

  // FIXME: Handle -mtune=.
  (void) Args.hasArg(options::OPT_mtune_EQ);

  if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
    CmdArgs.push_back("-mcode-model");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target cpu
  std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple ETriple(ETripleStr);
  std::string CPU = getCPUName(Args, ETriple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
    CmdArgs.push_back("-mfpmath");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target features
  getTargetFeatures(D, ETriple, Args, CmdArgs);

  // Add target specific flags.
  switch(getToolChain().getArch()) {
  default:
    break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
    break;

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    AddMIPSTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::sparc:
    AddSparcTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    AddX86TargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::hexagon:
    AddHexagonTargetArgs(Args, CmdArgs);
    break;
  }

  // Add clang-cl arguments.
  if (getToolChain().getDriver().IsCLMode())
    AddClangCLArgs(Args, CmdArgs);

  // 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());
  }

  if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-momit-leaf-frame-pointer");

  // Explicitly error on some things we know we don't support and can't just
  // ignore.
  types::ID InputType = Inputs[0].getType();
  if (!Args.hasArg(options::OPT_fallow_unsupported)) {
    Arg *Unsupported;
    if (types::isCXX(InputType) &&
        getToolChain().getTriple().isOSDarwin() &&
        getToolChain().getArch() == llvm::Triple::x86) {
      if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
          (Unsupported = Args.getLastArg(options::OPT_mkernel)))
        D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
          << Unsupported->getOption().getName();
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_v);
  Args.AddLastArg(CmdArgs, options::OPT_H);
  if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-header-include-file");
    CmdArgs.push_back(D.CCPrintHeadersFilename ?
                      D.CCPrintHeadersFilename : "-");
  }
  Args.AddLastArg(CmdArgs, options::OPT_P);
  Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);

  if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-diagnostic-log-file");
    CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
                      D.CCLogDiagnosticsFilename : "-");
  }

  // Use the last option from "-g" group. "-gline-tables-only"
  // is preserved, all other debug options are substituted with "-g".
  Args.ClaimAllArgs(options::OPT_g_Group);
  if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    if (A->getOption().matches(options::OPT_gline_tables_only))
      CmdArgs.push_back("-gline-tables-only");
    else if (A->getOption().matches(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    else if (A->getOption().matches(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    else if (A->getOption().matches(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");
    else if (!A->getOption().matches(options::OPT_g0) &&
             !A->getOption().matches(options::OPT_ggdb0)) {
      // Default is dwarf-2 for darwin.
      if (getToolChain().getTriple().isOSDarwin())
        CmdArgs.push_back("-gdwarf-2");
      else
        CmdArgs.push_back("-g");
    }
  }

  // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
  Args.ClaimAllArgs(options::OPT_g_flags_Group);
  if (Args.hasArg(options::OPT_gcolumn_info))
    CmdArgs.push_back("-dwarf-column-info");

  // FIXME: Move backend command line options to the module.
  // -gsplit-dwarf should turn on -g and enable the backend dwarf
  // splitting and extraction.
  // FIXME: Currently only works on Linux.
  if (getToolChain().getTriple().isOSLinux() &&
      Args.hasArg(options::OPT_gsplit_dwarf)) {
    CmdArgs.push_back("-g");
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-split-dwarf=Enable");
  }

  // -ggnu-pubnames turns on gnu style pubnames in the backend.
  if (Args.hasArg(options::OPT_ggnu_pubnames)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
  }

  Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section);

  Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
  Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);

  Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);

  if (Args.hasArg(options::OPT_ftest_coverage) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-notes");
  if (Args.hasArg(options::OPT_fprofile_arcs) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-data");

  if (C.getArgs().hasArg(options::OPT_c) ||
      C.getArgs().hasArg(options::OPT_S)) {
    if (Output.isFilename()) {
      CmdArgs.push_back("-coverage-file");
      SmallString<128> CoverageFilename(Output.getFilename());
      if (llvm::sys::path::is_relative(CoverageFilename.str())) {
        SmallString<128> Pwd;
        if (!llvm::sys::fs::current_path(Pwd)) {
          llvm::sys::path::append(Pwd, CoverageFilename.str());
          CoverageFilename.swap(Pwd);
        }
      }
      CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
    }
  }

  // Pass options for controlling the default header search paths.
  if (Args.hasArg(options::OPT_nostdinc)) {
    CmdArgs.push_back("-nostdsysteminc");
    CmdArgs.push_back("-nobuiltininc");
  } else {
    if (Args.hasArg(options::OPT_nostdlibinc))
        CmdArgs.push_back("-nostdsysteminc");
    Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
    Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
  }

  // Pass the path to compiler resource files.
  CmdArgs.push_back("-resource-dir");
  CmdArgs.push_back(D.ResourceDir.c_str());

  Args.AddLastArg(CmdArgs, options::OPT_working_directory);

  bool ARCMTEnabled = false;
  if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
    if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
                                       options::OPT_ccc_arcmt_modify,
                                       options::OPT_ccc_arcmt_migrate)) {
      ARCMTEnabled = true;
      switch (A->getOption().getID()) {
      default:
        llvm_unreachable("missed a case");
      case options::OPT_ccc_arcmt_check:
        CmdArgs.push_back("-arcmt-check");
        break;
      case options::OPT_ccc_arcmt_modify:
        CmdArgs.push_back("-arcmt-modify");
        break;
      case options::OPT_ccc_arcmt_migrate:
        CmdArgs.push_back("-arcmt-migrate");
        CmdArgs.push_back("-mt-migrate-directory");
        CmdArgs.push_back(A->getValue());

        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
        break;
      }
    }
  } else {
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
  }

  if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
    if (ARCMTEnabled) {
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-ccc-arcmt-migrate";
    }
    CmdArgs.push_back("-mt-migrate-directory");
    CmdArgs.push_back(A->getValue());

    if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
                     options::OPT_objcmt_migrate_subscripting,
                     options::OPT_objcmt_migrate_property)) {
      // None specified, means enable them all.
      CmdArgs.push_back("-objcmt-migrate-literals");
      CmdArgs.push_back("-objcmt-migrate-subscripting");
      CmdArgs.push_back("-objcmt-migrate-property");
    } else {
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    }
  } else {
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_white_list_dir_path);
  }

  // Add preprocessing options like -I, -D, etc. if we are using the
  // preprocessor.
  //
  // FIXME: Support -fpreprocessed
  if (types::getPreprocessedType(InputType) != types::TY_INVALID)
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);

  // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
  // that "The compiler can only warn and ignore the option if not recognized".
  // When building with ccache, it will pass -D options to clang even on
  // preprocessed inputs and configure concludes that -fPIC is not supported.
  Args.ClaimAllArgs(options::OPT_D);

  // Manually translate -O4 to -O3; let clang reject others.
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4)) {
      CmdArgs.push_back("-O3");
      D.Diag(diag::warn_O4_is_O3);
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Don't warn about unused -flto.  This can happen when we're preprocessing or
  // precompiling.
  Args.ClaimAllArgs(options::OPT_flto);

  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
  if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
    CmdArgs.push_back("-pedantic");
  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
  Args.AddLastArg(CmdArgs, options::OPT_w);

  // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
  // (-ansi is equivalent to -std=c89 or -std=c++98).
  //
  // If a std is supplied, only add -trigraphs if it follows the
  // option.
  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
    if (Std->getOption().matches(options::OPT_ansi))
      if (types::isCXX(InputType))
        CmdArgs.push_back("-std=c++98");
      else
        CmdArgs.push_back("-std=c89");
    else
      Std->render(Args, CmdArgs);

    if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
                                 options::OPT_trigraphs))
      if (A != Std)
        A->render(Args, CmdArgs);
  } else {
    // Honor -std-default.
    //
    // FIXME: Clang doesn't correctly handle -std= when the input language
    // doesn't match. For the time being just ignore this for C++ inputs;
    // eventually we want to do all the standard defaulting here instead of
    // splitting it between the driver and clang -cc1.
    if (!types::isCXX(InputType))
      Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
                                "-std=", /*Joined=*/true);
    else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32)
      CmdArgs.push_back("-std=c++11");

    Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
  }

  // GCC's behavior for -Wwrite-strings is a bit strange:
  //  * In C, this "warning flag" changes the types of string literals from
  //    'char[N]' to 'const char[N]', and thus triggers an unrelated warning
  //    for the discarded qualifier.
  //  * In C++, this is just a normal warning flag.
  //
  // Implementing this warning correctly in C is hard, so we follow GCC's
  // behavior for now. FIXME: Directly diagnose uses of a string literal as
  // a non-const char* in C, rather than using this crude hack.
  if (!types::isCXX(InputType)) {
    DiagnosticsEngine::Level DiagLevel = D.getDiags().getDiagnosticLevel(
        diag::warn_deprecated_string_literal_conversion_c, SourceLocation());
    if (DiagLevel > DiagnosticsEngine::Ignored)
      CmdArgs.push_back("-fconst-strings");
  }

  // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
  // during C++ compilation, which it is by default. GCC keeps this define even
  // in the presence of '-w', match this behavior bug-for-bug.
  if (types::isCXX(InputType) &&
      Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated,
                   true)) {
    CmdArgs.push_back("-fdeprecated-macro");
  }

  // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
  if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
    if (Asm->getOption().matches(options::OPT_fasm))
      CmdArgs.push_back("-fgnu-keywords");
    else
      CmdArgs.push_back("-fno-gnu-keywords");
  }

  if (ShouldDisableCFI(Args, getToolChain()))
    CmdArgs.push_back("-fno-dwarf2-cfi-asm");

  if (ShouldDisableDwarfDirectory(Args, getToolChain()))
    CmdArgs.push_back("-fno-dwarf-directory-asm");

  if (ShouldDisableAutolink(Args, getToolChain()))
    CmdArgs.push_back("-fno-autolink");

  // Add in -fdebug-compilation-dir if necessary.
  addDebugCompDirArg(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
                               options::OPT_ftemplate_depth_EQ)) {
    CmdArgs.push_back("-ftemplate-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
    CmdArgs.push_back("-foperator-arrow-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
    CmdArgs.push_back("-fconstexpr-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
    CmdArgs.push_back("-fconstexpr-steps");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
    CmdArgs.push_back("-fbracket-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
                               options::OPT_Wlarge_by_value_copy_def)) {
    if (A->getNumValues()) {
      StringRef bytes = A->getValue();
      CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
    } else
      CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
  }


  if (Args.hasArg(options::OPT_relocatable_pch))
    CmdArgs.push_back("-relocatable-pch");

  if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
    CmdArgs.push_back("-fconstant-string-class");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
    CmdArgs.push_back("-ftabstop");
    CmdArgs.push_back(A->getValue());
  }

  CmdArgs.push_back("-ferror-limit");
  if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
    CmdArgs.push_back(A->getValue());
  else
    CmdArgs.push_back("19");

  if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fmacro-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
    CmdArgs.push_back("-ftemplate-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fconstexpr-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  // Pass -fmessage-length=.
  CmdArgs.push_back("-fmessage-length");
  if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
    CmdArgs.push_back(A->getValue());
  } else {
    // If -fmessage-length=N was not specified, determine whether this is a
    // terminal and, if so, implicitly define -fmessage-length appropriately.
    unsigned N = llvm::sys::Process::StandardErrColumns();
    CmdArgs.push_back(Args.MakeArgString(Twine(N)));
  }

  // -fvisibility= and -fvisibility-ms-compat are of a piece.
  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
                                     options::OPT_fvisibility_ms_compat)) {
    if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back(A->getValue());
    } else {
      assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back("hidden");
      CmdArgs.push_back("-ftype-visibility");
      CmdArgs.push_back("default");
    }
  }

  Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);

  Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);

  // -fhosted is default.
  if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
      KernelOrKext)
    CmdArgs.push_back("-ffreestanding");

  // Forward -f (flag) options which we can pass directly.
  Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
  Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
  Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
  Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
  Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
  // AltiVec language extensions aren't relevant for assembling.
  if (!isa<PreprocessJobAction>(JA) || 
      Output.getType() != types::TY_PP_Asm)
    Args.AddLastArg(CmdArgs, options::OPT_faltivec);
  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
  Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);

  const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
  Sanitize.addArgs(Args, CmdArgs);

  if (!Args.hasFlag(options::OPT_fsanitize_recover,
                    options::OPT_fno_sanitize_recover,
                    true))
    CmdArgs.push_back("-fno-sanitize-recover");

  if (Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
      Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
                   options::OPT_fno_sanitize_undefined_trap_on_error, false))
    CmdArgs.push_back("-fsanitize-undefined-trap-on-error");

  // Report an error for -faltivec on anything other than PowerPC.
  if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
    if (!(getToolChain().getArch() == llvm::Triple::ppc ||
          getToolChain().getArch() == llvm::Triple::ppc64 ||
          getToolChain().getArch() == llvm::Triple::ppc64le))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "ppc/ppc64/ppc64le";

  if (getToolChain().SupportsProfiling())
    Args.AddLastArg(CmdArgs, options::OPT_pg);

  // -flax-vector-conversions is default.
  if (!Args.hasFlag(options::OPT_flax_vector_conversions,
                    options::OPT_fno_lax_vector_conversions))
    CmdArgs.push_back("-fno-lax-vector-conversions");

  if (Args.getLastArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-fapple-kext");

  if (Args.hasFlag(options::OPT_frewrite_includes,
                   options::OPT_fno_rewrite_includes, false))
    CmdArgs.push_back("-frewrite-includes");

  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);

  if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
    CmdArgs.push_back("-ftrapv-handler");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);

  // -fno-strict-overflow implies -fwrapv if it isn't disabled, but
  // -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
  if (Arg *A = Args.getLastArg(options::OPT_fwrapv,
                               options::OPT_fno_wrapv)) {
    if (A->getOption().matches(options::OPT_fwrapv))
      CmdArgs.push_back("-fwrapv");
  } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
                                      options::OPT_fno_strict_overflow)) {
    if (A->getOption().matches(options::OPT_fno_strict_overflow))
      CmdArgs.push_back("-fwrapv");
  }

  if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
                               options::OPT_fno_reroll_loops))
    if (A->getOption().matches(options::OPT_freroll_loops))
      CmdArgs.push_back("-freroll-loops");

  Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
  Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
                  options::OPT_fno_unroll_loops);

  Args.AddLastArg(CmdArgs, options::OPT_pthread);


  // -stack-protector=0 is default.
  unsigned StackProtectorLevel = 0;
  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                               options::OPT_fstack_protector_all,
                               options::OPT_fstack_protector)) {
    if (A->getOption().matches(options::OPT_fstack_protector))
      StackProtectorLevel = 1;
    else if (A->getOption().matches(options::OPT_fstack_protector_all))
      StackProtectorLevel = 2;
  } else {
    StackProtectorLevel =
      getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
  }
  if (StackProtectorLevel) {
    CmdArgs.push_back("-stack-protector");
    CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
  }

  // --param ssp-buffer-size=
  for (arg_iterator it = Args.filtered_begin(options::OPT__param),
       ie = Args.filtered_end(); it != ie; ++it) {
    StringRef Str((*it)->getValue());
    if (Str.startswith("ssp-buffer-size=")) {
      if (StackProtectorLevel) {
        CmdArgs.push_back("-stack-protector-buffer-size");
        // FIXME: Verify the argument is a valid integer.
        CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
      }
      (*it)->claim();
    }
  }

  // Translate -mstackrealign
  if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
                   false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-force-align-stack");
  }
  if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
                   false)) {
    CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
  }

  if (Args.hasArg(options::OPT_mstack_alignment)) {
    StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
    CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
  }
  // -mkernel implies -mstrict-align; don't add the redundant option.
  if (!KernelOrKext) {
    if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                                 options::OPT_munaligned_access)) {
      if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-strict-align");
      } else {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-no-strict-align");
      }
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
                               options::OPT_mno_restrict_it)) {
    if (A->getOption().matches(options::OPT_mrestrict_it)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-restrict-it");
    } else {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-no-restrict-it");
    }
  }

  // Forward -f options with positive and negative forms; we translate
  // these by hand.
  if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
    StringRef fname = A->getValue();
    if (!llvm::sys::fs::exists(fname))
      D.Diag(diag::err_drv_no_such_file) << fname;
    else
      A->render(Args, CmdArgs);
  }

  if (Args.hasArg(options::OPT_mkernel)) {
    if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
      CmdArgs.push_back("-fapple-kext");
    if (!Args.hasArg(options::OPT_fbuiltin))
      CmdArgs.push_back("-fno-builtin");
    Args.ClaimAllArgs(options::OPT_fno_builtin);
  }
  // -fbuiltin is default.
  else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
    CmdArgs.push_back("-fno-builtin");

  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fblocks=0 is default.
  if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
                   getToolChain().IsBlocksDefault()) ||
        (Args.hasArg(options::OPT_fgnu_runtime) &&
         Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
         !Args.hasArg(options::OPT_fno_blocks))) {
    CmdArgs.push_back("-fblocks");

    if (!Args.hasArg(options::OPT_fgnu_runtime) && 
        !getToolChain().hasBlocksRuntime())
      CmdArgs.push_back("-fblocks-runtime-optional");
  }

  // -fmodules enables modules (off by default). However, for C++/Objective-C++,
  // users must also pass -fcxx-modules. The latter flag will disappear once the
  // modules implementation is solid for C++/Objective-C++ programs as well.
  bool HaveModules = false;
  if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
    bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, 
                                     options::OPT_fno_cxx_modules, 
                                     false);
    if (AllowedInCXX || !types::isCXX(InputType)) {
      CmdArgs.push_back("-fmodules");
      HaveModules = true;
    }
  }

  // -fmodule-maps enables module map processing (off by default) for header
  // checking.  It is implied by -fmodules.
  if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
                   false)) {
    CmdArgs.push_back("-fmodule-maps");
  }

  // -fmodules-decluse checks that modules used are declared so (off by
  // default).
  if (Args.hasFlag(options::OPT_fmodules_decluse,
                   options::OPT_fno_modules_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-decluse");
  }

  // -fmodule-name specifies the module that is currently being built (or
  // used for header checking by -fmodule-maps).
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
    A->claim();
    A->render(Args, CmdArgs);
  }

  // -fmodule-map-file can be used to specify a file containing module
  // definitions.
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) {
    A->claim();
    A->render(Args, CmdArgs);
  }

  // If a module path was provided, pass it along. Otherwise, use a temporary
  // directory.
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) {
    A->claim();
    if (HaveModules) {
      A->render(Args, CmdArgs);
    }
  } else if (HaveModules) {
    SmallString<128> DefaultModuleCache;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
                                           DefaultModuleCache);
    llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
    llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
    const char Arg[] = "-fmodules-cache-path=";
    DefaultModuleCache.insert(DefaultModuleCache.begin(),
                              Arg, Arg + strlen(Arg));
    CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
  }

  // Pass through all -fmodules-ignore-macro arguments.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);

  // -faccess-control is default.
  if (Args.hasFlag(options::OPT_fno_access_control,
                   options::OPT_faccess_control,
                   false))
    CmdArgs.push_back("-fno-access-control");

  // -felide-constructors is the default.
  if (Args.hasFlag(options::OPT_fno_elide_constructors,
                   options::OPT_felide_constructors,
                   false))
    CmdArgs.push_back("-fno-elide-constructors");

  // -frtti is default.
  if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
      KernelOrKext) {
    CmdArgs.push_back("-fno-rtti");

    // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
    if (Sanitize.sanitizesVptr()) {
      std::string NoRttiArg =
        Args.getLastArg(options::OPT_mkernel,
                        options::OPT_fapple_kext,
                        options::OPT_fno_rtti)->getAsString(Args);
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fsanitize=vptr" << NoRttiArg;
    }
  }

  // -fshort-enums=0 is default for all architectures except Hexagon.
  if (Args.hasFlag(options::OPT_fshort_enums,
                   options::OPT_fno_short_enums,
                   getToolChain().getArch() ==
                   llvm::Triple::hexagon))
    CmdArgs.push_back("-fshort-enums");

  // -fsigned-char is default.
  if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
                    isSignedCharDefault(getToolChain().getTriple())))
    CmdArgs.push_back("-fno-signed-char");

  // -fthreadsafe-static is default.
  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
                    options::OPT_fno_threadsafe_statics))
    CmdArgs.push_back("-fno-threadsafe-statics");

  // -fuse-cxa-atexit is default.
  if (!Args.hasFlag(
           options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
           getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
               getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
               getToolChain().getArch() != llvm::Triple::hexagon &&
               getToolChain().getArch() != llvm::Triple::xcore) ||
      KernelOrKext)
    CmdArgs.push_back("-fno-use-cxa-atexit");

  // -fms-extensions=0 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
    CmdArgs.push_back("-fms-extensions");

  // -fms-compatibility=0 is default.
  if (Args.hasFlag(options::OPT_fms_compatibility, 
                   options::OPT_fno_ms_compatibility,
                   (getToolChain().getTriple().getOS() == llvm::Triple::Win32 &&
                    Args.hasFlag(options::OPT_fms_extensions, 
                                 options::OPT_fno_ms_extensions,
                                 true))))
    CmdArgs.push_back("-fms-compatibility");

  // -fmsc-version=1700 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
      Args.hasArg(options::OPT_fmsc_version)) {
    StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
    if (msc_ver.empty())
      CmdArgs.push_back("-fmsc-version=1700");
    else
      CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
  }


  // -fno-borland-extensions is default.
  if (Args.hasFlag(options::OPT_fborland_extensions,
                   options::OPT_fno_borland_extensions, false))
    CmdArgs.push_back("-fborland-extensions");

  // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
  // needs it.
  if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
                   options::OPT_fno_delayed_template_parsing,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
    CmdArgs.push_back("-fdelayed-template-parsing");

  // -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);

  if (Args.hasFlag(options::OPT_fgnu89_inline,
                   options::OPT_fno_gnu89_inline,
                   false))
    CmdArgs.push_back("-fgnu89-inline");

  if (Args.hasArg(options::OPT_fno_inline))
    CmdArgs.push_back("-fno-inline");

  if (Args.hasArg(options::OPT_fno_inline_functions))
    CmdArgs.push_back("-fno-inline-functions");

  ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);

  // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
  // legacy is the default. Next runtime is always legacy dispatch and
  // -fno-objc-legacy-dispatch gets ignored silently.
  if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) {
    if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
                      options::OPT_fno_objc_legacy_dispatch,
                      objcRuntime.isLegacyDispatchDefaultForArch(
                        getToolChain().getArch()))) {
      if (getToolChain().UseObjCMixedDispatch())
        CmdArgs.push_back("-fobjc-dispatch-method=mixed");
      else
        CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
    }
  }

  // When ObjectiveC legacy runtime is in effect on MacOSX,
  // turn on the option to do Array/Dictionary subscripting
  // by default.
  if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
      getToolChain().getTriple().isMacOSX() &&
      !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
      objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
      objcRuntime.isNeXTFamily())
    CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
  
  // -fencode-extended-block-signature=1 is default.
  if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
    CmdArgs.push_back("-fencode-extended-block-signature");
  }
  
  // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
  // NOTE: This logic is duplicated in ToolChains.cpp.
  bool ARC = isObjCAutoRefCount(Args);
  if (ARC) {
    getToolChain().CheckObjCARC();

    CmdArgs.push_back("-fobjc-arc");

    // FIXME: It seems like this entire block, and several around it should be
    // wrapped in isObjC, but for now we just use it here as this is where it
    // was being used previously.
    if (types::isCXX(InputType) && types::isObjC(InputType)) {
      if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
        CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
      else
        CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
    }

    // Allow the user to enable full exceptions code emission.
    // We define off for Objective-CC, on for Objective-C++.
    if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
                     options::OPT_fno_objc_arc_exceptions,
                     /*default*/ types::isCXX(InputType)))
      CmdArgs.push_back("-fobjc-arc-exceptions");
  }

  // -fobjc-infer-related-result-type is the default, except in the Objective-C
  // rewriter.
  if (rewriteKind != RK_None)
    CmdArgs.push_back("-fno-objc-infer-related-result-type");

  // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
  // takes precedence.
  const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
  if (!GCArg)
    GCArg = Args.getLastArg(options::OPT_fobjc_gc);
  if (GCArg) {
    if (ARC) {
      D.Diag(diag::err_drv_objc_gc_arr)
        << GCArg->getAsString(Args);
    } else if (getToolChain().SupportsObjCGC()) {
      GCArg->render(Args, CmdArgs);
    } else {
      // FIXME: We should move this to a hard error.
      D.Diag(diag::warn_drv_objc_gc_unsupported)
        << GCArg->getAsString(Args);
    }
  }

  // Add exception args.
  addExceptionArgs(Args, InputType, getToolChain().getTriple(),
                   KernelOrKext, objcRuntime, CmdArgs);

  if (getToolChain().UseSjLjExceptions())
    CmdArgs.push_back("-fsjlj-exceptions");

  // C++ "sane" operator new.
  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fconstant-cfstrings is default, and may be subject to argument translation
  // on Darwin.
  if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
                    options::OPT_fno_constant_cfstrings) ||
      !Args.hasFlag(options::OPT_mconstant_cfstrings,
                    options::OPT_mno_constant_cfstrings))
    CmdArgs.push_back("-fno-constant-cfstrings");

  // -fshort-wchar default varies depending on platform; only
  // pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
    A->render(Args, CmdArgs);

  // -fno-pascal-strings is default, only pass non-default.
  if (Args.hasFlag(options::OPT_fpascal_strings,
                   options::OPT_fno_pascal_strings,
                   false))
    CmdArgs.push_back("-fpascal-strings");

  // Honor -fpack-struct= and -fpack-struct, if given. Note that
  // -fno-pack-struct doesn't apply to -fpack-struct=.
  if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
    std::string PackStructStr = "-fpack-struct=";
    PackStructStr += A->getValue();
    CmdArgs.push_back(Args.MakeArgString(PackStructStr));
  } else if (Args.hasFlag(options::OPT_fpack_struct,
                          options::OPT_fno_pack_struct, false)) {
    CmdArgs.push_back("-fpack-struct=1");
  }

  if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
    if (!Args.hasArg(options::OPT_fcommon))
      CmdArgs.push_back("-fno-common");
    Args.ClaimAllArgs(options::OPT_fno_common);
  }

  // -fcommon is default, only pass non-default.
  else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
    CmdArgs.push_back("-fno-common");

  // -fsigned-bitfields is default, and clang doesn't yet support
  // -funsigned-bitfields.
  if (!Args.hasFlag(options::OPT_fsigned_bitfields,
                    options::OPT_funsigned_bitfields))
    D.Diag(diag::warn_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);

  // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
  if (!Args.hasFlag(options::OPT_ffor_scope,
                    options::OPT_fno_for_scope))
    D.Diag(diag::err_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);

  // -fcaret-diagnostics is default.
  if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
                    options::OPT_fno_caret_diagnostics, true))
    CmdArgs.push_back("-fno-caret-diagnostics");

  // -fdiagnostics-fixit-info is default, only pass non-default.
  if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
                    options::OPT_fno_diagnostics_fixit_info))
    CmdArgs.push_back("-fno-diagnostics-fixit-info");

  // Enable -fdiagnostics-show-option by default.
  if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
                   options::OPT_fno_diagnostics_show_option))
    CmdArgs.push_back("-fdiagnostics-show-option");

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
    CmdArgs.push_back("-fdiagnostics-show-category");
    CmdArgs.push_back(A->getValue());
  }

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(
      options::OPT_fdiagnostics_show_note_include_stack,
      options::OPT_fno_diagnostics_show_note_include_stack)) {
    if (A->getOption().matches(
        options::OPT_fdiagnostics_show_note_include_stack))
      CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
    else
      CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
  }

  // Color diagnostics are the default, unless the terminal doesn't support
  // them.
  // Support both clang's -f[no-]color-diagnostics and gcc's
  // -f[no-]diagnostics-colors[=never|always|auto].
  enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
       it != ie; ++it) {
    const Option &O = (*it)->getOption();
    if (!O.matches(options::OPT_fcolor_diagnostics) &&
        !O.matches(options::OPT_fdiagnostics_color) &&
        !O.matches(options::OPT_fno_color_diagnostics) &&
        !O.matches(options::OPT_fno_diagnostics_color) &&
        !O.matches(options::OPT_fdiagnostics_color_EQ))
      continue;

    (*it)->claim();
    if (O.matches(options::OPT_fcolor_diagnostics) ||
        O.matches(options::OPT_fdiagnostics_color)) {
      ShowColors = Colors_On;
    } else if (O.matches(options::OPT_fno_color_diagnostics) ||
               O.matches(options::OPT_fno_diagnostics_color)) {
      ShowColors = Colors_Off;
    } else {
      assert(O.matches(options::OPT_fdiagnostics_color_EQ));
      StringRef value((*it)->getValue());
      if (value == "always")
        ShowColors = Colors_On;
      else if (value == "never")
        ShowColors = Colors_Off;
      else if (value == "auto")
        ShowColors = Colors_Auto;
      else
        getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
          << ("-fdiagnostics-color=" + value).str();
    }
  }
  if (ShowColors == Colors_On ||
      (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
    CmdArgs.push_back("-fcolor-diagnostics");

  if (Args.hasArg(options::OPT_fansi_escape_codes))
    CmdArgs.push_back("-fansi-escape-codes");

  if (!Args.hasFlag(options::OPT_fshow_source_location,
                    options::OPT_fno_show_source_location))
    CmdArgs.push_back("-fno-show-source-location");

  if (!Args.hasFlag(options::OPT_fshow_column,
                    options::OPT_fno_show_column,
                    true))
    CmdArgs.push_back("-fno-show-column");

  if (!Args.hasFlag(options::OPT_fspell_checking,
                    options::OPT_fno_spell_checking))
    CmdArgs.push_back("-fno-spell-checking");


  // -fno-asm-blocks is default.
  if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
                   false))
    CmdArgs.push_back("-fasm-blocks");

  // Enable vectorization per default according to the optimization level
  // selected. For optimization levels that want vectorization we use the alias
  // option to simplify the hasFlag logic.
  bool EnableVec = shouldEnableVectorizerAtOLevel(Args);
  OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
    options::OPT_fvectorize;
  if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
                   options::OPT_fno_vectorize, EnableVec))
    CmdArgs.push_back("-vectorize-loops");

  // -fslp-vectorize is default.
  if (Args.hasFlag(options::OPT_fslp_vectorize,
                   options::OPT_fno_slp_vectorize, true))
    CmdArgs.push_back("-vectorize-slp");

  // -fno-slp-vectorize-aggressive is default.
  if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
                   options::OPT_fno_slp_vectorize_aggressive, false))
    CmdArgs.push_back("-vectorize-slp-aggressive");

  if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
    A->render(Args, CmdArgs);

  // -fdollars-in-identifiers default varies depending on platform and
  // language; only pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
                               options::OPT_fno_dollars_in_identifiers)) {
    if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
      CmdArgs.push_back("-fdollars-in-identifiers");
    else
      CmdArgs.push_back("-fno-dollars-in-identifiers");
  }

  // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
  // practical purposes.
  if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
                               options::OPT_fno_unit_at_a_time)) {
    if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
      D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
  }

  if (Args.hasFlag(options::OPT_fapple_pragma_pack,
                   options::OPT_fno_apple_pragma_pack, false))
    CmdArgs.push_back("-fapple-pragma-pack");

  // le32-specific flags: 
  //  -fno-math-builtin: clang should not convert math builtins to intrinsics
  //                     by default.
  if (getToolChain().getArch() == llvm::Triple::le32) {
    CmdArgs.push_back("-fno-math-builtin");
  }

  // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
  //
  // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
  if (getToolChain().getTriple().isOSDarwin() &&
      (getToolChain().getArch() == llvm::Triple::arm ||
       getToolChain().getArch() == llvm::Triple::thumb)) {
    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
      CmdArgs.push_back("-fno-builtin-strcat");
    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
      CmdArgs.push_back("-fno-builtin-strcpy");
  }
#endif

  // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
  if (Arg *A = Args.getLastArg(options::OPT_traditional,
                               options::OPT_traditional_cpp)) {
    if (isa<PreprocessJobAction>(JA))
      CmdArgs.push_back("-traditional-cpp");
    else
      D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
  }

  Args.AddLastArg(CmdArgs, options::OPT_dM);
  Args.AddLastArg(CmdArgs, options::OPT_dD);
  
  // Handle serialized diagnostics.
  if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
    CmdArgs.push_back("-serialize-diagnostic-file");
    CmdArgs.push_back(Args.MakeArgString(A->getValue()));
  }

  if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
    CmdArgs.push_back("-fretain-comments-from-system-headers");

  // Forward -fcomment-block-commands to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
  // Forward -fparse-all-comments to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);

  // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
  // parser.
  Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
  for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();

    // We translate this by hand to the -cc1 argument, since nightly test uses
    // it and developers have been trained to spell it with -mllvm.
    if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns")
      CmdArgs.push_back("-disable-llvm-optzns");
    else
      (*it)->render(Args, CmdArgs);
  }

  if (Output.getType() == types::TY_Dependencies) {
    // Handled with other dependency code.
  } else if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;
    CmdArgs.push_back("-x");
    if (Args.hasArg(options::OPT_rewrite_objc))
      CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
    else
      CmdArgs.push_back(types::getTypeName(II.getType()));
    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      II.getInputArg().renderAsInput(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_undef);

  const char *Exec = getToolChain().getDriver().getClangProgramPath();

  // Optionally embed the -cc1 level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (ArgList::const_iterator it = Args.begin(),
           ie = Args.end(); it != ie; ++it)
      (*it)->render(Args, OriginalArgs);

    SmallString<256> Flags;
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // Add the split debug info name to the command lines here so we
  // can propagate it to the backend.
  bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
    getToolChain().getTriple().isOSLinux() &&
    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
  const char *SplitDwarfOut;
  if (SplitDwarf) {
    CmdArgs.push_back("-split-dwarf-file");
    SplitDwarfOut = SplitDebugName(Args, Inputs);
    CmdArgs.push_back(SplitDwarfOut);
  }

  // Finally add the compile command to the compilation.
  if (Args.hasArg(options::OPT__SLASH_fallback)) {
    tools::visualstudio::Compile CL(getToolChain());
    Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
                                       LinkingOutput);
    C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
  } else {
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
  }


  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (SplitDwarf && !isa<CompileJobAction>(JA))
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);

  if (Arg *A = Args.getLastArg(options::OPT_pg))
    if (Args.hasArg(options::OPT_fomit_frame_pointer))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fomit-frame-pointer" << A->getAsString(Args);

  // Claim some arguments which clang supports automatically.

  // -fpch-preprocess is used with gcc to add a special marker in the output to
  // include the PCH file. Clang's PTH solution is completely transparent, so we
  // do not need to deal with it at all.
  Args.ClaimAllArgs(options::OPT_fpch_preprocess);

  // Claim some arguments which clang doesn't support, but we don't
  // care to warn the user about.
  Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
  Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);

  // Disable warnings for clang -E -emit-llvm foo.c
  Args.ClaimAllArgs(options::OPT_emit_llvm);
}

/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
                                      ArgStringList &cmdArgs,
                                      RewriteKind rewriteKind) const {
  // Look for the controlling runtime option.
  Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
                                    options::OPT_fgnu_runtime,
                                    options::OPT_fobjc_runtime_EQ);

  // Just forward -fobjc-runtime= to the frontend.  This supercedes
  // options about fragility.
  if (runtimeArg &&
      runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
    ObjCRuntime runtime;
    StringRef value = runtimeArg->getValue();
    if (runtime.tryParse(value)) {
      getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
        << value;
    }

    runtimeArg->render(args, cmdArgs);
    return runtime;
  }

  // Otherwise, we'll need the ABI "version".  Version numbers are
  // slightly confusing for historical reasons:
  //   1 - Traditional "fragile" ABI
  //   2 - Non-fragile ABI, version 1
  //   3 - Non-fragile ABI, version 2
  unsigned objcABIVersion = 1;
  // If -fobjc-abi-version= is present, use that to set the version.
  if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
    StringRef value = abiArg->getValue();
    if (value == "1")
      objcABIVersion = 1;
    else if (value == "2")
      objcABIVersion = 2;
    else if (value == "3")
      objcABIVersion = 3;
    else
      getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
        << value;
  } else {
    // Otherwise, determine if we are using the non-fragile ABI.
    bool nonFragileABIIsDefault = 
      (rewriteKind == RK_NonFragile || 
       (rewriteKind == RK_None &&
        getToolChain().IsObjCNonFragileABIDefault()));
    if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
                     options::OPT_fno_objc_nonfragile_abi,
                     nonFragileABIIsDefault)) {
      // Determine the non-fragile ABI version to use.
#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
      unsigned nonFragileABIVersion = 1;
#else
      unsigned nonFragileABIVersion = 2;
#endif

      if (Arg *abiArg = args.getLastArg(
            options::OPT_fobjc_nonfragile_abi_version_EQ)) {
        StringRef value = abiArg->getValue();
        if (value == "1")
          nonFragileABIVersion = 1;
        else if (value == "2")
          nonFragileABIVersion = 2;
        else
          getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
            << value;
      }

      objcABIVersion = 1 + nonFragileABIVersion;
    } else {
      objcABIVersion = 1;
    }
  }

  // We don't actually care about the ABI version other than whether
  // it's non-fragile.
  bool isNonFragile = objcABIVersion != 1;

  // If we have no runtime argument, ask the toolchain for its default runtime.
  // However, the rewriter only really supports the Mac runtime, so assume that.
  ObjCRuntime runtime;
  if (!runtimeArg) {
    switch (rewriteKind) {
    case RK_None:
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
      break;
    case RK_Fragile:
      runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
      break;
    case RK_NonFragile:
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
      break;
    }

  // -fnext-runtime
  } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
    // On Darwin, make this use the default behavior for the toolchain.
    if (getToolChain().getTriple().isOSDarwin()) {
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);

    // Otherwise, build for a generic macosx port.
    } else {
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
    }

  // -fgnu-runtime
  } else {
    assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
    // Legacy behaviour is to target the gnustep runtime if we are i
    // non-fragile mode or the GCC runtime in fragile mode.
    if (isNonFragile)
      runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6));
    else
      runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
  }

  cmdArgs.push_back(args.MakeArgString(
                                 "-fobjc-runtime=" + runtime.getAsString()));
  return runtime;
}

void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
  unsigned RTOptionID = options::OPT__SLASH_MT;

  if (Args.hasArg(options::OPT__SLASH_LDd))
    // The /LDd option implies /MTd. The dependent lib part can be overridden,
    // but defining _DEBUG is sticky.
    RTOptionID = options::OPT__SLASH_MTd;

  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
    RTOptionID = A->getOption().getID();

  switch(RTOptionID) {
    case options::OPT__SLASH_MD:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrt");
      break;
    case options::OPT__SLASH_MDd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrtd");
      break;
    case options::OPT__SLASH_MT:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmt");
      break;
    case options::OPT__SLASH_MTd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmtd");
      break;
    default:
      llvm_unreachable("Unexpected option ID.");
  }

  // This provides POSIX compatibility (maps 'open' to '_open'), which most
  // users want.  The /Za flag to cl.exe turns this off, but it's not
  // implemented in clang.
  CmdArgs.push_back("--dependent-lib=oldnames");

  // FIXME: Make this default for the win32 triple.
  CmdArgs.push_back("-cxx-abi");
  CmdArgs.push_back("microsoft");

  if (Arg *A = Args.getLastArg(options::OPT_show_includes))
    A->render(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    if (Args.hasArg(options::OPT__SLASH_fallback))
      CmdArgs.push_back("msvc-fallback");
    else
      CmdArgs.push_back("msvc");
  }
}

void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
                           const InputInfo &Output,
                           const InputInfoList &Inputs,
                           const ArgList &Args,
                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Don't warn about "clang -w -c foo.s"
  Args.ClaimAllArgs(options::OPT_w);
  // and "clang -emit-llvm -c foo.s"
  Args.ClaimAllArgs(options::OPT_emit_llvm);

  // Invoke ourselves in -cc1as mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1as");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = 
    getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  // Set the output mode, we currently only expect to be used as a real
  // assembler.
  CmdArgs.push_back("-filetype");
  CmdArgs.push_back("obj");

  // Set the main file name, so that debug info works even with
  // -save-temps or preprocessed assembly.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));

  // Add the target cpu
  const llvm::Triple &Triple = getToolChain().getTriple();
  std::string CPU = getCPUName(Args, Triple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  // Add the target features
  const Driver &D = getToolChain().getDriver();
  getTargetFeatures(D, Triple, Args, CmdArgs);

  // Ignore explicit -force_cpusubtype_ALL option.
  (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // Forward -g and handle debug info related flags, assuming we are dealing
  // with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    Args.ClaimAllArgs(options::OPT_g_Group);
    if (Arg *A = Args.getLastArg(options::OPT_g_Group))
      if (!A->getOption().matches(options::OPT_g0))
        CmdArgs.push_back("-g");

    // Add the -fdebug-compilation-dir flag if needed.
    addDebugCompDirArg(Args, CmdArgs);

    // Set the AT_producer to the clang version when using the integrated
    // assembler on assembly source files.
    CmdArgs.push_back("-dwarf-debug-producer");
    CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
  }

  // Optionally embed the -cc1as level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (ArgList::const_iterator it = Args.begin(),
           ie = Args.end(); it != ie; ++it)
      (*it)->render(Args, OriginalArgs);

    SmallString<256> Flags;
    const char *Exec = getToolChain().getDriver().getClangProgramPath();
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // FIXME: Add -static support, once we have it.

  CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
                                    getToolChain().getDriver());

  Args.AddAllArgs(CmdArgs, options::OPT_mllvm);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec = getToolChain().getDriver().getClangProgramPath();
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

void gcc::Common::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;

  for (ArgList::const_iterator
         it = Args.begin(), ie = Args.end(); it != ie; ++it) {
    Arg *A = *it;
    if (forwardToGCC(A->getOption())) {
      // Don't forward any -g arguments to assembly steps.
      if (isa<AssembleJobAction>(JA) &&
          A->getOption().matches(options::OPT_g_Group))
        continue;

      // Don't forward any -W arguments to assembly and link steps.
      if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
          A->getOption().matches(options::OPT_W_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
      // to get to the assembler.
      A->claim();
      A->render(Args, CmdArgs);
    }
  }

  RenderExtraToolArgs(JA, CmdArgs);

  // If using a driver driver, force the arch.
  llvm::Triple::ArchType Arch = getToolChain().getArch();
  if (getToolChain().getTriple().isOSDarwin()) {
    CmdArgs.push_back("-arch");

    // FIXME: Remove these special cases.
    if (Arch == llvm::Triple::ppc)
      CmdArgs.push_back("ppc");
    else if (Arch == llvm::Triple::ppc64)
      CmdArgs.push_back("ppc64");
    else if (Arch == llvm::Triple::ppc64le)
      CmdArgs.push_back("ppc64le");
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
  }

  // Try to force gcc to match the tool chain we want, if we recognize
  // the arch.
  //
  // FIXME: The triple class should directly provide the information we want
  // here.
  if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
    CmdArgs.push_back("-m32");
  else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
           Arch == llvm::Triple::ppc64le)
    CmdArgs.push_back("-m64");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
        << getToolChain().getTripleString();

    if (types::canTypeBeUserSpecified(II.getType())) {
      CmdArgs.push_back("-x");
      CmdArgs.push_back(types::getTypeName(II.getType()));
    }

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else {
      const Arg &A = II.getInputArg();

      // Reverse translate some rewritten options.
      if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
        CmdArgs.push_back("-lstdc++");
        continue;
      }

      // Don't render as input, we need gcc to do the translations.
      A.render(Args, CmdArgs);
    }
  }

  const std::string customGCCName = D.getCCCGenericGCCName();
  const char *GCCName;
  if (!customGCCName.empty())
    GCCName = customGCCName.c_str();
  else if (D.CCCIsCXX()) {
    GCCName = "g++";
  } else
    GCCName = "gcc";

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
                                          ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-E");
}

void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA,
                                          ArgStringList &CmdArgs) const {
  // The type is good enough.
}

void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
                                       ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // If -flto, etc. are present then make sure not to force assembly output.
  if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
      JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
    CmdArgs.push_back("-c");
  else {
    if (JA.getType() != types::TY_PP_Asm)
      D.Diag(diag::err_drv_invalid_gcc_output_type)
        << getTypeName(JA.getType());

    CmdArgs.push_back("-S");
  }
}

void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA,
                                        ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-c");
}

void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

// Hexagon tools start.
void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA,
                                        ArgStringList &CmdArgs) const {

}
void hexagon::Assemble::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;

  std::string MarchString = "-march=";
  MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString(MarchString));

  RenderExtraToolArgs(JA, CmdArgs);

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty())
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(clang::diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
      << getToolChain().getTripleString();

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ?
      II.getInputArg().render(Args, CmdArgs);
  }

  const char *GCCName = "hexagon-as";
  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

}
void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &Args,
                               const char *LinkingOutput) const {

  const toolchains::Hexagon_TC& ToolChain =
    static_cast<const toolchains::Hexagon_TC&>(getToolChain());
  const Driver &D = ToolChain.getDriver();

  ArgStringList CmdArgs;

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  bool hasStaticArg = Args.hasArg(options::OPT_static);
  bool buildingLib = Args.hasArg(options::OPT_shared);
  bool buildPIE = Args.hasArg(options::OPT_pie);
  bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
  bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
  bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
  bool useShared = buildingLib && !hasStaticArg;

  //----------------------------------------------------------------------------
  // Silence warnings for various options
  //----------------------------------------------------------------------------

  Args.ClaimAllArgs(options::OPT_g_Group);
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
                                     // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_static_libgcc);

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
         e = ToolChain.ExtraOpts.end();
       i != e; ++i)
    CmdArgs.push_back(i->c_str());

  std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));

  if (buildingLib) {
    CmdArgs.push_back("-shared");
    CmdArgs.push_back("-call_shared"); // should be the default, but doing as
                                       // hexagon-gcc does
  }

  if (hasStaticArg)
    CmdArgs.push_back("-static");

  if (buildPIE && !buildingLib)
    CmdArgs.push_back("-pie");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));
  }

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  const std::string MarchSuffix = "/" + MarchString;
  const std::string G0Suffix = "/G0";
  const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
  const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir)
                              + "/";
  const std::string StartFilesDir = RootDir
                                    + "hexagon/lib"
                                    + (buildingLib
                                       ? MarchG0Suffix : MarchSuffix);

  //----------------------------------------------------------------------------
  // moslib
  //----------------------------------------------------------------------------
  std::vector<std::string> oslibs;
  bool hasStandalone= false;

  for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();
    oslibs.push_back((*it)->getValue());
    hasStandalone = hasStandalone || (oslibs.back() == "standalone");
  }
  if (oslibs.empty()) {
    oslibs.push_back("standalone");
    hasStandalone = true;
  }

  //----------------------------------------------------------------------------
  // Start Files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {

    if (!buildingLib) {
      if (hasStandalone) {
        CmdArgs.push_back(
          Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
      }
      CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
    }
    std::string initObj = useShared ? "/initS.o" : "/init.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj));
  }

  //----------------------------------------------------------------------------
  // Library Search Paths
  //----------------------------------------------------------------------------
  const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
  for (ToolChain::path_list::const_iterator
         i = LibPaths.begin(),
         e = LibPaths.end();
       i != e;
       ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  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_u_Group);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  //----------------------------------------------------------------------------
  // Libraries
  //----------------------------------------------------------------------------
  if (incStdLib && incDefLibs) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    CmdArgs.push_back("--start-group");

    if (!buildingLib) {
      for(std::vector<std::string>::iterator i = oslibs.begin(),
            e = oslibs.end(); i != e; ++i)
        CmdArgs.push_back(Args.MakeArgString("-l" + *i));
      CmdArgs.push_back("-lc");
    }
    CmdArgs.push_back("-lgcc");

    CmdArgs.push_back("--end-group");
  }

  //----------------------------------------------------------------------------
  // End files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {
    std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
  }

  std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
  C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
}
// Hexagon tools end.

llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
    .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
    .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
    .Case("ppc64", llvm::Triple::ppc64)
    .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
    .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
           llvm::Triple::x86)
    .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
    // This is derived from the driver driver.
    .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
    .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm)
    .Cases("armv7s", "xscale", llvm::Triple::arm)
    .Case("r600", llvm::Triple::r600)
    .Case("nvptx", llvm::Triple::nvptx)
    .Case("nvptx64", llvm::Triple::nvptx64)
    .Case("amdil", llvm::Triple::amdil)
    .Case("spir", llvm::Triple::spir)
    .Default(llvm::Triple::UnknownArch);
}

const char *Clang::getBaseInputName(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  return Args.MakeArgString(
    llvm::sys::path::filename(Inputs[0].getBaseInput()));
}

const char *Clang::getBaseInputStem(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  const char *Str = getBaseInputName(Args, Inputs);

  if (const char *End = strrchr(Str, '.'))
    return Args.MakeArgString(std::string(Str, End));

  return Str;
}

const char *Clang::getDependencyFileName(const ArgList &Args,
                                         const InputInfoList &Inputs) {
  // FIXME: Think about this more.
  std::string Res;

  if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
    std::string Str(OutputOpt->getValue());
    Res = Str.substr(0, Str.rfind('.'));
  } else {
    Res = getBaseInputStem(Args, Inputs);
  }
  return Args.MakeArgString(Res + ".d");
}

void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // If -no_integrated_as is used add -Q to the darwin assember driver to make
  // sure it runs its system assembler not clang's integrated assembler.
  if (Args.hasArg(options::OPT_no_integrated_as))
    CmdArgs.push_back("-Q");

  // Forward -g, assuming we are dealing with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    if (Args.hasArg(options::OPT_gstabs))
      CmdArgs.push_back("--gstabs");
    else if (Args.hasArg(options::OPT_g_Group))
      CmdArgs.push_back("-g");
  }

  // Derived from asm spec.
  AddDarwinArch(Args, CmdArgs);

  // Use -force_cpusubtype_ALL on x86 by default.
  if (getToolChain().getArch() == llvm::Triple::x86 ||
      getToolChain().getArch() == llvm::Triple::x86_64 ||
      Args.hasArg(options::OPT_force__cpusubtype__ALL))
    CmdArgs.push_back("-force_cpusubtype_ALL");

  if (getToolChain().getArch() != llvm::Triple::x86_64 &&
      (((Args.hasArg(options::OPT_mkernel) ||
         Args.hasArg(options::OPT_fapple_kext)) &&
        (!getDarwinToolChain().isTargetIPhoneOS() ||
         getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) ||
       Args.hasArg(options::OPT_static)))
    CmdArgs.push_back("-static");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  // asm_final spec is empty.

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::DarwinTool::anchor() {}

void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
                                       ArgStringList &CmdArgs) const {
  StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args);

  // Derived from darwin_arch spec.
  CmdArgs.push_back("-arch");
  CmdArgs.push_back(Args.MakeArgString(ArchName));

  // FIXME: Is this needed anymore?
  if (ArchName == "arm")
    CmdArgs.push_back("-force_cpusubtype_ALL");
}

bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
  // We only need to generate a temp path for LTO if we aren't compiling object
  // files. When compiling source files, we run 'dsymutil' after linking. We
  // don't run 'dsymutil' when compiling object files.
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it)
    if (it->getType() != types::TY_Object)
      return true;

  return false;
}

void darwin::Link::AddLinkArgs(Compilation &C,
                               const ArgList &Args,
                               ArgStringList &CmdArgs,
                               const InputInfoList &Inputs) const {
  const Driver &D = getToolChain().getDriver();
  const toolchains::Darwin &DarwinTC = getDarwinToolChain();

  unsigned Version[3] = { 0, 0, 0 };
  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
    bool HadExtra;
    if (!Driver::GetReleaseVersion(A->getValue(), Version[0],
                                   Version[1], Version[2], HadExtra) ||
        HadExtra)
      D.Diag(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)) {
    // Don't pass -demangle to ld_classic.
    //
    // FIXME: This is a temporary workaround, ld should be handling this.
    bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 &&
                          Args.hasArg(options::OPT_static));
    if (getToolChain().getArch() == llvm::Triple::x86) {
      for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker,
                                                 options::OPT_Wl_COMMA),
             ie = Args.filtered_end(); it != ie; ++it) {
        const Arg *A = *it;
        for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
          if (StringRef(A->getValue(i)) == "-kext")
            UsesLdClassic = true;
      }
    }
    if (!UsesLdClassic)
      CmdArgs.push_back("-demangle");
  }

  if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
    CmdArgs.push_back("-export_dynamic");

  // If we are using LTO, then automatically create a temporary file path for
  // the linker to use, so that it's lifetime will extend past a possible
  // dsymutil step.
  if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
    const char *TmpPath = C.getArgs().MakeArgString(
      D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
    C.addTempFile(TmpPath);
    CmdArgs.push_back("-object_path_lto");
    CmdArgs.push_back(TmpPath);
  }

  // Derived from the "link" spec.
  Args.AddAllArgs(CmdArgs, options::OPT_static);
  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-dynamic");
  if (Args.hasArg(options::OPT_fgnu_runtime)) {
    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
    // here. How do we wish to handle such things?
  }

  if (!Args.hasArg(options::OPT_dynamiclib)) {
    AddDarwinArch(Args, CmdArgs);
    // FIXME: Why do this only on this path?
    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);

    Args.AddLastArg(CmdArgs, options::OPT_bundle);
    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
    Args.AddAllArgs(CmdArgs, options::OPT_client__name);

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
        (A = Args.getLastArg(options::OPT_current__version)) ||
        (A = Args.getLastArg(options::OPT_install__name)))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
  } else {
    CmdArgs.push_back("-dylib");

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_bundle)) ||
        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
        (A = Args.getLastArg(options::OPT_client__name)) ||
        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
        (A = Args.getLastArg(options::OPT_private__bundle)))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
                              "-dylib_compatibility_version");
    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
                              "-dylib_current_version");

    AddDarwinArch(Args, CmdArgs);

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
                              "-dylib_install_name");
  }

  Args.AddLastArg(CmdArgs, options::OPT_all__load);
  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
  if (DarwinTC.isTargetIPhoneOS())
    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
  Args.AddAllArgs(CmdArgs, options::OPT_force__load);
  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
  Args.AddAllArgs(CmdArgs, options::OPT_init);

  // Add the deployment target.
  VersionTuple TargetVersion = DarwinTC.getTargetVersion();

  // If we had an explicit -mios-simulator-version-min argument, honor that,
  // otherwise use the traditional deployment targets. We can't just check the
  // is-sim attribute because existing code follows this path, and the linker
  // may not handle the argument.
  //
  // FIXME: We may be able to remove this, once we can verify no one depends on
  // it.
  if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ))
    CmdArgs.push_back("-ios_simulator_version_min");
  else if (DarwinTC.isTargetIPhoneOS())
    CmdArgs.push_back("-iphoneos_version_min");
  else
    CmdArgs.push_back("-macosx_version_min");
  CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));

  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
  Args.AddLastArg(CmdArgs, options::OPT_single__module);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);

  if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
                                     options::OPT_fno_pie,
                                     options::OPT_fno_PIE)) {
    if (A->getOption().matches(options::OPT_fpie) ||
        A->getOption().matches(options::OPT_fPIE))
      CmdArgs.push_back("-pie");
    else
      CmdArgs.push_back("-no_pie");
  }

  Args.AddLastArg(CmdArgs, options::OPT_prebind);
  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);

  // Give --sysroot= preference, over the Apple specific behavior to also use
  // --isysroot as the syslibroot.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
  } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_y);
  Args.AddLastArg(CmdArgs, options::OPT_w);
  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
  Args.AddLastArg(CmdArgs, options::OPT_whyload);
  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
  Args.AddLastArg(CmdArgs, options::OPT_Mach);
}

void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");

  // The logic here is derived from gcc's behavior; most of which
  // comes from specs (starting with link_command). Consult gcc for
  // more information.
  ArgStringList CmdArgs;

  /// Hack(tm) to ignore linking errors when we are doing ARC migration.
  if (Args.hasArg(options::OPT_ccc_arcmt_check,
                  options::OPT_ccc_arcmt_migrate)) {
    for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I)
      (*I)->claim();
    const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("touch"));
    CmdArgs.push_back(Output.getFilename());
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
    return;
  }

  // I'm not sure why this particular decomposition exists in gcc, but
  // we follow suite for ease of comparison.
  AddLinkArgs(C, Args, CmdArgs, Inputs);

  Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_s);
  Args.AddAllArgs(CmdArgs, options::OPT_t);
  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
  Args.AddLastArg(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
  // members of static archive libraries which implement Objective-C classes or
  // categories.
  if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
    CmdArgs.push_back("-ObjC");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    // Derived from startfile spec.
    if (Args.hasArg(options::OPT_dynamiclib)) {
      // Derived from darwin_dylib1 spec.
      if (getDarwinToolChain().isTargetIOSSimulator()) {
        // The simulator doesn't have a versioned crt1 file.
        CmdArgs.push_back("-ldylib1.o");
      } else if (getDarwinToolChain().isTargetIPhoneOS()) {
        if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
          CmdArgs.push_back("-ldylib1.o");
      } else {
        if (getDarwinToolChain().isMacosxVersionLT(10, 5))
          CmdArgs.push_back("-ldylib1.o");
        else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
          CmdArgs.push_back("-ldylib1.10.5.o");
      }
    } else {
      if (Args.hasArg(options::OPT_bundle)) {
        if (!Args.hasArg(options::OPT_static)) {
          // Derived from darwin_bundle1 spec.
          if (getDarwinToolChain().isTargetIOSSimulator()) {
            // The simulator doesn't have a versioned crt1 file.
            CmdArgs.push_back("-lbundle1.o");
          } else if (getDarwinToolChain().isTargetIPhoneOS()) {
            if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
              CmdArgs.push_back("-lbundle1.o");
          } else {
            if (getDarwinToolChain().isMacosxVersionLT(10, 6))
              CmdArgs.push_back("-lbundle1.o");
          }
        }
      } else {
        if (Args.hasArg(options::OPT_pg) &&
            getToolChain().SupportsProfiling()) {
          if (Args.hasArg(options::OPT_static) ||
              Args.hasArg(options::OPT_object) ||
              Args.hasArg(options::OPT_preload)) {
            CmdArgs.push_back("-lgcrt0.o");
          } else {
            CmdArgs.push_back("-lgcrt1.o");

            // darwin_crt2 spec is empty.
          }
          // By default on OS X 10.8 and later, we don't link with a crt1.o
          // file and the linker knows to use _main as the entry point.  But,
          // when compiling with -pg, we need to link with the gcrt1.o file,
          // so pass the -no_new_main option to tell the linker to use the
          // "start" symbol as the entry point.
          if (getDarwinToolChain().isTargetMacOS() &&
              !getDarwinToolChain().isMacosxVersionLT(10, 8))
            CmdArgs.push_back("-no_new_main");
        } else {
          if (Args.hasArg(options::OPT_static) ||
              Args.hasArg(options::OPT_object) ||
              Args.hasArg(options::OPT_preload)) {
            CmdArgs.push_back("-lcrt0.o");
          } else {
            // Derived from darwin_crt1 spec.
            if (getDarwinToolChain().isTargetIOSSimulator()) {
              // The simulator doesn't have a versioned crt1 file.
              CmdArgs.push_back("-lcrt1.o");
            } else if (getDarwinToolChain().isTargetIPhoneOS()) {
              if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1))
                CmdArgs.push_back("-lcrt1.o");
              else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0))
                CmdArgs.push_back("-lcrt1.3.1.o");
            } else {
              if (getDarwinToolChain().isMacosxVersionLT(10, 5))
                CmdArgs.push_back("-lcrt1.o");
              else if (getDarwinToolChain().isMacosxVersionLT(10, 6))
                CmdArgs.push_back("-lcrt1.10.5.o");
              else if (getDarwinToolChain().isMacosxVersionLT(10, 8))
                CmdArgs.push_back("-lcrt1.10.6.o");

              // darwin_crt2 spec is empty.
            }
          }
        }
      }
    }

    if (!getDarwinToolChain().isTargetIPhoneOS() &&
        Args.hasArg(options::OPT_shared_libgcc) &&
        getDarwinToolChain().isMacosxVersionLT(10, 5)) {
      const char *Str =
        Args.MakeArgString(getToolChain().GetFilePath("crt3.o"));
      CmdArgs.push_back(Str);
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  if (Args.hasArg(options::OPT_fopenmp))
    // This is more complicated in gcc...
    CmdArgs.push_back("-lgomp");

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
  
  if (isObjCRuntimeLinked(Args) &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // Avoid linking compatibility stubs on i386 mac.
    if (!getDarwinToolChain().isTargetMacOS() ||
        getDarwinToolChain().getArch() != llvm::Triple::x86) {
      // If we don't have ARC or subscripting runtime support, link in the
      // runtime stubs.  We have to do this *before* adding any of the normal
      // linker inputs so that its initializer gets run first.
      ObjCRuntime runtime =
        getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true);
      // We use arclite library for both ARC and subscripting support.
      if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) ||
          !runtime.hasSubscripting())
        getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
    }
    CmdArgs.push_back("-framework");
    CmdArgs.push_back("Foundation");
    // Link libobj.
    CmdArgs.push_back("-lobjc");
  }

  if (LinkingOutput) {
    CmdArgs.push_back("-arch_multiple");
    CmdArgs.push_back("-final_output");
    CmdArgs.push_back(LinkingOutput);
  }

  if (Args.hasArg(options::OPT_fnested_functions))
    CmdArgs.push_back("-allow_stack_execute");

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);

    // link_ssp spec is empty.

    // Let the tool chain choose which runtime library to link.
    getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    // endfile_spec is empty.
  }

  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_F);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-create");
  assert(Output.isFilename() && "Unexpected lipo output.");

  CmdArgs.push_back("-output");
  CmdArgs.push_back(Output.getFilename());

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;
    assert(II.isFilename() && "Unexpected lipo input.");
    CmdArgs.push_back(II.getFilename());
  }
  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected dsymutil input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("--verify");
  CmdArgs.push_back("--debug-info");
  CmdArgs.push_back("--eh-frame");
  CmdArgs.push_back("--quiet");

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected verify input");

  // Grabbing the output of the earlier dsymutil run.
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  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 solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  // FIXME: Find a real GCC, don't hard-code versions here
  std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
  const llvm::Triple &T = getToolChain().getTriple();
  std::string LibPath = "/usr/lib/";
  llvm::Triple::ArchType Arch = T.getArch();
  switch (Arch) {
  case llvm::Triple::x86:
    GCCLibPath +=
        ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
    break;
  case llvm::Triple::x86_64:
    GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
    GCCLibPath += "/4.5.2/amd64/";
    LibPath += "amd64/";
    break;
  default:
    llvm_unreachable("Unsupported architecture");
  }

  ArgStringList CmdArgs;

  // Demangle C++ names in errors
  CmdArgs.push_back("-C");

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    } else {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    }
    if (getToolChain().getDriver().CCCIsCXX())
      CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
  }

  CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
    CmdArgs.push_back("-lgcc_s");
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-lgcc");
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
  }
  CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));

  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  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("gas"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
//    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
    }
    CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtn.o")));
  }

  CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
                                       + getToolChain().getTripleString()
                                       + "/4.2.4"));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: For some reason GCC passes -lgcc before adding
    // the default system libraries. Just mimic this for now.
    CmdArgs.push_back("-lgcc");

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-pthread");
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtend.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     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");
  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 openbsd::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;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Args.hasArg(options::OPT_nopie))
    CmdArgs.push_back("-nopie");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))  
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  std::string Triple = getToolChain().getTripleString();
  if (Triple.substr(0, 6) == "x86_64")
    Triple.replace(0, 6, "amd64");
  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
                                       "/4.2.1"));

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg)) 
        CmdArgs.push_back("-lm_p");
      else
        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");

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lpthread_p");
      else
         CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lc_p");
      else
         CmdArgs.push_back("-lc");
    }

    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    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");
  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 bitrig::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 ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lc_p");
      else
        CmdArgs.push_back("-lc");
    }

    StringRef MyArch;
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
      MyArch = "arm";
      break;
    case llvm::Triple::x86:
      MyArch = "i386";
      break;
    case llvm::Triple::x86_64:
      MyArch = "amd64";
      break;
    default:
      llvm_unreachable("Unsupported architecture");
    }
    CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");
  else if (getToolChain().getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("-a32");
  else if (getToolChain().getArch() == llvm::Triple::mips ||
           getToolChain().getArch() == llvm::Triple::mipsel ||
           getToolChain().getArch() == llvm::Triple::mips64 ||
           getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                      options::OPT_fpic, options::OPT_fno_pic,
                                      options::OPT_fPIE, options::OPT_fno_PIE,
                                      options::OPT_fpie, options::OPT_fno_pie);
    if (LastPICArg &&
        (LastPICArg->getOption().matches(options::OPT_fPIC) ||
         LastPICArg->getOption().matches(options::OPT_fpic) ||
         LastPICArg->getOption().matches(options::OPT_fPIE) ||
         LastPICArg->getOption().matches(options::OPT_fpie))) {
      CmdArgs.push_back("-KPIC");
    }
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::thumb) {
    CmdArgs.push_back("-mfpu=softvfp");
    switch(getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::GNUEABI:
    case llvm::Triple::EABI:
      CmdArgs.push_back("-meabi=5");
      break;

    default:
      CmdArgs.push_back("-matpcs");
    }
  }

  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 freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const toolchains::FreeBSD& ToolChain = 
    static_cast<const toolchains::FreeBSD&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_pie))
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld-elf.so.1");
    }
    if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
      llvm::Triple::ArchType Arch = ToolChain.getArch();
      if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
          Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
        CmdArgs.push_back("--hash-style=both");
      }
    }
    CmdArgs.push_back("--enable-new-dtags");
  }

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (ToolChain.getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386_fbsd");
  }

  if (ToolChain.getArch() == llvm::Triple::ppc) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32ppc_fbsd");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    const char *crt1 = NULL;
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        crt1 = "gcrt1.o";
      else if (Args.hasArg(options::OPT_pie))
        crt1 = "Scrt1.o";
      else
        crt1 = "crt1.o";
    }
    if (crt1)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

    const char *crtbegin = NULL;
    if (Args.hasArg(options::OPT_static))
      crtbegin = "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      crtbegin = "crtbeginS.o";
    else
      crtbegin = "crtbegin.o";

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  const ToolChain::path_list Paths = ToolChain.getFilePaths();
  for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
       i != e; ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
  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);

  // Tell the linker to load the plugin. This has to come before AddLinkerInputs
  // as gold requires -plugin to come before any -plugin-opt that -Wl might
  // forward.
  if (D.IsUsingLTO(Args)) {
    CmdArgs.push_back("-plugin");
    std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
    CmdArgs.push_back(Args.MakeArgString(Plugin));

    // Try to pass driver level flags relevant to LTO code generation down to
    // the plugin.

    // Handle flags for selecting CPU variants.
    std::string CPU = getCPUName(Args, ToolChain.getTriple());
    if (!CPU.empty()) {
      CmdArgs.push_back(
                        Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
                                           CPU));
    }
  }

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }
    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
    // the default system libraries. Just mimic this for now.
    if (Args.hasArg(options::OPT_pg))
      CmdArgs.push_back("-lgcc_p");
    else
      CmdArgs.push_back("-lgcc");
    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (Args.hasArg(options::OPT_pg)) {
      if (Args.hasArg(options::OPT_shared))
        CmdArgs.push_back("-lc");
      else
        CmdArgs.push_back("-lc_p");
      CmdArgs.push_back("-lgcc_p");
    } else {
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lgcc");
    }

    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
  }

  addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple());

  const char *Exec =
    Args.MakeArgString(ToolChain.GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on NetBSD/amd64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");

  // Set byte order explicitly
  if (getToolChain().getArch() == llvm::Triple::mips)
    CmdArgs.push_back("-EB");
  else if (getToolChain().getArch() == llvm::Triple::mipsel)
    CmdArgs.push_back("-EL");

  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 netbsd::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 (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld.elf_so");
    }
  }

  // When building 32-bit code on NetBSD/amd64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  unsigned Major, Minor, Micro;
  getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
  bool useLibgcc = true;
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
    if (getToolChain().getArch() == llvm::Triple::x86 ||
        getToolChain().getArch() == llvm::Triple::x86_64)
      useLibgcc = false;
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");

    if (useLibgcc) {
      if (Args.hasArg(options::OPT_static)) {
        // libgcc_eh depends on libc, so resolve as much as possible,
        // pull in any new requirements from libc and then get the rest
        // of libgcc.
        CmdArgs.push_back("-lgcc_eh");
        CmdArgs.push_back("-lc");
        CmdArgs.push_back("-lgcc");
      } else {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("--as-needed");
        CmdArgs.push_back("-lgcc_s");
        CmdArgs.push_back("--no-as-needed");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                  "crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                 "crtendS.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                    "crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gnutools::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::ppc) {
    CmdArgs.push_back("-a32");
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64le");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::arm) {
    StringRef MArch = getToolChain().getArchName();
    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
      CmdArgs.push_back("-mfpu=neon");
    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a")
      CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");

    StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args,
                                           getToolChain().getTriple());
    CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));

    Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
    Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
    Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
  } else if (getToolChain().getArch() == llvm::Triple::mips ||
             getToolChain().getArch() == llvm::Triple::mipsel ||
             getToolChain().getArch() == llvm::Triple::mips64 ||
             getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
      if (StringRef(A->getValue()) == "2008")
        CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
    }

    Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16);
    Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
                    options::OPT_mno_micromips);
    Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
    Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);

    Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                      options::OPT_fpic, options::OPT_fno_pic,
                                      options::OPT_fPIE, options::OPT_fno_PIE,
                                      options::OPT_fpie, options::OPT_fno_pie);
    if (LastPICArg &&
        (LastPICArg->getOption().matches(options::OPT_fPIC) ||
         LastPICArg->getOption().matches(options::OPT_fpic) ||
         LastPICArg->getOption().matches(options::OPT_fPIE) ||
         LastPICArg->getOption().matches(options::OPT_fpie))) {
      CmdArgs.push_back("-KPIC");
    }
  } else if (getToolChain().getArch() == llvm::Triple::systemz) {
    // Always pass an -march option, since our default of z10 is later
    // than the GNU assembler's default.
    StringRef CPUName = getSystemZTargetCPU(Args);
    CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
  }

  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));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

static void AddLibgcc(llvm::Triple Triple, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
  bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
                      Args.hasArg(options::OPT_static);
  if (!D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  if (StaticLibgcc || isAndroid) {
    if (D.CCCIsCXX())
      CmdArgs.push_back("-lgcc");
  } else {
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--as-needed");
    CmdArgs.push_back("-lgcc_s");
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--no-as-needed");
  }

  if (StaticLibgcc && !isAndroid)
    CmdArgs.push_back("-lgcc_eh");
  else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  // According to Android ABI, we have to link with libdl if we are
  // linking with non-static libgcc.
  //
  // NOTE: This fixes a link error on Android MIPS as well.  The non-static
  // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
  if (isAndroid && !StaticLibgcc)
    CmdArgs.push_back("-ldl");
}

static bool hasMipsN32ABIArg(const ArgList &Args) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef("n32"));
}

static StringRef getLinuxDynamicLinker(const ArgList &Args,
                                       const toolchains::Linux &ToolChain) {
  if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android)
    return "/system/bin/linker";
  else if (ToolChain.getArch() == llvm::Triple::x86)
    return "/lib/ld-linux.so.2";
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    return "/lib/ld-linux-aarch64.so.1";
  else if (ToolChain.getArch() == llvm::Triple::arm ||
           ToolChain.getArch() == llvm::Triple::thumb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";
    else
      return "/lib/ld-linux.so.3";
  } else if (ToolChain.getArch() == llvm::Triple::mips ||
             ToolChain.getArch() == llvm::Triple::mipsel)
    return "/lib/ld.so.1";
  else if (ToolChain.getArch() == llvm::Triple::mips64 ||
           ToolChain.getArch() == llvm::Triple::mips64el) {
    if (hasMipsN32ABIArg(Args))
      return "/lib32/ld.so.1";
    else
      return "/lib64/ld.so.1";
  } else if (ToolChain.getArch() == llvm::Triple::ppc)
    return "/lib/ld.so.1";
  else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
           ToolChain.getArch() == llvm::Triple::ppc64le ||
           ToolChain.getArch() == llvm::Triple::systemz)
    return "/lib64/ld64.so.1";
  else
    return "/lib64/ld-linux-x86-64.so.2";
}

void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  const toolchains::Linux& ToolChain =
    static_cast<const toolchains::Linux&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const bool isAndroid =
    ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
  const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs();
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow());

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (IsPIE)
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
         e = ToolChain.ExtraOpts.end();
       i != e; ++i)
    CmdArgs.push_back(i->c_str());

  if (!Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("--eh-frame-hdr");
  }

  CmdArgs.push_back("-m");
  if (ToolChain.getArch() == llvm::Triple::x86)
    CmdArgs.push_back("elf_i386");
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    CmdArgs.push_back("aarch64linux");
  else if (ToolChain.getArch() == llvm::Triple::arm
           ||  ToolChain.getArch() == llvm::Triple::thumb)
    CmdArgs.push_back("armelf_linux_eabi");
  else if (ToolChain.getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("elf32ppclinux");
  else if (ToolChain.getArch() == llvm::Triple::ppc64)
    CmdArgs.push_back("elf64ppc");
  else if (ToolChain.getArch() == llvm::Triple::mips)
    CmdArgs.push_back("elf32btsmip");
  else if (ToolChain.getArch() == llvm::Triple::mipsel)
    CmdArgs.push_back("elf32ltsmip");
  else if (ToolChain.getArch() == llvm::Triple::mips64) {
    if (hasMipsN32ABIArg(Args))
      CmdArgs.push_back("elf32btsmipn32");
    else
      CmdArgs.push_back("elf64btsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::mips64el) {
    if (hasMipsN32ABIArg(Args))
      CmdArgs.push_back("elf32ltsmipn32");
    else
      CmdArgs.push_back("elf64ltsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::systemz)
    CmdArgs.push_back("elf64_s390");
  else
    CmdArgs.push_back("elf_x86_64");

  if (Args.hasArg(options::OPT_static)) {
    if (ToolChain.getArch() == llvm::Triple::arm
        || ToolChain.getArch() == llvm::Triple::thumb)
      CmdArgs.push_back("-Bstatic");
    else
      CmdArgs.push_back("-static");
  } else if (Args.hasArg(options::OPT_shared)) {
    CmdArgs.push_back("-shared");
    if (isAndroid) {
      CmdArgs.push_back("-Bsymbolic");
    }
  }

  if (ToolChain.getArch() == llvm::Triple::arm ||
      ToolChain.getArch() == llvm::Triple::thumb ||
      (!Args.hasArg(options::OPT_static) &&
       !Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-dynamic-linker");
    CmdArgs.push_back(Args.MakeArgString(
        D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!isAndroid) {
      const char *crt1 = NULL;
      if (!Args.hasArg(options::OPT_shared)){
        if (Args.hasArg(options::OPT_pg))
          crt1 = "gcrt1.o";
        else if (IsPIE)
          crt1 = "Scrt1.o";
        else
          crt1 = "crt1.o";
      }
      if (crt1)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
    }

    const char *crtbegin;
    if (Args.hasArg(options::OPT_static))
      crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared))
      crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
    else if (IsPIE)
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
    else
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));

    // Add crtfastmath.o if available and fast math is enabled.
    ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  const ToolChain::path_list Paths = ToolChain.getFilePaths();

  for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
       i != e; ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));

  // Tell the linker to load the plugin. This has to come before AddLinkerInputs
  // as gold requires -plugin to come before any -plugin-opt that -Wl might
  // forward.
  if (D.IsUsingLTO(Args)) {
    CmdArgs.push_back("-plugin");
    std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
    CmdArgs.push_back(Args.MakeArgString(Plugin));

    // Try to pass driver level flags relevant to LTO code generation down to
    // the plugin.

    // Handle flags for selecting CPU variants.
    std::string CPU = getCPUName(Args, ToolChain.getTriple());
    if (!CPU.empty()) {
      CmdArgs.push_back(
                        Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
                                           CPU));
    }
  }


  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  // Call these before we add the C++ ABI library.
  if (Sanitize.needsUbsanRt())
    addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(),
                    Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                    Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
  if (Sanitize.needsAsanRt())
    addAsanRTLinux(getToolChain(), Args, CmdArgs);
  if (Sanitize.needsTsanRt())
    addTsanRTLinux(getToolChain(), Args, CmdArgs);
  if (Sanitize.needsMsanRt())
    addMsanRTLinux(getToolChain(), Args, CmdArgs);
  if (Sanitize.needsLsanRt())
    addLsanRTLinux(getToolChain(), Args, CmdArgs);
  if (Sanitize.needsDfsanRt())
    addDfsanRTLinux(getToolChain(), Args, CmdArgs);

  // The profile runtime also needs access to system libraries.
  addProfileRTLinux(getToolChain(), Args, CmdArgs);

  if (D.CCCIsCXX() &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
      !Args.hasArg(options::OPT_static);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bstatic");
    ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bdynamic");
    CmdArgs.push_back("-lm");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--start-group");

      bool OpenMP = Args.hasArg(options::OPT_fopenmp);
      if (OpenMP) {
        CmdArgs.push_back("-lgomp");

        // FIXME: Exclude this for platforms whith libgomp that doesn't require
        // librt. Most modern Linux platfroms require it, but some may not.
        CmdArgs.push_back("-lrt");
      }

      AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);

      if (Args.hasArg(options::OPT_pthread) ||
          Args.hasArg(options::OPT_pthreads) || OpenMP)
        CmdArgs.push_back("-lpthread");

      CmdArgs.push_back("-lc");

      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--end-group");
      else
        AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
    }

    if (!Args.hasArg(options::OPT_nostartfiles)) {
      const char *crtend;
      if (Args.hasArg(options::OPT_shared))
        crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
      else if (IsPIE)
        crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
      else
        crtend = isAndroid ? "crtend_android.o" : "crtend.o";

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
      if (!isAndroid)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
    }
  }

  C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}

void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                   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");
  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::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("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lCompilerRT-Generic");
    CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
    CmdArgs.push_back(
         Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

/// DragonFly Tools

// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");

  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 dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  bool UseGCC47 = false;
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47))
    UseGCC47 = false;

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  CmdArgs.push_back("--eh-frame-hdr");
  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-Bshareable");
    else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
    }
    CmdArgs.push_back("--hash-style=both");
  }

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt1.o")));
      else {
        if (Args.hasArg(options::OPT_pie))
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("Scrt1.o")));
        else
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("crt1.o")));
      }
    }
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crti.o")));
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
    //         rpaths
    if (UseGCC47)
      CmdArgs.push_back("-L/usr/lib/gcc47");
    else
      CmdArgs.push_back("-L/usr/lib/gcc44");

    if (!Args.hasArg(options::OPT_static)) {
      if (UseGCC47) {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc47");
      } else {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc44");
      }
    }

    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");

    if (!Args.hasArg(options::OPT_nolibc)) {
      CmdArgs.push_back("-lc");
    }

    if (UseGCC47) {
      if (Args.hasArg(options::OPT_static) ||
          Args.hasArg(options::OPT_static_libgcc)) {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("-lgcc_eh");
      } else {
        if (Args.hasArg(options::OPT_shared_libgcc)) {
          CmdArgs.push_back("-lgcc_pic");
          if (!Args.hasArg(options::OPT_shared))
            CmdArgs.push_back("-lgcc");
        } else {
          CmdArgs.push_back("-lgcc");
          CmdArgs.push_back("--as-needed");
          CmdArgs.push_back("-lgcc_pic");
          CmdArgs.push_back("--no-as-needed");
        }
      }
    } else {
      if (Args.hasArg(options::OPT_shared)) {
        CmdArgs.push_back("-lgcc_pic");
      } else {
        CmdArgs.push_back("-lgcc");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  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 {
  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) &&
      !C.getDriver().IsCLMode()) {
    CmdArgs.push_back("-defaultlib:libcmt");
  }

  CmdArgs.push_back("-nologo");

  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);

  if (DLL) {
    CmdArgs.push_back(Args.MakeArgString("-dll"));

    SmallString<128> ImplibName(Output.getFilename());
    llvm::sys::path::replace_extension(ImplibName, "lib");
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
                                         ImplibName.str()));
  }

  if (getToolChain().getSanitizerArgs().needsAsanRt()) {
    CmdArgs.push_back(Args.MakeArgString("-debug"));
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
    SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
    llvm::sys::path::append(LibSanitizer, "lib", "windows");
    if (DLL) {
      llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
    } else {
      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
    }
    // FIXME: Handle 64-bit.
    CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_l);
  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);

  // Add filenames immediately.
  for (InputInfoList::const_iterator
       it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    if (it->isFilename())
      CmdArgs.push_back(it->getFilename());
    else
      it->getInputArg().renderAsInput(Args, CmdArgs);
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
                                         const InputInfo &Output,
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
  C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}

// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
// If one cannot be found, return FallbackName.
// We do this special search to prevent clang-cl from falling back onto itself
// if it's available as cl.exe on the path.
static std::string FindFallback(const char *FallbackName,
                                const char *ClangProgramPath) {
  llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
  if (!OptPath.hasValue())
    return FallbackName;

#ifdef LLVM_ON_WIN32
  const StringRef PathSeparators = ";";
#else
  const StringRef PathSeparators = ":";
#endif

  SmallVector<StringRef, 8> PathSegments;
  llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators);

  for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
    const StringRef &PathSegment = PathSegments[i];
    if (PathSegment.empty())
      continue;

    SmallString<128> FilePath(PathSegment);
    llvm::sys::path::append(FilePath, FallbackName);
    if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
        !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
      return FilePath.str();
  }

  return FallbackName;
}

Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("/nologo");
  CmdArgs.push_back("/c"); // Compile only.
  CmdArgs.push_back("/W0"); // No warnings.

  // The goal is to be able to invoke this tool correctly based on
  // any flag accepted by clang-cl.

  // These are spelled the same way in clang and cl.exe,.
  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I);

  // Optimization level.
  if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
    if (A->getOption().getID() == options::OPT_O0) {
      CmdArgs.push_back("/Od");
    } else {
      StringRef OptLevel = A->getValue();
      if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
        A->render(Args, CmdArgs);
      else if (OptLevel == "3")
        CmdArgs.push_back("/Ox");
    }
  }

  // Flags for which clang-cl have an alias.
  // FIXME: How can we ensure this stays in sync with relevant clang-cl options?

  if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR"
                                                                   : "/GR-");
  if (Args.hasArg(options::OPT_fsyntax_only))
    CmdArgs.push_back("/Zs");

  std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
  for (size_t I = 0, E = Includes.size(); I != E; ++I)
    CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I]));

  // Flags that can simply be passed through.
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);

  // The order of these flags is relevant, so pick the last one.
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
                               options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
    A->render(Args, CmdArgs);


  // Input filename.
  assert(Inputs.size() == 1);
  const InputInfo &II = Inputs[0];
  assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
  CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
  if (II.isFilename())
    CmdArgs.push_back(II.getFilename());
  else
    II.getInputArg().renderAsInput(Args, CmdArgs);

  // Output filename.
  assert(Output.getType() == types::TY_Object);
  const char *Fo = Args.MakeArgString(std::string("/Fo") +
                                      Output.getFilename());
  CmdArgs.push_back(Fo);

  const Driver &D = getToolChain().getDriver();
  std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());

  return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
}


/// XCore Tools
// We pass assemble and link construction to the xcc tool.

void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  CmdArgs.push_back("-c");

  if (Args.hasArg(options::OPT_g_Group)) {
    CmdArgs.push_back("-g");
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  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("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import clang 3.4rc2 r196603.
Many bug fixes and improvements for the driver NetBSD/ARM EABI.
@
text
@a501 5
  if (Triple.getOS() == llvm::Triple::NetBSD) {
    if (MArch == "armv6")
      return "arm1176jzf-s";
  }

a5969 7
  // Pass the target CPU to GNU as for ARM, since the source code might
  // not have the correct .cpu annotation.
  if (getToolChain().getArch() == llvm::Triple::arm) {
    std::string MArch(getARMTargetCPU(Args, getToolChain().getTriple()));
    CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
  }

a6175 7
    if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfp64)) {
      if (A->getOption().matches(options::OPT_mfp32))
        CmdArgs.push_back(Args.MakeArgString("-mfp32"));
      else
        CmdArgs.push_back(Args.MakeArgString("-mfp64"));
    }

a6181 7
    if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
      // Do not use AddLastArg because not all versions of MIPS assembler
      // support -mmsa / -mno-msa options.
      if (A->getOption().matches(options::OPT_mmsa))
        CmdArgs.push_back(Args.MakeArgString("-mmsa"));
    }

@


1.1.1.3
log
@Import clang 3.5svn r198450.
@
text
@d193 1
a193 3
  //                and only supported on native toolchains.
  if (!TC.isCrossCompiling())
    addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
d445 103
a661 3
  } else if (FPU == "vfp") {
    Features.push_back("+vfp2");
    Features.push_back("-neon");
d666 3
a671 7
  } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp4" || FPU == "vfpv4") {
    Features.push_back("+vfp4");
    Features.push_back("-neon");
d699 3
a701 2
StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
                                     const llvm::Triple &Triple) {
d730 1
a730 1
        arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
a751 3
      case llvm::Triple::EABIHF:
        FloatABI = "hard";
        break;
d758 1
a758 1
          arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
d779 12
a790 24
                                 std::vector<const char *> &Features,
                                 bool ForAS) {
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
  if (!ForAS) {
    // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
    // yet (it uses the -mfloat-abi and -msoft-float options), and it is
    // stripped out by the ARM target. We should probably pass this a new
    // -target-option, which is handled by the -cc1/-cc1as invocation.
    //
    // FIXME2:  For consistency, it would be ideal if we set up the target
    // machine state the same when using the frontend or the assembler. We don't
    // currently do that for the assembler, we pass the options directly to the
    // backend and never even instantiate the frontend TargetInfo. If we did,
    // and used its handleTargetFeatures hook, then we could ensure the
    // assembler and the frontend behave the same.

    // Use software floating point operations?
    if (FloatABI == "soft")
      Features.push_back("+soft-float");

    // Use software floating point argument passing?
    if (FloatABI != "hard")
      Features.push_back("+soft-float-abi");
  }
d820 1
a820 1
  std::string CPUName = arm::getARMTargetCPU(Args, Triple);
a844 1
    case llvm::Triple::EABIHF:
d856 1
a856 1
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
d1023 2
a1024 1
  if (FloatABI == "soft") {
d1065 3
a1067 1
  if (FloatABI == "soft") {
d1072 5
d1345 1
a1345 1
    return arm::getARMTargetCPU(Args, T);
a1394 18
static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
                          ArgStringList &CmdArgs) {
  // Tell the linker to load the plugin. This has to come before AddLinkerInputs
  // as gold requires -plugin to come before any -plugin-opt that -Wl might
  // forward.
  CmdArgs.push_back("-plugin");
  std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
  CmdArgs.push_back(Args.MakeArgString(Plugin));

  // Try to pass driver level flags relevant to LTO code generation down to
  // the plugin.

  // Handle flags for selecting CPU variants.
  std::string CPU = getCPUName(Args, ToolChain.getTriple());
  if (!CPU.empty())
    CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
}

d1507 1
a1507 2
                              const ArgList &Args, ArgStringList &CmdArgs,
                              bool ForAS) {
d1521 1
a1521 1
    getARMTargetFeatures(D, Triple, Args, Features, ForAS);
d1572 1
a1572 1
  if (!Triple.isMacOSX())
d2539 1
a2539 1
  getTargetFeatures(D, ETriple, Args, CmdArgs, false);
d2616 2
a2617 2
  // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
  // are preserved, all other debug options are substituted with "-g".
d2620 1
a2620 3
    if (A->getOption().matches(options::OPT_gline_tables_only)) {
      // FIXME: we should support specifying dwarf version with
      // -gline-tables-only.
d2622 1
a2622 4
      // Default is dwarf-2 for darwin.
      if (getToolChain().getTriple().isOSDarwin())
        CmdArgs.push_back("-gdwarf-2");
    } else if (A->getOption().matches(options::OPT_gdwarf_2))
d2772 1
a2772 2
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
d4044 1
a4044 1
  getTargetFeatures(D, Triple, Args, CmdArgs, true);
d4254 5
d4276 5
a4531 129
/// getARMCPUForMArch - Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting
//
// FIXME: tblgen this.
const char *arm::getARMCPUForMArch(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  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();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  // Handle -march=native.
  if (MArch == "native") {
    std::string CPU = llvm::sys::getHostCPUName();
    if (CPU != "generic") {
      // Translate the native cpu into the architecture. The switch below will
      // then chose the minimum cpu for that arch.
      MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
    }
  }

  if (Triple.getOS() == llvm::Triple::NetBSD) {
    if (MArch == "armv6")
      return "arm1176jzf-s";
  }

  const char *result = llvm::StringSwitch<const char *>(MArch)
    .Cases("armv2", "armv2a","arm2")
    .Case("armv3", "arm6")
    .Case("armv3m", "arm7m")
    .Case("armv4", "strongarm")
    .Case("armv4t", "arm7tdmi")
    .Case("thumbv4t", "arm7tdmi")
    .Cases("armv5", "armv5t", "arm10tdmi")
    .Cases("thumbv5", "thumbv5t", "arm10tdmi")
    .Cases("armv5e", "armv5te", "arm1022e")
    .Cases("thumbv5e", "thumbv5te", "arm1022e")
    .Case("armv5tej", "arm926ej-s")
    .Case("thumbv5tej", "arm926ej-s")
    .Cases("armv6", "armv6k", "arm1136jf-s")
    .Cases("thumbv6", "thumbv6k", "arm1136jf-s")
    .Case("armv6j", "arm1136j-s")
    .Case("thumbv6j", "arm1136j-s")
    .Cases("armv6z", "armv6zk", "arm1176jzf-s")
    .Cases("thumbv6z", "thumbv6zk", "arm1176jzf-s")
    .Case("armv6t2", "arm1156t2-s")
    .Case("thumbv6t2", "arm1156t2-s")
    .Cases("armv6m", "armv6-m", "cortex-m0")
    .Case("thumbv6m", "cortex-m0")
    .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
    .Cases("thumbv7", "thumbv7a", "cortex-a8")
    .Cases("armv7l", "armv7-l", "cortex-a8")
    .Cases("armv7f", "armv7-f", "cortex-a9-mp")
    .Cases("armv7s", "armv7-s", "swift")
    .Cases("armv7r", "armv7-r", "cortex-r4")
    .Case("thumbv7r", "cortex-r4")
    .Cases("armv7m", "armv7-m", "cortex-m3")
    .Case("thumbv7m", "cortex-m3")
    .Cases("armv7em", "armv7e-m", "cortex-m4")
    .Cases("thumbv7em", "thumbv7e-m", "cortex-m4")
    .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
    .Cases("thumbv8", "thumbv8a", "cortex-a53")
    .Case("ep9312", "ep9312")
    .Case("iwmmxt", "iwmmxt")
    .Case("xscale", "xscale")
    // If all else failed, return the most base CPU with thumb interworking
    // supported by LLVM.
    .Default(0);

  if (result)
    return result;

  return
    Triple.getEnvironment() == llvm::Triple::GNUEABIHF
      ? "arm1176jzf-s"
      : "arm7tdmi";
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
StringRef arm::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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  return getARMCPUForMArch(Args, Triple);
}

/// 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!
const char *arm::getLLVMArchSuffixForARM(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Case("strongarm", "v4")
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7")
    .Cases("cortex-r4", "cortex-r5", "v7r")
    .Case("cortex-m0", "v6m")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7em")
    .Case("cortex-a9-mp", "v7f")
    .Case("swift", "v7s")
    .Cases("cortex-a53", "cortex-a57", "v8")
    .Default("");
}

d4614 2
a4615 8
  // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
  // FIXME: at run-time detect assembler capabilities or rely on version
  // information forwarded by -target-assembler-version (future)
  if (Args.hasArg(options::OPT_no_integrated_as)) {
    const llvm::Triple &T(getToolChain().getTriple());
    if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
      CmdArgs.push_back("-Q");
  }
d4795 1
a4795 1
  if (DarwinTC.isTargetIOSBased())
d4818 1
a4818 1
  if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) {
d4820 1
a4820 2
    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
  } else if (DarwinTC.isTargetIOSBased()) {
d4822 1
a4822 2
    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
  } else if (DarwinTC.isTargetMacOS()) {
d4824 1
a4824 2
    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
  }
d4949 1
a4949 1
      } else if (getDarwinToolChain().isTargetMacOS()) {
d4965 1
a4965 1
          } else if (getDarwinToolChain().isTargetMacOS()) {
d5005 1
a5005 1
            } else if (getDarwinToolChain().isTargetMacOS()) {
d5020 1
a5020 1
    if (getDarwinToolChain().isTargetMacOS() &&
a5407 34
  // When building 32-bit code on OpenBSD/amd64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");
  else if (getToolChain().getArch() == llvm::Triple::ppc) {
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::mips64 ||
             getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                      options::OPT_fpic, options::OPT_fno_pic,
                                      options::OPT_fPIE, options::OPT_fno_PIE,
                                      options::OPT_fpie, options::OPT_fno_pie);
    if (LastPICArg &&
        (LastPICArg->getOption().matches(options::OPT_fPIC) ||
         LastPICArg->getOption().matches(options::OPT_fpic) ||
         LastPICArg->getOption().matches(options::OPT_fPIE) ||
         LastPICArg->getOption().matches(options::OPT_fpie))) {
      CmdArgs.push_back("-KPIC");
    }
  }

a5440 5
  if (getToolChain().getArch() == llvm::Triple::mips64)
    CmdArgs.push_back("-EB");
  else if (getToolChain().getArch() == llvm::Triple::mips64el)
    CmdArgs.push_back("-EL");

a5747 13
  } else if (getToolChain().getArch() == llvm::Triple::sparc ||
             getToolChain().getArch() == llvm::Triple::sparcv9) {
    Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                      options::OPT_fpic, options::OPT_fno_pic,
                                      options::OPT_fPIE, options::OPT_fno_PIE,
                                      options::OPT_fpie, options::OPT_fno_pie);
    if (LastPICArg &&
        (LastPICArg->getOption().matches(options::OPT_fPIC) ||
         LastPICArg->getOption().matches(options::OPT_fpic) ||
         LastPICArg->getOption().matches(options::OPT_fPIE) ||
         LastPICArg->getOption().matches(options::OPT_fpie))) {
      CmdArgs.push_back("-KPIC");
    }
d5871 19
a5889 2
  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);
d5978 1
a5978 1
    std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
d5982 5
a5986 32
  if (getToolChain().getArch() == llvm::Triple::mips ||
      getToolChain().getArch() == llvm::Triple::mipsel ||
      getToolChain().getArch() == llvm::Triple::mips64 ||
      getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                      options::OPT_fpic, options::OPT_fno_pic,
                                      options::OPT_fPIE, options::OPT_fno_PIE,
                                      options::OPT_fpie, options::OPT_fno_pie);
    if (LastPICArg &&
        (LastPICArg->getOption().matches(options::OPT_fPIC) ||
         LastPICArg->getOption().matches(options::OPT_fpic) ||
         LastPICArg->getOption().matches(options::OPT_fPIE) ||
         LastPICArg->getOption().matches(options::OPT_fpie))) {
      CmdArgs.push_back("-KPIC");
    }
  }
d6156 2
a6157 2
    StringRef ARMFloatABI = tools::arm::getARMFloatABI(
        getToolChain().getDriver(), Args, getToolChain().getTriple());
d6161 1
a6161 10

    // FIXME: remove krait check when GNU tools support krait cpu
    // for now replace it with -march=armv7-a  to avoid a lower
    // march from being picked in the absence of a cpu flag.
    Arg *A;
    if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
      StringRef(A->getValue()) == "krait")
        CmdArgs.push_back("-march=armv7-a");
    else
      Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
d6188 7
a6194 1
    Args.AddLastArg(CmdArgs, options::OPT_mfp32, options::OPT_mfp64);
d6467 20
a6486 2
  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);
d6534 2
a6535 2
        // FIXME: Exclude this for platforms with libgomp that don't require
        // librt. Most modern Linux platforms require it, but some may not.
@


1.1.1.4
log
@Import Clang 3.5svn r199312
@
text
@d37 1
a38 1
#include "llvm/Support/Program.h"
a217 1
        Args.hasArg(options::OPT_fprofile_instr_generate) ||
a1717 1
        Args.hasArg(options::OPT_fprofile_instr_generate) ||
a2603 13
  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      (Args.hasArg(options::OPT_fprofile_instr_use) ||
       Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
    D.Diag(diag::err_drv_argument_not_allowed_with)
      << "-fprofile-instr-generate" << "-fprofile-instr-use";

  Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);

  if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
    A->render(Args, CmdArgs);
  else if (Args.hasArg(options::OPT_fprofile_instr_use))
    CmdArgs.push_back("-fprofile-instr-use=pgo-data");

d2933 2
a2934 2
  Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
  Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
d3713 1
a3713 2
  if (Args.hasArg(options::OPT__SLASH_fallback) &&
      Output.getType() == types::TY_Object) {
d3920 4
d4767 1
a4767 1
  // Newer linkers support -demangle. Pass it if supported and not disabled by
d4769 19
a4787 2
  if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("-demangle");
a6257 1
  bool NeedsKPIC = false;
a6276 8
  } else if (getToolChain().getArch() == llvm::Triple::sparc) {
    CmdArgs.push_back("-32");
    CmdArgs.push_back("-Av8plusa");
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
a6338 9
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::systemz) {
    // Always pass an -march option, since our default of z10 is later
    // than the GNU assembler's default.
    StringRef CPUName = getSystemZTargetCPU(Args);
    CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
  }

  if (NeedsKPIC) {
d6350 5
d6424 1
a6424 2
  else if (ToolChain.getArch() == llvm::Triple::x86 ||
           ToolChain.getArch() == llvm::Triple::sparc)
a6448 2
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    return "/lib64/ld-linux.so.2";
a6510 4
  else if (ToolChain.getArch() == llvm::Triple::sparc)
    CmdArgs.push_back("elf32_sparc");
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    CmdArgs.push_back("elf64_sparc");
@


1.1.1.5
log
@Import Clang 3.5svn r201163.
@
text
@a12 1
#include "clang/Basic/LangOptions.h"
d24 1
a46 5
static bool hasMipsABIArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

d478 1
a478 1
    if (Triple.isOSBinFormatMachO())
d518 4
a664 4
      case llvm::Triple::MachO: {
        FloatABI = "soft";
        break;
      }
d749 1
a749 1
  } else if (Triple.isOSBinFormatMachO()) {
a752 1
        Triple.getEnvironment() == llvm::Triple::MachO ||
d840 2
a841 2
  const char *DefMips32CPU = "mips32r2";
  const char *DefMips64CPU = "mips64r2";
d1194 1
a1194 1
      if (Triple.isOSBinFormatMachO() && Triple.getArchName() == "x86_64h")
d1219 1
a1219 1
  if (Triple.isOSBinFormatMachO()) {
d1225 2
a1226 1
  // On Android use targets compatible with gcc
d1228 1
a1228 1
    return Is64Bit ? "x86-64" : "i686";
a1340 5
  if (Triple.getEnvironment() == llvm::Triple::Android) {
    // Add sse3 feature to comply with gcc on Android
    Features.push_back("+sse3");
  }

a1435 6

  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  }
a1700 3
        } else if (Value == "-compress-debug-sections" ||
                   Value == "--compress-debug-sections") {
          D.Diag(diag::warn_missing_debug_compression);
a1714 8
// Until ARM libraries are build separately, we have them all in one library
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
  if (TC.getArch() == llvm::Triple::arm)
    return "arm";
  else
    return TC.getArchName();
}

d1729 1
a1729 1
      Twine("libclang_rt.profile-") + getArchNameForCompilerRTLib(TC) + ".a");
d1743 1
a1743 2
      (Twine("libclang_rt.") + Sanitizer + "-" +
          getArchNameForCompilerRTLib(TC) + ".a"));
d1784 1
a1784 1
            getArchNameForCompilerRTLib(TC) + "-android.so"));
a1969 15
/// Add -x lang to \p CmdArgs for \p Input.
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
                             ArgStringList &CmdArgs) {
  // When using -verify-pch, we don't want to provide the type
  // 'precompiled-header' if it was inferred from the file extension
  if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
    return;

  CmdArgs.push_back("-x");
  if (Args.hasArg(options::OPT_rewrite_objc))
    CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
  else
    CmdArgs.push_back(types::getTypeName(Input.getType()));
}

a2025 2
  } else if (isa<VerifyPCHJobAction>(JA)) {
    CmdArgs.push_back("-verify-pch");
a2128 23
  // Android-specific defaults for PIC/PIE
  if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      PIC = true; // "-fpic"
      break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      PIC = true; // "-fPIC"
      IsPICLevelTwo = true;
      break;

    default:
      break;
    }
  }

d2559 1
a2559 1
      if (getToolChain().getTriple().isOSBinFormatMachO())
d2570 1
a2570 1
      if (getToolChain().getTriple().isOSBinFormatMachO())
d2599 1
a2599 5
  if (Args.hasFlag(options::OPT_fdebug_types_section,
                   options::OPT_fno_debug_types_section, false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-type-units");
  }
d2601 2
a2602 9
  if (Args.hasFlag(options::OPT_ffunction_sections,
                   options::OPT_fno_function_sections, false)) {
    CmdArgs.push_back("-ffunction-sections");
  }

  if (Args.hasFlag(options::OPT_fdata_sections,
                   options::OPT_fno_data_sections, false)) {
    CmdArgs.push_back("-fdata-sections");
  }
d2805 3
a2807 7
    // FIXME: This should behave just like a warning flag, and thus should also
    // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
    Arg *WriteStrings =
        Args.getLastArg(options::OPT_Wwrite_strings,
                        options::OPT_Wno_write_strings, options::OPT_w);
    if (WriteStrings &&
        WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
a3034 1
                               options::OPT_fstack_protector_strong,
d3037 1
a3037 3
      StackProtectorLevel = LangOptions::SSPOn;
    else if (A->getOption().matches(options::OPT_fstack_protector_strong))
      StackProtectorLevel = LangOptions::SSPStrong;
d3039 1
a3039 1
      StackProtectorLevel = LangOptions::SSPReq;
d3321 3
a3323 4
  // legacy is the default. Except for deployment taget of 10.5,
  // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
  // gets ignored silently.
  if (objcRuntime.isNonFragile()) {
d3682 5
a3686 3

    addDashXForInput(Args, II, CmdArgs);

d3867 1
a3867 1
    if (getToolChain().getTriple().isOSBinFormatMachO()) {
a4044 10
  // Consume all the warning flags. Usually this would be handled more
  // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
  // doesn't handle that so rather than warning about unused flags that are
  // actually used, we'll lie by omission instead.
  // FIXME: Stop lying and consume only the appropriate driver flags
  for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
                    ie = Args.filtered_end();
       it != ie; ++it)
    (*it)->claim();

d4104 1
a4104 1
  if (getToolChain().getTriple().isOSBinFormatMachO()) {
d4527 1
d4589 1
a4589 1
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7")
d4595 1
d4601 1
a4601 1
llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
d4624 1
a4624 1
    .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
a4633 12
void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
  llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
  T.setArch(Arch);

  if (Str == "x86_64h")
    T.setArchName(Str);
  else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
    T.setOS(llvm::Triple::UnknownOS);
    T.setEnvironment(llvm::Triple::MachO);
  }
}

d4702 1
a4702 1
  AddMachOArch(Args, CmdArgs);
d4713 2
a4714 1
        getMachOToolChain().isKernelStatic()) ||
d4735 1
a4735 1
void darwin::MachOTool::anchor() {}
d4737 3
a4739 3
void darwin::MachOTool::AddMachOArch(const ArgList &Args,
                                     ArgStringList &CmdArgs) const {
  StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
d4767 1
a4767 1
  const toolchains::MachO &MachOTC = getMachOToolChain();
d4808 1
a4808 1
    AddMachOArch(Args, CmdArgs);
d4844 1
a4844 1
    AddMachOArch(Args, CmdArgs);
d4853 1
a4853 1
  if (MachOTC.isTargetIOSBased())
d4867 19
a4885 1
  MachOTC.addMinVersionArgs(Args, CmdArgs);
d5000 89
a5088 2
      !Args.hasArg(options::OPT_nostartfiles))
    getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
d5101 13
a5113 3
    // We use arclite library for both ARC and subscripting support.
    getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);

d5137 1
a5137 1
    getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
d6073 1
a6073 2
  if (getToolChain().getArch() == llvm::Triple::arm ||
      getToolChain().getArch() == llvm::Triple::thumb) {
d6152 3
a6154 4
  // Many NetBSD architectures support more than one ABI.
  // Determine the correct emulation for ld.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
a6156 36
    break;
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    CmdArgs.push_back("-m");
    switch (getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::EABI:
    case llvm::Triple::GNUEABI:
      CmdArgs.push_back("armelf_nbsd_eabi");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      CmdArgs.push_back("armelf_nbsd_eabihf");
      break;
    default:
      CmdArgs.push_back("armelf_nbsd");
      break;
    }
    break;
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    if (hasMipsABIArg(Args, "32")) {
      CmdArgs.push_back("-m");
      if (getToolChain().getArch() == llvm::Triple::mips64)
        CmdArgs.push_back("elf32btsmip");
      else
        CmdArgs.push_back("elf32ltsmip");
   } else if (hasMipsABIArg(Args, "64")) {
     CmdArgs.push_back("-m");
     if (getToolChain().getArch() == llvm::Triple::mips64)
       CmdArgs.push_back("elf64btsmip");
     else
       CmdArgs.push_back("elf64ltsmip");
   }
   break;
  default:
    break;
d6197 2
a6198 3
    switch(getToolChain().getArch()) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
a6199 4
      break;
    default:
      break;
    }
d6423 5
d6430 4
a6433 7
  if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
    if (ToolChain.getTriple().isArch64Bit())
      return "/system/bin/linker64";
    else
      return "/system/bin/linker";
  } else if (ToolChain.getArch() == llvm::Triple::x86 ||
             ToolChain.getArch() == llvm::Triple::sparc)
d6448 1
a6448 1
    if (hasMipsABIArg(Args, "n32"))
d6531 1
a6531 1
    if (hasMipsABIArg(Args, "n32"))
d6537 1
a6537 1
    if (hasMipsABIArg(Args, "n32"))
d6548 2
a6549 2
    if (ToolChain.getArch() == llvm::Triple::arm ||
        ToolChain.getArch() == llvm::Triple::thumb)
a7160 3
  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   false))
    CmdArgs.push_back("-fverbose-asm");
@


1.1.1.6
log
@Import Clang 3.5svn r202566.
@
text
@d47 3
a49 13
static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                    options::OPT_fpic, options::OPT_fno_pic,
                                    options::OPT_fPIE, options::OPT_fno_PIE,
                                    options::OPT_fpie, options::OPT_fno_pie);
  if (!LastPICArg)
    return;
  if (LastPICArg->getOption().matches(options::OPT_fPIC) ||
      LastPICArg->getOption().matches(options::OPT_fpic) ||
      LastPICArg->getOption().matches(options::OPT_fPIE) ||
      LastPICArg->getOption().matches(options::OPT_fpie)) {
    CmdArgs.push_back("-KPIC");
  }
d218 20
a479 1
  case llvm::Triple::aarch64_be:
d483 1
a483 1
    if (Triple.isOSDarwin())
a579 5
  } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("+fp-only-sp");
    Features.push_back("-neon");
d647 2
a648 9
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      default:
        // FreeBSD defaults to soft float
        FloatABI = "soft";
        break;
      }
d726 1
a726 1
  if (FloatABI == "soft") {
a727 3
    // Also need to explicitly disable features which imply NEON.
    Features.push_back("-crypto");
  }
d754 1
a754 1
  } else if (Triple.isOSDarwin()) {
d1200 1
a1200 1
      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
d1225 1
a1225 1
  if (Triple.isOSDarwin()) {
a1259 1
  case llvm::Triple::aarch64_be:
d1295 1
a1295 2
  case llvm::Triple::sparcv9:
    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
a1445 2
  else
    Features.push_back("+neon");
a1481 1
  case llvm::Triple::aarch64_be:
a1528 38
namespace {
  struct ExceptionSettings {
    bool ExceptionsEnabled;
    bool ShouldUseExceptionTables;
    ExceptionSettings() : ExceptionsEnabled(false),
                          ShouldUseExceptionTables(false) {}
  };
} // end anonymous namespace.

// exceptionSettings() exists to share the logic between -cc1 and linker invocations.
static ExceptionSettings exceptionSettings(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  ExceptionSettings ES;

  // Are exceptions enabled by default?
  ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);

  // This keeps track of whether exceptions were explicitly turned on or off.
  bool DidHaveExplicitExceptionFlag = false;

  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
                               options::OPT_fno_exceptions)) {
    if (A->getOption().matches(options::OPT_fexceptions))
      ES.ExceptionsEnabled = true;
    else
      ES.ExceptionsEnabled = false;

    DidHaveExplicitExceptionFlag = true;
  }

  // Exception tables and cleanups can be enabled with -fexceptions even if the
  // language itself doesn't support exceptions.
  if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
    ES.ShouldUseExceptionTables = true;

  return ES;
}

d1551 22
a1572 2
   // Gather the exception settings from the command line arguments.
   ExceptionSettings ES = exceptionSettings(Args, Triple);
d1582 1
a1582 1
    ES.ShouldUseExceptionTables |=
d1587 1
a1587 1
    bool CXXExceptionsEnabled = ES.ExceptionsEnabled;
d1602 1
a1602 1
      ES.ShouldUseExceptionTables = true;
d1606 1
a1606 1
  if (ES.ShouldUseExceptionTables)
d1742 1
a1742 23
static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
  // The runtimes are located in the OS-specific resource directory.
  SmallString<128> Res(TC.getDriver().ResourceDir);
  llvm::sys::path::append(Res, "lib", TC.getOS());
  return Res;
}

// This adds the static libclang_rt.arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
static void addClangRTLinux(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibClangRT,
      Twine("libclang_rt.") + getArchNameForCompilerRTLib(TC) + ".a");

  CmdArgs.push_back(Args.MakeArgString(LibClangRT));
  CmdArgs.push_back("-lgcc_s");
  if (TC.getDriver().CCCIsCXX())
    CmdArgs.push_back("-lgcc_eh");
}

static void addProfileRT(
d1751 5
a1755 2
  SmallString<128> LibProfile = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibProfile,
d1761 1
a1761 1
static void addSanitizerRTLinkFlags(
d1765 7
a1771 5
  // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.a".
  SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibSanitizer,
                          (Twine("libclang_rt.") + Sanitizer + "-" +
                           getArchNameForCompilerRTLib(TC) + ".a"));
d1806 2
a1807 2
static void addAsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
d1809 4
a1812 4
    SmallString<128> LibAsan = getCompilerRTLibDir(TC);
    llvm::sys::path::append(LibAsan,
                            (Twine("libclang_rt.asan-") +
                             getArchNameForCompilerRTLib(TC) + "-android.so"));
d1816 1
a1816 1
      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
d1822 2
a1823 2
static void addTsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
d1825 1
a1825 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true);
d1830 2
a1831 2
static void addMsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
d1833 1
a1833 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true);
d1838 2
a1839 2
static void addLsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
d1841 1
a1841 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
d1846 3
a1848 3
static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs, bool IsCXX,
                       bool HasOtherSanitizerRt) {
d1852 1
a1852 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);
d1854 1
a1854 1
  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false);
d1859 1
a1859 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false);
d1862 2
a1863 2
static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
d1865 1
a1865 22
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
}

// Should be called before we add C++ ABI library.
static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
                                 ArgStringList &CmdArgs) {
  const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
  const Driver &D = TC.getDriver();
  if (Sanitize.needsUbsanRt())
    addUbsanRT(TC, Args, CmdArgs, D.CCCIsCXX(),
                    Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                    Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
  if (Sanitize.needsAsanRt())
    addAsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsTsanRt())
    addTsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsMsanRt())
    addMsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsLsanRt())
    addLsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsDfsanRt())
    addDfsanRT(TC, Args, CmdArgs);
d2470 1
a2470 2
  bool IsIntegratedAssemblerDefault =
      getToolChain().IsIntegratedAssemblerDefault();
d2472 1
a2472 1
                   IsIntegratedAssemblerDefault) ||
a2475 4
  if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
                    IsIntegratedAssemblerDefault))
    CmdArgs.push_back("-no-integrated-as");

d2503 4
a2506 5
      Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
                   options::OPT_fno_asynchronous_unwind_tables,
                   (getToolChain().IsUnwindTablesDefault() ||
                    getToolChain().getSanitizerArgs().needsUnwindTables()) &&
                       !KernelOrKext);
d2627 1
a2627 1
      if (getToolChain().getTriple().isOSDarwin())
d2638 1
a2638 1
      if (getToolChain().getTriple().isOSDarwin())
a2666 7
  // -gdwarf-aranges turns on the emission of the aranges section in the
  // backend.
  if (Args.hasArg(options::OPT_gdwarf_aranges)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-arange-section");
  }

a3293 10
  Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);

  if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
    if (!Args.getLastArg(options::OPT_fbuild_session_timestamp))
      D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);

    Args.AddLastArg(CmdArgs,
                    options::OPT_fmodules_validate_once_per_build_session);
  }

d3508 1
a3508 2
  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
                               options::OPT_fno_short_wchar))
d3952 1
a3952 1
    if (getToolChain().getTriple().isOSDarwin()) {
a4023 34
  // RTTI is currently not supported, so disable it by default.
  if (!Args.hasArg(options::OPT_frtti, options::OPT_fno_rtti))
    CmdArgs.push_back("-fno-rtti");

  const Driver &D = getToolChain().getDriver();
  Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
  Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
  if (MostGeneralArg && BestCaseArg)
    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
        << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);

  if (MostGeneralArg) {
    Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
    Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
    Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);

    Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
    Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
    if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << FirstConflict->getAsString(Args)
          << SecondConflict->getAsString(Args);

    if (SingleArg)
      CmdArgs.push_back("-fms-memptr-rep=single");
    else if (MultipleArg)
      CmdArgs.push_back("-fms-memptr-rep=multiple");
    else
      CmdArgs.push_back("-fms-memptr-rep=virtual");
  }

  if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
    A->render(Args, CmdArgs);

d4199 1
a4199 1
  if (getToolChain().getTriple().isOSDarwin()) {
d4641 4
a4644 20
  switch (Triple.getOS()) {
  case llvm::Triple::NetBSD:
    switch (Triple.getEnvironment()) {
    case llvm::Triple::GNUEABIHF:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::EABIHF:
    case llvm::Triple::EABI:
      return "arm926ej-s";
    default:
      return "strongarm";
    }
  default:
    switch (Triple.getEnvironment()) {
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      return "arm1176jzf-s";
    default:
      return "arm7tdmi";
    }
  }
a4693 5
bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

d4786 1
a4786 1
  // If -fno_integrated_as is used add -Q to the darwin assember driver to make
d4791 1
a4791 1
  if (Args.hasArg(options::OPT_fno_integrated_as)) {
d5332 1
a5332 1
  addProfileRT(getToolChain(), Args, CmdArgs);
d5444 1
a5444 1
  addProfileRT(getToolChain(), Args, CmdArgs);
a5456 1
  bool NeedsKPIC = false;
d5458 3
a5460 4
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    // When building 32-bit code on OpenBSD/amd64, we have to explicitly
    // instruct as in the base system to assemble 32-bit code.
d5462 1
a5462 3
    break;

  case llvm::Triple::ppc:
d5465 2
a5466 15
    break;

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    NeedsKPIC = true;
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
    break;

  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
d5479 11
a5489 6
    NeedsKPIC = true;
    break;
  }

  default:
    break;
a5491 3
  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);

d5814 11
a5824 1
    addAssemblerKPIC(Args, CmdArgs);
d5827 1
a5827 10
    const Driver &D = getToolChain().getDriver();
    llvm::Triple Triple = getToolChain().getTriple();
    StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);

    if (FloatABI == "hard") {
      CmdArgs.push_back("-mfpu=vfp");
    } else {
      CmdArgs.push_back("-mfpu=softvfp");
    }

a5828 1
    case llvm::Triple::GNUEABIHF:
d5839 11
a5849 6
    if (getToolChain().getArch() == llvm::Triple::sparc)
      CmdArgs.push_back("-Av8plusa");
    else
      CmdArgs.push_back("-Av9a");

    addAssemblerKPIC(Args, CmdArgs);
a5876 3
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
d5890 1
a5890 1
  if (IsPIE)
d5940 1
a5940 1
      else if (IsPIE)
d5953 1
a5953 1
    else if (Args.hasArg(options::OPT_shared) || IsPIE)
d6034 1
a6034 1
    if (Args.hasArg(options::OPT_shared) || IsPIE)
d6041 1
a6041 1
  addProfileRT(ToolChain, Args, CmdArgs);
d6055 3
a6057 4
  // GNU as needs different flags for creating the correct output format
  // on architectures with different ABIs or optional feature sets.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
d6059 5
a6063 3
    break;
  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
a6065 1
    break;
d6068 4
a6071 4
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
d6088 11
a6098 17
    addAssemblerKPIC(Args, CmdArgs);
    break;
  }

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  default:
    break;  
d6168 1
a6168 1
    if (mips::hasMipsAbiArg(Args, "32")) {
d6174 1
a6174 1
   } else if (mips::hasMipsAbiArg(Args, "64")) {
a6181 11

  case llvm::Triple::sparc:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32_sparc");
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf64_sparc");
    break;

d6273 1
a6273 1
  addProfileRT(getToolChain(), Args, CmdArgs);
d6383 13
a6395 2
  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);
d6478 1
a6478 1
    if (mips::hasMipsAbiArg(Args, "n32"))
a6493 15
static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  // Make use of compiler-rt if --rtlib option is used
  ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);

  switch(RLT) {
  case ToolChain::RLT_CompilerRT:
    addClangRTLinux(TC, Args, CmdArgs);
    break;
  case ToolChain::RLT_Libgcc:
    AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
    break;
  }
}

d6504 1
d6507 1
a6507 1
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
d6561 1
a6561 1
    if (mips::hasMipsAbiArg(Args, "n32"))
d6567 1
a6567 1
    if (mips::hasMipsAbiArg(Args, "n32"))
d6651 16
a6666 1
  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
d6668 1
a6668 1
  addProfileRT(getToolChain(), Args, CmdArgs);
d6697 1
a6697 1
      AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
d6708 1
a6708 1
        AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
d6782 1
a6782 1
  addProfileRT(getToolChain(), Args, CmdArgs);
d6984 1
a6984 1
  addProfileRT(getToolChain(), Args, CmdArgs);
a7134 2
  if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
    CmdArgs.push_back("/Z7");
d7188 1
a7188 4
  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  if (Args.hasArg(options::OPT_g_Group))
d7190 1
a7190 1

a7222 7
  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
  if (EH.ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");

@


1.1.1.6.2.1
log
@Rebase.
@
text
@a31 1
#include "llvm/Support/Compression.h"
a297 3

    if (isa<PrecompileJobAction>(JA))
      CmdArgs.push_back("-module-file-deps");
d443 20
a470 2
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
a471 5
  case llvm::Triple::armeb:
    if (Triple.isOSDarwin() || Triple.isOSWindows())
      return true;
    return false;

a641 5
    // FIXME: this is invalid for WindowsCE
    case llvm::Triple::Win32:
      FloatABI = "hard";
      break;

d669 4
d685 1
a685 3
        if (Triple.getOS() != llvm::Triple::UnknownOS ||
            !Triple.isOSBinFormatMachO())
          D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
d757 1
a757 1
  const char *ABIName = nullptr;
d760 1
a760 1
  } else if (Triple.isOSBinFormatMachO()) {
d764 1
a764 2
        (Triple.getOS() == llvm::Triple::UnknownOS &&
         Triple.getObjectFormat() == llvm::Triple::MachO) ||
a769 3
  } else if (Triple.isOSWindows()) {
    // FIXME: this is invalid for WindowsCE
    ABIName = "aapcs";
d837 7
a843 73
  // llvm does not support reserving registers in general. There is support
  // for reserving r9 on ARM though (defined as a platform-specific register
  // in ARM EABI).
  if (Args.hasArg(options::OPT_ffixed_r9)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-reserve-r9");
  }
}

/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
/// targeting.
static std::string getAArch64TargetCPU(const ArgList &Args) {
  // If we have -mcpu=, use that.
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  // At some point, we may need to check -march here, but for now we only
  // one arm64 architecture.

  // Make sure we pick "cyclone" if -arch is used.
  // FIXME: Should this be picked by checking the target triple instead?
  if (Args.getLastArg(options::OPT_arch))
    return "cyclone";

  return "generic";
}

void Clang::AddAArch64TargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);

  if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float, true))
    CmdArgs.push_back("-no-implicit-float");

  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
    ABIName = A->getValue();
  else if (Triple.isOSDarwin())
    ABIName = "darwinpcs";
  else
    ABIName = "aapcs";

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  CmdArgs.push_back("-target-cpu");
  CmdArgs.push_back(Args.MakeArgString(getAArch64TargetCPU(Args)));

  if (Args.hasArg(options::OPT_mstrict_align)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-strict-align");
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }
d965 1
a965 2
    StringRef Val = StringRef(A->getValue());
    if (Val == "2008")
a966 5
    else if (Val == "legacy")
      Features.push_back("-nan2008");
    else
      D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
d1226 1
a1226 1
    return nullptr; // This routine is only handling x86 targets.
d1267 1
a1267 3
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
    return getAArch64TargetCPU(Args);
a1269 1
  case llvm::Triple::armeb:
a1270 1
  case llvm::Triple::thumbeb:
a1401 11

  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  }
a1461 9

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
a1478 1
  case llvm::Triple::armeb:
a1479 1
  case llvm::Triple::thumbeb:
a1492 2
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
d1549 1
a1549 2
// exceptionSettings() exists to share the logic between -cc1 and linker
// invocations.
d1651 13
a1722 1
    bool CompressDebugSections = false;
d1748 1
a1748 4
          CompressDebugSections = true;
        } else if (Value == "-nocompress-debug-sections" ||
                   Value == "--nocompress-debug-sections") {
          CompressDebugSections = false;
a1754 2
        } else if (Value.startswith("-gdwarf-")) {
          CmdArgs.push_back(Value.data());
a1760 6
    if (CompressDebugSections) {
      if (llvm::zlib::isAvailable())
        CmdArgs.push_back("-compress-debug-sections");
      else
        D.Diag(diag::warn_debug_compression_unavailable);
    }
d1765 1
a1765 2
  if (TC.getArch() == llvm::Triple::arm ||
      TC.getArch() == llvm::Triple::armeb)
d1774 1
a1774 5
  const llvm::Triple &Triple = TC.getTriple();
  // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
  StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
    "freebsd" : TC.getOS();
  llvm::sys::path::append(Res, "lib", OSLibName);
d1778 1
a1778 1
// This adds the static libclang_rt.builtins-arch.a directly to the command line
d1784 2
a1785 3
  llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
                                          getArchNameForCompilerRTLib(TC) +
                                          ".a");
a1801 7
  // -fprofile-instr-generate requires position-independent code to build with
  // shared objects.  Link against the right archive.
  const char *Lib = "libclang_rt.profile-";
  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      Args.hasArg(options::OPT_shared))
    Lib = "libclang_rt.profile-pic-";

d1804 1
a1804 1
      Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");
d1809 5
a1813 7
static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
                                              const StringRef Sanitizer,
                                              bool Shared) {
  // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
  // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
  const char *EnvSuffix =
    TC.getTriple().getEnvironment() == llvm::Triple::Android ?  "-android" : "";
d1816 2
a1817 14
                          Twine("libclang_rt.") + Sanitizer + "-" +
                              getArchNameForCompilerRTLib(TC) + EnvSuffix +
                              (Shared ? ".so" : ".a"));
  return LibSanitizer;
}

static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const StringRef Sanitizer,
                                    bool BeforeLibStdCXX,
                                    bool ExportSymbols = true,
                                    bool LinkDeps = true) {
  SmallString<128> LibSanitizer =
      getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
d1833 4
a1836 9
  if (LinkDeps) {
    // Link sanitizer dependencies explicitly
    CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lrt");
    CmdArgs.push_back("-lm");
    // There's no libdl on FreeBSD.
    if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
      CmdArgs.push_back("-ldl");
  }
d1853 7
a1859 17
                      ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
  if (Shared) {
    // Link dynamic runtime if necessary.
    SmallString<128> LibSanitizer =
        getSanitizerRTLibName(TC, "asan", Shared);
    CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
  }

  // Do not link static runtime to DSOs or if compiling for Android.
  if (Args.hasArg(options::OPT_shared) ||
      (TC.getTriple().getEnvironment() == llvm::Triple::Android))
    return;

  if (Shared) {
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
                            /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
                            /*LinkDeps*/ false);
d1861 2
a1862 3
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
    if (IsCXX)
      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
d1924 1
a1924 1
    addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX());
d1994 1
a1994 2
    SmallString<128> T(
        Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
d2027 7
d2035 1
a2035 2
/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
d2051 1
a2051 1
    // Don't vectorize -Oz, unless it's the slp vectorizer.
d2053 1
a2053 1
      return isSlpVec;
a2089 5
  bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
  bool IsWindowsCygnus =
      getToolChain().getTriple().isWindowsCygwinEnvironment();
  bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();

a2101 16
  const llvm::Triple TT(TripleStr);
  if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                           TT.getArch() == llvm::Triple::thumb)) {
    unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
    unsigned Version;
    TT.getArchName().substr(Offset).getAsInteger(10, Version);
    if (Version < 7)
      D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
                                                << TripleStr;
  }

  // Push all default warning arguments that are specific to
  // the given target.  These come before user provided warning options
  // are provided.
  getToolChain().addClangWarningOptions(CmdArgs);

d2198 1
a2198 1
      if (!IsWindowsMSVC)
d2209 2
a2210 3
      // Enable the following experimental checkers for testing.
      CmdArgs.push_back(
          "-analyzer-checker=security.insecureAPI.UncheckedReturn");
a2244 1
    case llvm::Triple::armeb:
a2245 3
    case llvm::Triple::thumbeb:
    case llvm::Triple::aarch64:
    case llvm::Triple::arm64:
d2304 2
a2305 3
  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
                       Triple.getArch() == llvm::Triple::arm64 ||
                       Triple.getArch() == llvm::Triple::aarch64))
a2382 3
  // We turn strict aliasing off by default if we're in CL mode, since MSVC
  // doesn't do any TBAA.
  bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
d2384 1
a2384 1
                    options::OPT_fno_strict_aliasing, TBAAOnByDefault))
d2531 1
a2531 2
  if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
                               options::OPT_fno_fast_math))
a2621 1
  case llvm::Triple::armeb:
a2622 1
  case llvm::Triple::thumbeb:
a2625 7
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
    AddAArch64TargetArgs(Args, CmdArgs);
    break;

d2948 1
a2948 1
    else if (IsWindowsMSVC)
d2991 3
d3129 2
a3130 1
  if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
d3200 3
a3202 4
    if (A->getOption().matches(options::OPT_fstack_protector)) {
      StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
        getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
    } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
d3250 1
a3250 7
        if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
          CmdArgs.push_back("-aarch64-strict-align");
        else
          CmdArgs.push_back("-arm-strict-align");
d3253 1
a3253 7
        if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
          CmdArgs.push_back("-aarch64-no-strict-align");
        else
          CmdArgs.push_back("-arm-no-strict-align");
a3266 5
  } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                                  TT.getArch() == llvm::Triple::thumb)) {
    // Windows on ARM expects restricted IT blocks
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-restrict-it");
a3278 9
  if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
    A->render(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
    A->render(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
    A->render(Args, CmdArgs);

a3335 8
  // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
  // all #included headers are part of modules.
  if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
                   options::OPT_fno_modules_strict_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-strict-decluse");
  }

a3368 7
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path)) {
    A->claim();
    if (HaveModules) {
      A->render(Args, CmdArgs);
    }
  }

a3383 2
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);

d3430 6
a3435 5
  if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
                    options::OPT_fno_use_cxa_atexit,
                    !IsWindowsCygnus && !IsWindowsGNU &&
                    getToolChain().getArch() != llvm::Triple::hexagon &&
                    getToolChain().getArch() != llvm::Triple::xcore) ||
d3441 1
a3441 1
                   IsWindowsMSVC))
d3447 4
a3450 3
                   (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
                                                  options::OPT_fno_ms_extensions,
                                                  true))))
d3455 2
a3456 1
                   IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version)) {
d3473 2
a3474 1
                   options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
d3744 1
a3744 1
  bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
d3751 3
a3753 6
  // -fslp-vectorize is enabled based on the optimization level selected.
  bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
  OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
    options::OPT_fslp_vectorize;
  if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
                   options::OPT_fno_slp_vectorize, EnableSLPVec))
d3905 1
a3905 2
      Output.getType() == types::TY_Object &&
      (InputType == types::TY_C || InputType == types::TY_CXX)) {
d3909 1
a3909 9
    // RTTI support in clang-cl is a work in progress.  Fall back to MSVC early
    // if we are using 'clang-cl /fallback /GR'.
    // FIXME: Remove this when RTTI is finished.
    if (Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, false)) {
      D.Diag(diag::warn_drv_rtti_fallback) << CLCommand->getExecutable();
      C.addCommand(CLCommand);
    } else {
      C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
    }
a4224 7
    if (Args.hasArg(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    if (Args.hasArg(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    if (Args.hasArg(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");

d4716 1
a4716 2
  switch (Triple.getOS()) {
  case llvm::Triple::NetBSD:
a4718 6
    break;
  case llvm::Triple::Win32:
    // FIXME: this is invalid for WindowsCE
    return "cortex-a9";
  default:
    break;
d4721 41
a4761 36
  const char *result = nullptr;
  size_t offset = StringRef::npos;
  if (MArch.startswith("arm"))
    offset = 3;
  if (MArch.startswith("thumb"))
    offset = 5;
  if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb")
    offset += 2;
  if (offset != StringRef::npos)
    result = llvm::StringSwitch<const char *>(MArch.substr(offset))
      .Cases("v2", "v2a", "arm2")
      .Case("v3", "arm6")
      .Case("v3m", "arm7m")
      .Case("v4", "strongarm")
      .Case("v4t", "arm7tdmi")
      .Cases("v5", "v5t", "arm10tdmi")
      .Cases("v5e", "v5te", "arm1022e")
      .Case("v5tej", "arm926ej-s")
      .Cases("v6", "v6k", "arm1136jf-s")
      .Case("v6j", "arm1136j-s")
      .Cases("v6z", "v6zk", "arm1176jzf-s")
      .Case("v6t2", "arm1156t2-s")
      .Cases("v6m", "v6-m", "cortex-m0")
      .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8")
      .Cases("v7s", "v7-s", "swift")
      .Cases("v7r", "v7-r", "cortex-r4")
      .Cases("v7m", "v7-m", "cortex-m3")
      .Cases("v7em", "v7e-m", "cortex-m4")
      .Cases("v8", "v8a", "v8-a", "cortex-a53")
      .Default(nullptr);
  else
    result = llvm::StringSwitch<const char *>(MArch)
      .Case("ep9312", "ep9312")
      .Case("iwmmxt", "iwmmxt")
      .Case("xscale", "xscale")
      .Default(nullptr);
a4765 3
  // If all else failed, return the most base CPU with thumb interworking
  // supported by LLVM.
  // FIXME: Should warn once that we're falling back.
a4830 1
    .Case("cyclone", "v8")
a4864 1
    .Case("arm64", llvm::Triple::arm64)
d4881 1
a4881 1
    T.setObjectFormat(llvm::Triple::MachO);
a5185 6
enum LibOpenMP {
  LibUnknown,
  LibGOMP,
  LibIOMP5
};

d5237 2
a5238 14
  LibOpenMP UsedOpenMPLib = LibUnknown;
  if (Args.hasArg(options::OPT_fopenmp)) {
    UsedOpenMPLib = LibGOMP;
  } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
    UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
        .Case("libgomp",  LibGOMP)
        .Case("libiomp5", LibIOMP5)
        .Default(LibUnknown);
    if (UsedOpenMPLib == LibUnknown)
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
        << A->getOption().getName() << A->getValue();
  }
  switch (UsedOpenMPLib) {
  case LibGOMP:
a5239 7
    break;
  case LibIOMP5:
    CmdArgs.push_back("-liomp5");
    break;
  case LibUnknown:
    break;
  }
d5977 1
a5977 3
             getToolChain().getArch() == llvm::Triple::armeb ||
             getToolChain().getArch() == llvm::Triple::thumb ||
             getToolChain().getArch() == llvm::Triple::thumbeb) {
d5979 1
a5979 1
    const llvm::Triple &Triple = getToolChain().getTriple();
d6095 1
a6095 1
    const char *crt1 = nullptr;
d6109 1
a6109 1
    const char *crtbegin = nullptr;
a6199 2
  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);

d6221 1
a6221 3
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb: {
a6292 1
  CmdArgs.push_back("--eh-frame-hdr");
d6298 1
a6314 1
  case llvm::Triple::armeb:
a6315 1
  case llvm::Triple::thumbeb:
d6399 1
a6399 1
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
a6400 4
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
d6479 1
a6479 1
    CmdArgs.push_back("-mppc64");
a6480 1
    CmdArgs.push_back("-mlittle-endian");
d6489 1
a6489 2
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::armeb) {
d6493 1
a6493 2
    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
        MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
d6587 1
a6587 1
static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
d6630 1
a6630 2
  else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
           ToolChain.getArch() == llvm::Triple::arm64)
a6631 3
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
           ToolChain.getArch() == llvm::Triple::arm64_be)
    return "/lib/ld-linux-aarch64_be.so.1";
a6637 6
  } else if (ToolChain.getArch() == llvm::Triple::armeb ||
             ToolChain.getArch() == llvm::Triple::thumbeb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";        /* TODO: check which dynamic linker name.  */
    else
      return "/lib/ld-linux.so.3";              /* TODO: check which dynamic linker name.  */
d6686 1
a6686 6
    !Args.hasArg(options::OPT_static) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
     // On Android every code is PIC so every executable is PIE
     // Cannot use isPIEDefault here since otherwise
     // PIE only logic will be enabled during compilation
     isAndroid);
d6722 1
a6722 2
  else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
           ToolChain.getArch() == llvm::Triple::arm64)
a6723 3
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
           ToolChain.getArch() == llvm::Triple::arm64_be)
    CmdArgs.push_back("aarch64_be_linux");
a6726 3
  else if (ToolChain.getArch() == llvm::Triple::armeb
           ||  ToolChain.getArch() == llvm::Triple::thumbeb)
    CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME.  */
a6730 2
  else if (ToolChain.getArch() == llvm::Triple::ppc64le)
    CmdArgs.push_back("elf64lppc");
d6758 1
a6758 3
        ToolChain.getArch() == llvm::Triple::armeb ||
        ToolChain.getArch() == llvm::Triple::thumb ||
        ToolChain.getArch() == llvm::Triple::thumbeb)
a6769 1
      ToolChain.getArch() == llvm::Triple::armeb ||
a6770 1
      ToolChain.getArch() == llvm::Triple::thumbeb ||
d6784 1
a6784 1
      const char *crt1 = nullptr;
d6852 2
a6853 14
      LibOpenMP UsedOpenMPLib = LibUnknown;
      if (Args.hasArg(options::OPT_fopenmp)) {
        UsedOpenMPLib = LibGOMP;
      } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
        UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
            .Case("libgomp",  LibGOMP)
            .Case("libiomp5", LibIOMP5)
            .Default(LibUnknown);
        if (UsedOpenMPLib == LibUnknown)
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << A->getValue();
      }
      switch (UsedOpenMPLib) {
      case LibGOMP:
a6858 6
        break;
      case LibIOMP5:
        CmdArgs.push_back("-liomp5");
        break;
      case LibUnknown:
        break;
d6860 1
d6863 2
a6864 3
      if (!isAndroid &&
          (Args.hasArg(options::OPT_pthread) ||
           Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown))
a7154 9
static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs,
                                  const StringRef RTName) {
  SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
  llvm::sys::path::append(LibSanitizer,
                          Twine("clang_rt.") + RTName + ".lib");
  CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
}

a7176 4
  if (Args.hasArg(options::OPT_g_Group)) {
    CmdArgs.push_back("-debug");
  }

d7191 2
a7192 1
    // FIXME: Handle 64-bit.
d7194 1
a7194 2
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
                            "asan_dll_thunk-i386");
d7196 1
a7196 2
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
d7198 2
a7296 9
  if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
                               options::OPT_fno_function_sections))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
                          ? "/Gy"
                          : "/Gy-");
  if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
                               options::OPT_fno_data_sections))
    CmdArgs.push_back(
        A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
d7357 2
a7358 3
  if (Arg *A = Args.getLastArg(options::OPT_g_Group))
    if (!A->getOption().matches(options::OPT_g0))
      CmdArgs.push_back("-g");
@


1.1.1.7
log
@Import Clang 3.5svn r209886.
@
text
@a31 1
#include "llvm/Support/Compression.h"
a297 3

    if (isa<PrecompileJobAction>(JA))
      CmdArgs.push_back("-module-file-deps");
d443 20
a470 2
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
a471 5
  case llvm::Triple::armeb:
    if (Triple.isOSDarwin() || Triple.isOSWindows())
      return true;
    return false;

a641 5
    // FIXME: this is invalid for WindowsCE
    case llvm::Triple::Win32:
      FloatABI = "hard";
      break;

d669 4
d685 1
a685 3
        if (Triple.getOS() != llvm::Triple::UnknownOS ||
            !Triple.isOSBinFormatMachO())
          D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
d757 1
a757 1
  const char *ABIName = nullptr;
d760 1
a760 1
  } else if (Triple.isOSBinFormatMachO()) {
d764 1
a764 2
        (Triple.getOS() == llvm::Triple::UnknownOS &&
         Triple.getObjectFormat() == llvm::Triple::MachO) ||
a769 3
  } else if (Triple.isOSWindows()) {
    // FIXME: this is invalid for WindowsCE
    ABIName = "aapcs";
d837 7
a843 73
  // llvm does not support reserving registers in general. There is support
  // for reserving r9 on ARM though (defined as a platform-specific register
  // in ARM EABI).
  if (Args.hasArg(options::OPT_ffixed_r9)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-reserve-r9");
  }
}

/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
/// targeting.
static std::string getAArch64TargetCPU(const ArgList &Args) {
  // If we have -mcpu=, use that.
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  // At some point, we may need to check -march here, but for now we only
  // one arm64 architecture.

  // Make sure we pick "cyclone" if -arch is used.
  // FIXME: Should this be picked by checking the target triple instead?
  if (Args.getLastArg(options::OPT_arch))
    return "cyclone";

  return "generic";
}

void Clang::AddAArch64TargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);

  if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float, true))
    CmdArgs.push_back("-no-implicit-float");

  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
    ABIName = A->getValue();
  else if (Triple.isOSDarwin())
    ABIName = "darwinpcs";
  else
    ABIName = "aapcs";

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  CmdArgs.push_back("-target-cpu");
  CmdArgs.push_back(Args.MakeArgString(getAArch64TargetCPU(Args)));

  if (Args.hasArg(options::OPT_mstrict_align)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-strict-align");
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }
d965 1
a965 2
    StringRef Val = StringRef(A->getValue());
    if (Val == "2008")
a966 5
    else if (Val == "legacy")
      Features.push_back("-nan2008");
    else
      D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
d1226 1
a1226 1
    return nullptr; // This routine is only handling x86 targets.
d1267 1
a1267 3
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
    return getAArch64TargetCPU(Args);
a1269 1
  case llvm::Triple::armeb:
a1270 1
  case llvm::Triple::thumbeb:
a1401 11

  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  }
a1461 9

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
a1478 1
  case llvm::Triple::armeb:
a1479 1
  case llvm::Triple::thumbeb:
a1492 2
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
d1549 1
a1549 2
// exceptionSettings() exists to share the logic between -cc1 and linker
// invocations.
d1651 13
a1722 1
    bool CompressDebugSections = false;
d1748 1
a1748 4
          CompressDebugSections = true;
        } else if (Value == "-nocompress-debug-sections" ||
                   Value == "--nocompress-debug-sections") {
          CompressDebugSections = false;
a1754 2
        } else if (Value.startswith("-gdwarf-")) {
          CmdArgs.push_back(Value.data());
a1760 6
    if (CompressDebugSections) {
      if (llvm::zlib::isAvailable())
        CmdArgs.push_back("-compress-debug-sections");
      else
        D.Diag(diag::warn_debug_compression_unavailable);
    }
d1765 1
a1765 2
  if (TC.getArch() == llvm::Triple::arm ||
      TC.getArch() == llvm::Triple::armeb)
d1774 1
a1774 5
  const llvm::Triple &Triple = TC.getTriple();
  // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
  StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
    "freebsd" : TC.getOS();
  llvm::sys::path::append(Res, "lib", OSLibName);
d1778 1
a1778 1
// This adds the static libclang_rt.builtins-arch.a directly to the command line
d1784 2
a1785 3
  llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
                                          getArchNameForCompilerRTLib(TC) +
                                          ".a");
a1801 7
  // -fprofile-instr-generate requires position-independent code to build with
  // shared objects.  Link against the right archive.
  const char *Lib = "libclang_rt.profile-";
  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      Args.hasArg(options::OPT_shared))
    Lib = "libclang_rt.profile-pic-";

d1804 1
a1804 1
      Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");
d1809 5
a1813 7
static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
                                              const StringRef Sanitizer,
                                              bool Shared) {
  // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
  // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
  const char *EnvSuffix =
    TC.getTriple().getEnvironment() == llvm::Triple::Android ?  "-android" : "";
d1816 2
a1817 14
                          Twine("libclang_rt.") + Sanitizer + "-" +
                              getArchNameForCompilerRTLib(TC) + EnvSuffix +
                              (Shared ? ".so" : ".a"));
  return LibSanitizer;
}

static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const StringRef Sanitizer,
                                    bool BeforeLibStdCXX,
                                    bool ExportSymbols = true,
                                    bool LinkDeps = true) {
  SmallString<128> LibSanitizer =
      getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
d1833 4
a1836 9
  if (LinkDeps) {
    // Link sanitizer dependencies explicitly
    CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lrt");
    CmdArgs.push_back("-lm");
    // There's no libdl on FreeBSD.
    if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
      CmdArgs.push_back("-ldl");
  }
d1853 7
a1859 17
                      ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
  if (Shared) {
    // Link dynamic runtime if necessary.
    SmallString<128> LibSanitizer =
        getSanitizerRTLibName(TC, "asan", Shared);
    CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
  }

  // Do not link static runtime to DSOs or if compiling for Android.
  if (Args.hasArg(options::OPT_shared) ||
      (TC.getTriple().getEnvironment() == llvm::Triple::Android))
    return;

  if (Shared) {
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
                            /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
                            /*LinkDeps*/ false);
d1861 2
a1862 3
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
    if (IsCXX)
      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
d1924 1
a1924 1
    addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX());
d1994 1
a1994 2
    SmallString<128> T(
        Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
d2027 7
d2035 1
a2035 2
/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
d2051 1
a2051 1
    // Don't vectorize -Oz, unless it's the slp vectorizer.
d2053 1
a2053 1
      return isSlpVec;
a2089 5
  bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
  bool IsWindowsCygnus =
      getToolChain().getTriple().isWindowsCygwinEnvironment();
  bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();

a2101 16
  const llvm::Triple TT(TripleStr);
  if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                           TT.getArch() == llvm::Triple::thumb)) {
    unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
    unsigned Version;
    TT.getArchName().substr(Offset).getAsInteger(10, Version);
    if (Version < 7)
      D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
                                                << TripleStr;
  }

  // Push all default warning arguments that are specific to
  // the given target.  These come before user provided warning options
  // are provided.
  getToolChain().addClangWarningOptions(CmdArgs);

d2198 1
a2198 1
      if (!IsWindowsMSVC)
d2209 2
a2210 3
      // Enable the following experimental checkers for testing.
      CmdArgs.push_back(
          "-analyzer-checker=security.insecureAPI.UncheckedReturn");
a2244 1
    case llvm::Triple::armeb:
a2245 3
    case llvm::Triple::thumbeb:
    case llvm::Triple::aarch64:
    case llvm::Triple::arm64:
d2304 2
a2305 3
  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
                       Triple.getArch() == llvm::Triple::arm64 ||
                       Triple.getArch() == llvm::Triple::aarch64))
a2382 3
  // We turn strict aliasing off by default if we're in CL mode, since MSVC
  // doesn't do any TBAA.
  bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
d2384 1
a2384 1
                    options::OPT_fno_strict_aliasing, TBAAOnByDefault))
d2531 1
a2531 2
  if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
                               options::OPT_fno_fast_math))
a2621 1
  case llvm::Triple::armeb:
a2622 1
  case llvm::Triple::thumbeb:
a2625 7
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
  case llvm::Triple::arm64:
  case llvm::Triple::arm64_be:
    AddAArch64TargetArgs(Args, CmdArgs);
    break;

d2948 1
a2948 1
    else if (IsWindowsMSVC)
d2991 3
d3129 2
a3130 1
  if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
d3200 3
a3202 4
    if (A->getOption().matches(options::OPT_fstack_protector)) {
      StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
        getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
    } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
d3250 1
a3250 7
        if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
          CmdArgs.push_back("-aarch64-strict-align");
        else
          CmdArgs.push_back("-arm-strict-align");
d3253 1
a3253 7
        if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
            getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
          CmdArgs.push_back("-aarch64-no-strict-align");
        else
          CmdArgs.push_back("-arm-no-strict-align");
a3266 5
  } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                                  TT.getArch() == llvm::Triple::thumb)) {
    // Windows on ARM expects restricted IT blocks
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-restrict-it");
a3278 9
  if (Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
    A->render(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
    A->render(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
    A->render(Args, CmdArgs);

a3335 8
  // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
  // all #included headers are part of modules.
  if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
                   options::OPT_fno_modules_strict_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-strict-decluse");
  }

a3368 7
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path)) {
    A->claim();
    if (HaveModules) {
      A->render(Args, CmdArgs);
    }
  }

a3383 2
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);

d3430 6
a3435 5
  if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
                    options::OPT_fno_use_cxa_atexit,
                    !IsWindowsCygnus && !IsWindowsGNU &&
                    getToolChain().getArch() != llvm::Triple::hexagon &&
                    getToolChain().getArch() != llvm::Triple::xcore) ||
d3441 1
a3441 1
                   IsWindowsMSVC))
d3447 4
a3450 3
                   (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
                                                  options::OPT_fno_ms_extensions,
                                                  true))))
d3455 2
a3456 1
                   IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version)) {
d3473 2
a3474 1
                   options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
d3744 1
a3744 1
  bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
d3751 3
a3753 6
  // -fslp-vectorize is enabled based on the optimization level selected.
  bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
  OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
    options::OPT_fslp_vectorize;
  if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
                   options::OPT_fno_slp_vectorize, EnableSLPVec))
d3905 1
a3905 2
      Output.getType() == types::TY_Object &&
      (InputType == types::TY_C || InputType == types::TY_CXX)) {
d3909 1
a3909 9
    // RTTI support in clang-cl is a work in progress.  Fall back to MSVC early
    // if we are using 'clang-cl /fallback /GR'.
    // FIXME: Remove this when RTTI is finished.
    if (Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti, false)) {
      D.Diag(diag::warn_drv_rtti_fallback) << CLCommand->getExecutable();
      C.addCommand(CLCommand);
    } else {
      C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
    }
a4224 7
    if (Args.hasArg(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    if (Args.hasArg(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    if (Args.hasArg(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");

d4716 1
a4716 2
  switch (Triple.getOS()) {
  case llvm::Triple::NetBSD:
a4718 6
    break;
  case llvm::Triple::Win32:
    // FIXME: this is invalid for WindowsCE
    return "cortex-a9";
  default:
    break;
d4721 41
a4761 36
  const char *result = nullptr;
  size_t offset = StringRef::npos;
  if (MArch.startswith("arm"))
    offset = 3;
  if (MArch.startswith("thumb"))
    offset = 5;
  if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb")
    offset += 2;
  if (offset != StringRef::npos)
    result = llvm::StringSwitch<const char *>(MArch.substr(offset))
      .Cases("v2", "v2a", "arm2")
      .Case("v3", "arm6")
      .Case("v3m", "arm7m")
      .Case("v4", "strongarm")
      .Case("v4t", "arm7tdmi")
      .Cases("v5", "v5t", "arm10tdmi")
      .Cases("v5e", "v5te", "arm1022e")
      .Case("v5tej", "arm926ej-s")
      .Cases("v6", "v6k", "arm1136jf-s")
      .Case("v6j", "arm1136j-s")
      .Cases("v6z", "v6zk", "arm1176jzf-s")
      .Case("v6t2", "arm1156t2-s")
      .Cases("v6m", "v6-m", "cortex-m0")
      .Cases("v7", "v7a", "v7-a", "v7l", "v7-l", "cortex-a8")
      .Cases("v7s", "v7-s", "swift")
      .Cases("v7r", "v7-r", "cortex-r4")
      .Cases("v7m", "v7-m", "cortex-m3")
      .Cases("v7em", "v7e-m", "cortex-m4")
      .Cases("v8", "v8a", "v8-a", "cortex-a53")
      .Default(nullptr);
  else
    result = llvm::StringSwitch<const char *>(MArch)
      .Case("ep9312", "ep9312")
      .Case("iwmmxt", "iwmmxt")
      .Case("xscale", "xscale")
      .Default(nullptr);
a4765 3
  // If all else failed, return the most base CPU with thumb interworking
  // supported by LLVM.
  // FIXME: Should warn once that we're falling back.
a4830 1
    .Case("cyclone", "v8")
a4864 1
    .Case("arm64", llvm::Triple::arm64)
d4881 1
a4881 1
    T.setObjectFormat(llvm::Triple::MachO);
a5185 6
enum LibOpenMP {
  LibUnknown,
  LibGOMP,
  LibIOMP5
};

d5237 2
a5238 14
  LibOpenMP UsedOpenMPLib = LibUnknown;
  if (Args.hasArg(options::OPT_fopenmp)) {
    UsedOpenMPLib = LibGOMP;
  } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
    UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
        .Case("libgomp",  LibGOMP)
        .Case("libiomp5", LibIOMP5)
        .Default(LibUnknown);
    if (UsedOpenMPLib == LibUnknown)
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
        << A->getOption().getName() << A->getValue();
  }
  switch (UsedOpenMPLib) {
  case LibGOMP:
a5239 7
    break;
  case LibIOMP5:
    CmdArgs.push_back("-liomp5");
    break;
  case LibUnknown:
    break;
  }
d5977 1
a5977 3
             getToolChain().getArch() == llvm::Triple::armeb ||
             getToolChain().getArch() == llvm::Triple::thumb ||
             getToolChain().getArch() == llvm::Triple::thumbeb) {
d5979 1
a5979 1
    const llvm::Triple &Triple = getToolChain().getTriple();
d6095 1
a6095 1
    const char *crt1 = nullptr;
d6109 1
a6109 1
    const char *crtbegin = nullptr;
a6199 2
  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);

d6221 1
a6221 3
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb: {
a6292 1
  CmdArgs.push_back("--eh-frame-hdr");
d6298 1
a6314 1
  case llvm::Triple::armeb:
a6315 1
  case llvm::Triple::thumbeb:
d6399 1
a6399 1
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
a6400 4
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
d6479 1
a6479 1
    CmdArgs.push_back("-mppc64");
a6480 1
    CmdArgs.push_back("-mlittle-endian");
d6489 1
a6489 2
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::armeb) {
d6493 1
a6493 2
    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
        MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
d6587 1
a6587 1
static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
d6630 1
a6630 2
  else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
           ToolChain.getArch() == llvm::Triple::arm64)
a6631 3
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
           ToolChain.getArch() == llvm::Triple::arm64_be)
    return "/lib/ld-linux-aarch64_be.so.1";
a6637 6
  } else if (ToolChain.getArch() == llvm::Triple::armeb ||
             ToolChain.getArch() == llvm::Triple::thumbeb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";        /* TODO: check which dynamic linker name.  */
    else
      return "/lib/ld-linux.so.3";              /* TODO: check which dynamic linker name.  */
d6686 1
a6686 6
    !Args.hasArg(options::OPT_static) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
     // On Android every code is PIC so every executable is PIE
     // Cannot use isPIEDefault here since otherwise
     // PIE only logic will be enabled during compilation
     isAndroid);
d6722 1
a6722 2
  else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
           ToolChain.getArch() == llvm::Triple::arm64)
a6723 3
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
           ToolChain.getArch() == llvm::Triple::arm64_be)
    CmdArgs.push_back("aarch64_be_linux");
a6726 3
  else if (ToolChain.getArch() == llvm::Triple::armeb
           ||  ToolChain.getArch() == llvm::Triple::thumbeb)
    CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME.  */
a6730 2
  else if (ToolChain.getArch() == llvm::Triple::ppc64le)
    CmdArgs.push_back("elf64lppc");
d6758 1
a6758 3
        ToolChain.getArch() == llvm::Triple::armeb ||
        ToolChain.getArch() == llvm::Triple::thumb ||
        ToolChain.getArch() == llvm::Triple::thumbeb)
a6769 1
      ToolChain.getArch() == llvm::Triple::armeb ||
a6770 1
      ToolChain.getArch() == llvm::Triple::thumbeb ||
d6784 1
a6784 1
      const char *crt1 = nullptr;
d6852 2
a6853 14
      LibOpenMP UsedOpenMPLib = LibUnknown;
      if (Args.hasArg(options::OPT_fopenmp)) {
        UsedOpenMPLib = LibGOMP;
      } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
        UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
            .Case("libgomp",  LibGOMP)
            .Case("libiomp5", LibIOMP5)
            .Default(LibUnknown);
        if (UsedOpenMPLib == LibUnknown)
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << A->getValue();
      }
      switch (UsedOpenMPLib) {
      case LibGOMP:
a6858 6
        break;
      case LibIOMP5:
        CmdArgs.push_back("-liomp5");
        break;
      case LibUnknown:
        break;
d6860 1
d6863 2
a6864 3
      if (!isAndroid &&
          (Args.hasArg(options::OPT_pthread) ||
           Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown))
a7154 9
static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs,
                                  const StringRef RTName) {
  SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
  llvm::sys::path::append(LibSanitizer,
                          Twine("clang_rt.") + RTName + ".lib");
  CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
}

a7176 4
  if (Args.hasArg(options::OPT_g_Group)) {
    CmdArgs.push_back("-debug");
  }

d7191 2
a7192 1
    // FIXME: Handle 64-bit.
d7194 1
a7194 2
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
                            "asan_dll_thunk-i386");
d7196 1
a7196 2
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
d7198 2
a7296 9
  if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
                               options::OPT_fno_function_sections))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
                          ? "/Gy"
                          : "/Gy-");
  if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
                               options::OPT_fno_data_sections))
    CmdArgs.push_back(
        A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
d7357 2
a7358 3
  if (Arg *A = Args.getLastArg(options::OPT_g_Group))
    if (!A->getOption().matches(options::OPT_g0))
      CmdArgs.push_back("-g");
@


1.1.1.8
log
@Import clang 3.6svn r215315.
@
text
@d41 1
d66 2
a67 3
  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) {
    if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
        !Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
d69 1
a69 4
          << A->getBaseArg().getAsString(Args)
          << (D.IsCLMode() ? "/E, /P or /EP" : "-E");
    }
  }
d176 4
a179 1
  for (const auto &II : Inputs) {
d200 1
a200 1
    if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
d202 1
a202 1
    else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
d204 2
a205 7
    else if (A.getOption().matches(options::OPT_z)) {
      // Pass -z prefix for gcc linker compatibility.
      A.claim();
      A.render(Args, CmdArgs);
    } else {
       A.renderAsInput(Args, CmdArgs);
    }
d455 2
d486 23
a821 12
  // -mkernel implies -mstrict-align; don't add the redundant option.
  if (!KernelOrKext) {
    if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                                 options::OPT_munaligned_access)) {
      CmdArgs.push_back("-backend-option");
      if (A->getOption().matches(options::OPT_mno_unaligned_access))
        CmdArgs.push_back("-arm-strict-align");
      else
        CmdArgs.push_back("-arm-no-strict-align");
    }
  }

d847 8
a854 8
  Arg *A;
  std::string CPU;
  // If we have -mtune or -mcpu, use that.
  if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
    CPU = A->getValue();
  } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
    StringRef Mcpu = A->getValue();
    CPU = Mcpu.split("+").first;
d857 2
a858 5
  // Handle CPU name is 'native'.
  if (CPU == "native")
    return llvm::sys::getHostCPUName();
  else if (CPU.size())
    return CPU;
d893 4
a896 2
  if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                               options::OPT_munaligned_access)) {
d898 1
a898 4
    if (A->getOption().matches(options::OPT_mno_unaligned_access))
      CmdArgs.push_back("-aarch64-strict-align");
    else
      CmdArgs.push_back("-aarch64-no-strict-align");
d912 4
a915 4
void mips::getMipsCPUAndABI(const ArgList &Args,
                            const llvm::Triple &Triple,
                            StringRef &CPUName,
                            StringRef &ABIName) {
a918 8
  // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
  // default for mips64(el)?-img-linux-gnu.
  if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
      Triple.getEnvironment() == llvm::Triple::GNU) {
    DefMips32CPU = "mips32r6";
    DefMips64CPU = "mips64r6";
  }

d949 1
a949 10
  if (ABIName.empty()) {
    // Deduce ABI name from the target triple.
    if (Triple.getArch() == llvm::Triple::mips ||
        Triple.getArch() == llvm::Triple::mipsel)
      ABIName = "o32";
    else
      ABIName = "n64";
  }

  if (CPUName.empty()) {
d952 9
a960 2
      .Cases("o32", "eabi", DefMips32CPU)
      .Cases("n32", "n64", DefMips64CPU)
d964 1
a964 1
  // FIXME: Warn on inconsistent use of -march and -mabi.
d1018 1
a1018 2
static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
a1019 19
  StringRef CPUName;
  StringRef ABIName;
  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
  ABIName = getGnuCompatibleMipsABIName(ABIName);

  // Always override the backend's default ABI.
  std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
                               .Case("32", "+o32")
                               .Case("n32", "+n32")
                               .Case("64", "+n64")
                               .Case("eabi", "+eabi")
                               .Default(("+" + ABIName).str());
  Features.push_back("-o32");
  Features.push_back("-n64");
  Features.push_back(Args.MakeArgString(ABIFeature));

  AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
                   options::OPT_mabicalls, "noabicalls");

d1051 2
a1052 19

  // Add the last -mfp32/-mfpxx/-mfp64 or if none are given and the ABI is O32
  // pass -mfpxx
  if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
                               options::OPT_mfp64)) {
    if (A->getOption().matches(options::OPT_mfp32))
      Features.push_back(Args.MakeArgString("-fp64"));
    else if (A->getOption().matches(options::OPT_mfpxx)) {
      Features.push_back(Args.MakeArgString("+fpxx"));
      Features.push_back(Args.MakeArgString("+nooddspreg"));
    } else
      Features.push_back(Args.MakeArgString("+fp64"));
  } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
    Features.push_back(Args.MakeArgString("+fpxx"));
    Features.push_back(Args.MakeArgString("+nooddspreg"));
  }

  AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
                   options::OPT_modd_spreg, "nooddspreg");
d1061 1
a1061 1
  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
a1157 1
      .Case("power8", "pwr8")
a1164 1
      .Case("pwr8", "pwr8")
a1204 29
void Clang::AddPPCTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  // Select the ABI to use.
  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
  } else if (getToolChain().getTriple().isOSLinux())
    switch(getToolChain().getArch()) {
    case llvm::Triple::ppc64:
      ABIName = "elfv1";
      break;
    case llvm::Triple::ppc64le:
      ABIName = "elfv2";
      break;
    default:
      break;
  }

  if (ABIName) {
    CmdArgs.push_back("-target-abi");
    CmdArgs.push_back(ABIName);
  }
}

bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

d1238 1
a1238 1
  // Select the float ABI as determined by -msoft-float and -mhard-float.
d1337 2
d1353 1
a1353 1
    mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
d1414 1
a1414 2
static void getX86TargetFeatures(const Driver & D,
                                 const llvm::Triple &Triple,
a1427 1
  // Add features to comply with gcc on Android
d1429 2
a1430 30
    if (Triple.getArch() == llvm::Triple::x86_64) {
      Features.push_back("+sse4.2");
      Features.push_back("+popcnt");
    } else
      Features.push_back("+ssse3");
  }

  // Set features according to the -arch flag on MSVC
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
    StringRef Arch = A->getValue();
    bool ArchUsed = false;
    // First, look for flags that are shared in x86 and x86-64.
    if (Triple.getArch() == llvm::Triple::x86_64 ||
        Triple.getArch() == llvm::Triple::x86) {
      if (Arch == "AVX" || Arch == "AVX2") {
        ArchUsed = true;
        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
      }
    }
    // Then, look for x86-specific flags.
    if (Triple.getArch() == llvm::Triple::x86) {
      if (Arch == "IA32") {
        ArchUsed = true;
      } else if (Arch == "SSE" || Arch == "SSE2") {
        ArchUsed = true;
        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
      }
    }
    if (!ArchUsed)
      D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
a1533 100
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, const StringRef &text,
                                  std::vector<const char *> &Features) {
  SmallVector<StringRef, 8> Split;
  text.split(Split, StringRef("+"), -1, false);

  for (unsigned I = 0, E = Split.size(); I != E; ++I) {
    const char *result = llvm::StringSwitch<const char *>(Split[I])
                             .Case("fp", "+fp-armv8")
                             .Case("simd", "+neon")
                             .Case("crc", "+crc")
                             .Case("crypto", "+crypto")
                             .Case("nofp", "-fp-armv8")
                             .Case("nosimd", "-neon")
                             .Case("nocrc", "-crc")
                             .Case("nocrypto", "-crypto")
                             .Default(nullptr);
    if (result)
      Features.push_back(result);
    else if (Split[I] == "neon" || Split[I] == "noneon")
      D.Diag(diag::err_drv_no_neon_modifier);
    else
      return false;
  }
  return true;
}

// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
// decode CPU and feature.
static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
                              std::vector<const char *> &Features) {
  std::pair<StringRef, StringRef> Split = Mcpu.split("+");
  CPU = Split.first;
  if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
    Features.push_back("+neon");
    Features.push_back("+crc");
    Features.push_back("+crypto");
  } else if (CPU == "generic") {
    Features.push_back("+neon");
  } else {
    return false;
  }

  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
    return false;

  return true;
}

static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
                                const ArgList &Args,
                                std::vector<const char *> &Features) {
  std::pair<StringRef, StringRef> Split = March.split("+");
  if (Split.first != "armv8-a")
    return false;

  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
    return false;

  return true;
}

static bool
getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
                               const ArgList &Args,
                               std::vector<const char *> &Features) {
  StringRef CPU;
  if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
    return false;

  return true;
}

static bool
getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
                                     const ArgList &Args,
                                     std::vector<const char *> &Features) {
  // Handle CPU name is 'native'.
  if (Mtune == "native")
    Mtune = llvm::sys::getHostCPUName();
  if (Mtune == "cyclone") {
    Features.push_back("+zcm");
    Features.push_back("+zcz");
  }
  return true;
}

static bool
getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
                                    const ArgList &Args,
                                    std::vector<const char *> &Features) {
  StringRef CPU;
  std::vector<const char *> DecodedFeature;
  if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
    return false;

  return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
}

d1536 5
a1540 18
  Arg *A;
  bool success = true;
  // Enable NEON by default.
  Features.push_back("+neon");
  if ((A = Args.getLastArg(options::OPT_march_EQ)))
    success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
  else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);

  if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
    success =
        getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
  else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
    success =
        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);

  if (!success)
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
d1569 1
a1569 1
    getMIPSTargetFeatures(D, Triple, Args, Features);
d1589 2
d1595 1
a1595 1
    getX86TargetFeatures(D, Triple, Args, Features);
d1763 2
a1764 2
  for (const auto &Act : *A)
    if (ContainsCompileAction(Act))
d1780 3
a1782 2
    for (const auto &Act : C.getActions()) {
      if (ContainsCompileAction(Act)) {
d1899 1
a1899 2
  if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                     false) ||
a2035 4
  // Do not link runtime into shared libraries.
  if (Args.hasArg(options::OPT_shared))
    return;

d2041 1
a2041 1
  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true);
d2046 1
a2046 1
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true);
d2059 1
d2061 3
a2063 3
    addUbsanRT(TC, Args, CmdArgs, Sanitize.linkCXXRuntimes(),
               Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                   Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
d2065 1
a2065 2
    addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(),
              Sanitize.linkCXXRuntimes());
a2215 20
static std::string getMSCompatibilityVersion(const char *VersionStr) {
  unsigned Version;
  if (StringRef(VersionStr).getAsInteger(10, Version))
    return "0";

  if (Version < 100)
    return llvm::utostr_32(Version) + ".0";

  if (Version < 10000)
    return llvm::utostr_32(Version / 100) + "." +
        llvm::utostr_32(Version % 100);

  unsigned Build = 0, Factor = 1;
  for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
    Build = Build + (Version % 10) * Factor;
  return llvm::utostr_32(Version / 100) + "." +
      llvm::utostr_32(Version % 100) + "." +
      llvm::utostr_32(Build);
}

d2324 2
a2325 5
  // We normally speed up the clang process a bit by skipping destructors at
  // exit, but when we're generating diagnostics we can rely on some of the
  // cleanup.
  if (!C.isForDiagnostics())
    CmdArgs.push_back("-disable-free");
d2407 1
a2425 21
  // OpenBSD-specific defaults for PIE
  if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
    case llvm::Triple::sparc:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      IsPICLevelTwo = false; // "-fpie"
      break;

    case llvm::Triple::ppc:
    case llvm::Triple::sparcv9:
      IsPICLevelTwo = true; // "-fPIE"
      break;

    default:
      break;
    }
  }

d2467 1
a2513 7
  if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
    StringRef v = A->getValue();
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
    A->claim();
  }

d2797 2
a2808 6
  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    AddPPCTargetArgs(Args, CmdArgs);
    break;

a2809 1
  case llvm::Triple::sparcv9:
d2875 2
a2876 4
      // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
      const llvm::Triple &Triple = getToolChain().getTriple();
      if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
          Triple.getOS() == llvm::Triple::FreeBSD)
d2886 2
a2887 4
      // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
      const llvm::Triple &Triple = getToolChain().getTriple();
      if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
          Triple.getOS() == llvm::Triple::FreeBSD)
d2896 1
a2896 2
  if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
                   /*Default*/ true))
d2957 1
a2957 2
  if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                   false) ||
a2960 8
  if (Args.hasArg(options::OPT_fcoverage_mapping) &&
      !Args.hasArg(options::OPT_fprofile_instr_generate))
    D.Diag(diag::err_drv_argument_only_allowed_with)
      << "-fcoverage-mapping" << "-fprofile-instr-generate";

  if (Args.hasArg(options::OPT_fcoverage_mapping))
    CmdArgs.push_back("-fcoverage-mapping");

a3085 7
  // Warn about ignored options to clang.
  for (arg_iterator it = Args.filtered_begin(
       options::OPT_clang_ignored_gcc_optimization_f_Group),
       ie = Args.filtered_end(); it != ie; ++it) {
    D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
  }

a3089 1
  Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
d3325 4
d3417 25
a3458 11
  if (TT.getArch() == llvm::Triple::arm ||
      TT.getArch() == llvm::Triple::thumb) {
    if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
                                 options::OPT_mno_long_calls)) {
      if (A->getOption().matches(options::OPT_mlong_calls)) {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-long-calls");
      }
    }
  }

d3469 9
d3545 2
a3546 1
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_name))
d3548 1
d3552 2
a3553 1
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file))
d3555 1
d3557 6
a3562 17
  // -fmodule-cache-path specifies where our module files should be written.
  SmallString<128> ModuleCachePath;
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
    ModuleCachePath = A->getValue();
  if (HaveModules) {
    if (C.isForDiagnostics()) {
      // When generating crash reports, we want to emit the modules along with
      // the reproduction sources, so we ignore any provided module path.
      ModuleCachePath = Output.getFilename();
      llvm::sys::path::replace_extension(ModuleCachePath, ".cache");
      llvm::sys::path::append(ModuleCachePath, "modules");
    } else if (ModuleCachePath.empty()) {
      // No module path was provided: use the default.
      llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
                                             ModuleCachePath);
      llvm::sys::path::append(ModuleCachePath, "org.llvm.clang");
      llvm::sys::path::append(ModuleCachePath, "ModuleCache");
d3564 6
d3571 3
a3573 2
    ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg));
    CmdArgs.push_back(Args.MakeArgString(ModuleCachePath));
d3576 5
a3580 8
  // When building modules and generating crashdumps, we need to dump a module
  // dependency VFS alongside the output.
  if (HaveModules && C.isForDiagnostics()) {
    SmallString<128> VFSDir(Output.getFilename());
    llvm::sys::path::replace_extension(VFSDir, ".cache");
    llvm::sys::path::append(VFSDir, "vfs");
    CmdArgs.push_back("-module-dependency-dir");
    CmdArgs.push_back(Args.MakeArgString(VFSDir));
a3582 4
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path))
    if (HaveModules)
      A->render(Args, CmdArgs);

a3589 14
  if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
    if (Args.hasArg(options::OPT_fbuild_session_timestamp))
      D.Diag(diag::err_drv_argument_not_allowed_with)
          << A->getAsString(Args) << "-fbuild-session-timestamp";

    llvm::sys::fs::file_status Status;
    if (llvm::sys::fs::status(A->getValue(), Status))
      D.Diag(diag::err_drv_no_such_file) << A->getValue();
    char TimeStamp[48];
    snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64,
             (uint64_t)Status.getLastModificationTime().toEpochTime());
    CmdArgs.push_back(Args.MakeArgString(TimeStamp));
  }

d3591 1
a3591 2
    if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
                         options::OPT_fbuild_session_file))
d3667 1
a3667 1
  // -fms-compatibility-version=17.00 is default.
d3669 4
a3672 19
                   IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
      Args.hasArg(options::OPT_fms_compatibility_version)) {
    const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
    const Arg *MSCompatibilityVersion =
      Args.getLastArg(options::OPT_fms_compatibility_version);

    if (MSCVersion && MSCompatibilityVersion)
      D.Diag(diag::err_drv_argument_not_allowed_with)
          << MSCVersion->getAsString(Args)
          << MSCompatibilityVersion->getAsString(Args);

    std::string Ver;
    if (MSCompatibilityVersion)
      Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
    else if (MSCVersion)
      Ver = getMSCompatibilityVersion(MSCVersion->getValue());

    if (Ver.empty())
      CmdArgs.push_back("-fms-compatibility-version=17.00");
d3674 1
a3674 1
      CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
d3677 1
d3788 3
a3790 4
  // Handle GCC-style exception args.
  if (!C.getDriver().IsCLMode())
    addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
                     objcRuntime, CmdArgs);
a3830 15
  // Handle -fmax-type-align=N and -fno-type-align
  bool SkipMaxTypeAlign = Args.hasArg(options::OPT_fno_max_type_align);
  if (Arg *A = Args.getLastArg(options::OPT_fmax_type_align_EQ)) {
    if (!SkipMaxTypeAlign) {
      std::string MaxTypeAlignStr = "-fmax-type-align=";
      MaxTypeAlignStr += A->getValue();
      CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
    }
  } else if (getToolChain().getTriple().isOSDarwin()) {
    if (!SkipMaxTypeAlign) {
      std::string MaxTypeAlignStr = "-fmax-type-align=16";
      CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
    }
  }

a3853 8
  // -finput_charset=UTF-8 is default. Reject others
  if (Arg *inputCharset = Args.getLastArg(
          options::OPT_finput_charset_EQ)) {
      StringRef value = inputCharset->getValue();
      if (value != "UTF-8")
          D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value;
  }

d3896 3
a3898 2
  for (const auto &Arg : Args) {
    const Option &O = Arg->getOption();
d3906 1
a3906 1
    Arg->claim();
d3915 1
a3915 1
      StringRef value(Arg->getValue());
a4021 9
  // Enable rewrite includes if the user's asked for it or if we're generating
  // diagnostics.
  // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
  // nice to enable this when doing a crashdump for modules as well.
  if (Args.hasFlag(options::OPT_frewrite_includes,
                   options::OPT_fno_rewrite_includes, false) ||
      (C.isForDiagnostics() && !HaveModules))
    CmdArgs.push_back("-frewrite-includes");

d4072 4
a4075 1
  for (const auto &II : Inputs) {
d4092 3
a4094 2
    for (const auto &Arg : Args)
      Arg->render(Args, OriginalArgs);
d4122 12
a4133 3
    Command *CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs,
                                                     Args, LinkingOutput);
    C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
a4290 39
static bool maybeConsumeDash(const std::string &EH, size_t &I) {
  bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
  I += HaveDash;
  return !HaveDash;
}

struct EHFlags {
  EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
  bool Synch;
  bool Asynch;
  bool NoExceptC;
};

/// /EH controls whether to run destructor cleanups when exceptions are
/// thrown.  There are three modifiers:
/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions.
/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions.
///      The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
/// - c: Assume that extern "C" functions are implicitly noexcept.  This
///      modifier is an optimization, so we ignore it for now.
/// The default is /EHs-c-, meaning cleanups are disabled.
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
  EHFlags EH;
  std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
  for (auto EHVal : EHArgs) {
    for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
      switch (EHVal[I]) {
      case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
      case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
      case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
      default: break;
      }
      D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
      break;
    }
  }
  return EH;
}

d4336 2
a4337 5
  // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
  // would produce interleaved output, so ignore /showIncludes in such cases.
  if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP))
    if (Arg *A = Args.getLastArg(options::OPT_show_includes))
      A->render(Args, CmdArgs);
d4339 3
a4341 4
  // This controls whether or not we emit RTTI data for polymorphic types.
  if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
                   /*default=*/false))
    CmdArgs.push_back("-fno-rtti-data");
a4343 13
  EHFlags EH = parseClangCLEHFlags(D, Args);
  // FIXME: Do something with NoExceptC.
  if (EH.Synch || EH.Asynch) {
    CmdArgs.push_back("-fexceptions");
    CmdArgs.push_back("-fcxx-exceptions");
  }

  // /EP should expand to -E -P.
  if (Args.hasArg(options::OPT__SLASH_EP)) {
    CmdArgs.push_back("-E");
    CmdArgs.push_back("-P");
  }

a4381 6
visualstudio::Compile *Clang::getCLFallback() const {
  if (!CLFallback)
    CLFallback.reset(new visualstudio::Compile(getToolChain()));
  return CLFallback.get();
}

d4469 3
a4471 2
    for (const auto &Arg : Args)
      Arg->render(Args, OriginalArgs);
d4528 3
a4530 1
  for (const auto &A : Args) {
d4599 4
a4602 1
  for (const auto &II : Inputs) {
d4721 4
a4724 1
  for (const auto &II : Inputs) {
d4745 2
a4746 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
d4748 1
a4749 1

d4791 4
a4794 2
  for (const auto &Opt : ToolChain.ExtraOpts)
    CmdArgs.push_back(Opt.c_str());
d4870 6
a4875 2
  for (const auto &LibPath : LibPaths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
d4923 3
a4925 1
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
d4947 75
a5021 1
  return Triple.getARMCPUForArch(MArch);
a5076 31
bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
  if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
    return llvm::StringSwitch<bool>(NaNArg->getValue())
               .Case("2008", true)
               .Case("legacy", false)
               .Default(false);

  // NaN2008 is the default for MIPS32r6/MIPS64r6.
  return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
             .Cases("mips32r6", "mips64r6", true)
             .Default(false);

  return false;
}

bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
                         StringRef ABIName) {
  if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
      Triple.getVendor() != llvm::Triple::MipsTechnologies)
    return false;

  if (ABIName != "32")
    return false;

  return llvm::StringSwitch<bool>(CPUName)
             .Cases("mips2", "mips3", "mips4", "mips5", true)
             .Cases("mips32", "mips32r2", true)
             .Cases("mips64", "mips64r2", true)
             .Default(false);
}

d5102 1
a5102 1
    .Case("arm64", llvm::Triple::aarch64)
d5242 3
a5244 2
  for (const auto &Input : Inputs)
    if (Input.getType() != types::TY_Object)
d5445 2
a5446 2
    for (const auto &Arg : Args)
      Arg->claim();
d5547 1
a5547 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d5564 3
a5566 1
  for (const auto &II : Inputs) {
d5570 2
a5571 2

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
d5631 3
a5633 1
  for (const auto &II : Inputs)
d5635 1
d5637 2
a5638 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d5642 1
d5744 1
a5744 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d5761 3
a5763 1
  for (const auto &II : Inputs)
d5765 1
d5767 2
a5768 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas"));
d5856 1
a5856 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d5895 1
a5895 1
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
d5922 3
a5924 1
  for (const auto &II : Inputs)
d5926 1
d6061 1
a6061 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d6078 3
a6080 1
  for (const auto &II : Inputs)
d6082 1
d6084 2
a6085 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d6201 1
a6201 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d6224 1
a6224 1
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
d6279 3
a6281 1
  for (const auto &II : Inputs)
d6283 1
d6285 2
a6286 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d6387 3
a6389 2
  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
d6470 1
a6470 1
    Args.MakeArgString(getToolChain().GetLinkerPath());
d6502 1
a6502 1
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
d6541 3
a6543 1
  for (const auto &II : Inputs)
d6545 1
d6670 1
a6670 1
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) {
a6671 1
    case llvm::Triple::aarch64:
a6675 1
    case llvm::Triple::ppc:
d6726 1
a6726 1
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
d6743 1
a6743 4
    if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
      CmdArgs.push_back("--x32");
    else
      CmdArgs.push_back("--64");
d6796 1
a6796 2
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
    ABIName = getGnuCompatibleMipsABIName(ABIName);
d6802 1
a6802 21
    CmdArgs.push_back(ABIName.data());

    // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
    // or -mshared (not implemented) is in effect.
    bool IsPicOrPie = false;
    if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                 options::OPT_fpic, options::OPT_fno_pic,
                                 options::OPT_fPIE, options::OPT_fno_PIE,
                                 options::OPT_fpie, options::OPT_fno_pie)) {
      if (A->getOption().matches(options::OPT_fPIC) ||
          A->getOption().matches(options::OPT_fpic) ||
          A->getOption().matches(options::OPT_fPIE) ||
          A->getOption().matches(options::OPT_fpie))
        IsPicOrPie = true;
    }
    if (!IsPicOrPie)
      CmdArgs.push_back("-mno-shared");

    // LLVM doesn't support -mplt yet and acts as if it is always given.
    // However, -mplt has no effect with the N64 ABI.
    CmdArgs.push_back(ABIName == "64" ? "-KPIC" : "-call_nonpic");
d6815 2
a6816 22
    // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
    if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
                                 options::OPT_mfp64)) {
      A->claim();
      A->render(Args, CmdArgs);
    } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
                                   ABIName))
      CmdArgs.push_back("-mfpxx");

    // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
    // -mno-mips16 is actually -no-mips16.
    if (Arg *A = Args.getLastArg(options::OPT_mips16,
                                 options::OPT_mno_mips16)) {
      if (A->getOption().matches(options::OPT_mips16)) {
        A->claim();
        A->render(Args, CmdArgs);
      } else {
        A->claim();
        CmdArgs.push_back("-no-mips16");
      }
    }

a6828 6
    Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
                    options::OPT_msoft_float);

    Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
                    options::OPT_mno_odd_spreg);

d6846 3
a6848 1
  for (const auto &II : Inputs)
d6850 1
d6852 2
a6853 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d6898 2
a6899 2
static std::string getLinuxDynamicLinker(const ArgList &Args,
                                         const toolchains::Linux &ToolChain) {
d6908 2
a6909 1
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
d6911 2
a6912 1
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
d6927 8
a6934 16
             ToolChain.getArch() == llvm::Triple::mipsel ||
             ToolChain.getArch() == llvm::Triple::mips64 ||
             ToolChain.getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName);
    bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple());

    StringRef LibDir = llvm::StringSwitch<llvm::StringRef>(ABIName)
                           .Case("o32", "/lib")
                           .Case("n32", "/lib32")
                           .Case("n64", "/lib64")
                           .Default("/lib");
    StringRef LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";

    return (LibDir + "/" + LibName).str();
d6937 3
a6939 9
  else if (ToolChain.getArch() == llvm::Triple::ppc64) {
    if (ppc::hasPPCAbiArg(Args, "elfv2"))
      return "/lib64/ld64.so.2";
    return "/lib64/ld64.so.1";
  } else if (ToolChain.getArch() == llvm::Triple::ppc64le) {
    if (ppc::hasPPCAbiArg(Args, "elfv1"))
      return "/lib64/ld64.so.1";
    return "/lib64/ld64.so.2";
  } else if (ToolChain.getArch() == llvm::Triple::systemz)
a6942 3
  else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
           ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
    return "/libx32/ld-linux-x32.so.2";
d7003 4
a7006 2
  for (const auto &Opt : ToolChain.ExtraOpts)
    CmdArgs.push_back(Opt.c_str());
d7015 2
a7016 1
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
d7018 2
a7019 1
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
a7054 3
  else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
           ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
    CmdArgs.push_back("elf32_x86_64");
d7068 3
a7120 1
  Args.AddAllArgs(CmdArgs, options::OPT_u);
d7124 3
a7126 2
  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
d7186 3
a7188 3
      if ((Args.hasArg(options::OPT_pthread) ||
           Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) &&
          !isAndroid)
d7224 2
a7225 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d7230 3
a7232 1
  for (const auto &II : Inputs)
d7234 1
d7236 2
a7237 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d7291 1
a7291 1
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
d7311 2
a7312 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d7317 3
a7319 1
  for (const auto &II : Inputs)
d7321 1
d7323 2
a7324 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
d7474 2
a7475 1
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
d7542 4
a7545 3
  for (const auto &Input : Inputs)
    if (Input.isFilename())
      CmdArgs.push_back(Input.getFilename());
d7547 2
a7548 1
      Input.getInputArg().renderAsInput(Args, CmdArgs);
d7573 6
a7578 1
  const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
d7580 1
a7580 1
  llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
d7630 3
a7632 3
  if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
                   /*default=*/false))
    CmdArgs.push_back("/GR-");
d7648 2
a7649 2
  for (const auto &Include : Includes)
    CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
a7653 1
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
d7679 1
d7713 3
a7715 1
  for (const auto &II : Inputs)
d7717 1
d7719 2
a7720 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
d7747 2
a7748 1
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
@


1.1.1.8.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@a15 1
#include "clang/Config/config.h"
a85 17
// Add backslashes to escape spaces and other backslashes.
// This is used for the space-separated argument list specified with
// the -dwarf-debug-flags option.
static void EscapeSpacesAndBackslashes(const char *Arg,
                                       SmallVectorImpl<char> &Res) {
  for ( ; *Arg; ++Arg) {
    switch (*Arg) {
    default: break;
    case ' ':
    case '\\':
      Res.push_back('\\');
      break;
    }
    Res.push_back(*Arg);
  }
}

a461 2
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
d509 1
a509 1

a546 12
  } else if (FPU == "fp5-sp-d16" || FPU == "fpv5-sp-d16") {
    Features.push_back("+fp-armv8");
    Features.push_back("+fp-only-sp");
    Features.push_back("+d16");
    Features.push_back("-neon");
    Features.push_back("-crypto");
  } else if (FPU == "fp5-dp-d16" || FPU == "fpv5-dp-d16" ||
             FPU == "fp5-d16" || FPU == "fpv5-d16") {
    Features.push_back("+fp-armv8");
    Features.push_back("+d16");
    Features.push_back("-neon");
    Features.push_back("-crypto");
a560 6
  } else if (FPU == "neon-vfpv3") {
    Features.push_back("+vfp3");
    Features.push_back("+neon");
  } else if (FPU == "neon-vfpv4") {
    Features.push_back("+neon");
    Features.push_back("+vfp4");
a730 1
  // FIXME: Parts of this are duplicated in the backend, unify this somehow.
d738 2
a739 1
        Triple.getOS() == llvm::Triple::UnknownOS ||
d761 1
a761 5
      if (Triple.getOS() == llvm::Triple::NetBSD)
        ABIName = "apcs-gnu";
      else
        ABIName = "aapcs";
      break;
d809 1
a809 3
      else {
        if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
          D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
a810 1
      }
a896 13
  if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
                               options::OPT_mno_fix_cortex_a53_835769)) {
    CmdArgs.push_back("-backend-option");
    if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
      CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
    else
      CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
  } else if (Triple.getEnvironment() == llvm::Triple::Android) {
    // Enabled A53 errata (835769) workaround by default on android
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
  }

a903 5

  if (Args.hasArg(options::OPT_ffixed_x18)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-reserve-x18");
  }
a922 4
  // MIPS3 is the default for mips64*-unknown-openbsd.
  if (Triple.getOS() == llvm::Triple::OpenBSD)
    DefMips64CPU = "mips3";

d1297 1
a1297 1
                                   std::vector<const char *> &Features) {
a1463 1
  case llvm::Triple::amdgcn:
d1474 1
a1474 1
  std::string Plugin = ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
d1637 1
a1637 1
static bool DecodeAArch64Features(const Driver &D, StringRef text,
a1745 3
  else if (Args.hasArg(options::OPT_arch))
    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), Args,
                                             Features);
a1752 3
  else if (Args.hasArg(options::OPT_arch))
    success = getAArch64MicroArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args),
                                                  Args, Features);
a1799 1
  case llvm::Triple::sparcv9:
d1851 9
d1862 10
a1871 1
static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) {
d1873 1
a1873 1
                               options::OPT_fno_exceptions))
d1875 11
a1885 1
      return true;
d1887 1
a1887 1
  return false;
d1912 2
a1913 2
  // Gather the exception settings from the command line arguments.
  bool EH = exceptionSettings(Args, Triple);
d1923 2
a1924 1
    EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
d1928 2
a1929 1
    bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore;
d1933 6
a1938 4
                                 options::OPT_fno_exceptions))
      CXXExceptionsEnabled =
          A->getOption().matches(options::OPT_fcxx_exceptions) ||
          A->getOption().matches(options::OPT_fexceptions);
d1943 1
a1943 1
      EH = true;
d1947 1
a1947 1
  if (EH)
d1973 1
a1973 1
  if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
d2041 2
a2042 1
          CmdArgs.push_back("-massembler-fatal-warnings");
d2075 2
a2076 5
  // FIXME: handle 64-bit
  if (TC.getTriple().isOSWindows() &&
      !TC.getTriple().isWindowsItaniumEnvironment())
    return "i386";
  if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
d2078 2
a2079 1
  return TC.getArchName();
d2087 2
a2088 2
  StringRef OSLibName =
      (Triple.getOS() == llvm::Triple::FreeBSD) ? "freebsd" : TC.getOS();
a2092 16
static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
                                      bool Shared = false,
                                      const char *Env = "") {
  bool IsOSWindows = TC.getTriple().isOSWindows();
  StringRef Arch = getArchNameForCompilerRTLib(TC);
  const char *Prefix = IsOSWindows ? "" : "lib";
  const char *Suffix =
      Shared ? (IsOSWindows ? ".dll" : ".so") : (IsOSWindows ? ".lib" : ".a");

  SmallString<128> Path = getCompilerRTLibDir(TC);
  llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
                                    Arch + Env + Suffix);

  return Path;
}

d2096 11
a2106 10
static void addClangRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "builtins")));

  if (!TC.getTriple().isOSWindows()) {
    // FIXME: why do we link against gcc when we are using compiler-rt?
    CmdArgs.push_back("-lgcc_s");
    if (TC.getDriver().CCCIsCXX())
      CmdArgs.push_back("-lgcc_eh");
  }
d2109 2
a2110 2
static void addProfileRT(const ToolChain &TC, const ArgList &Args,
                         ArgStringList &CmdArgs) {
d2119 6
a2124 9
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
}

static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
                                ArgStringList &CmdArgs, StringRef Sanitizer,
                                bool IsShared) {
  const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
                        ? "-android"
                        : "";
d2126 20
a2145 8
  // Static runtimes must be forced into executable, so we wrap them in
  // whole-archive.
  if (!IsShared)
    CmdArgs.push_back("-whole-archive");
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared,
                                                     Env)));
  if (!IsShared)
    CmdArgs.push_back("-no-whole-archive");
d2148 1
a2148 3
// Tries to use a file with the list of dynamic symbols that need to be exported
// from the runtime library. Returns true if the file was found.
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
d2150 29
a2178 5
                                    StringRef Sanitizer) {
  SmallString<128> SanRT = getCompilerRT(TC, Sanitizer);
  if (llvm::sys::fs::exists(SanRT + ".syms")) {
    CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
    return true;
a2179 2
  return false;
}
d2181 10
a2190 11
static void linkSanitizerRuntimeDeps(const ToolChain &TC,
                                     ArgStringList &CmdArgs) {
  // Force linking against the system libraries sanitizers depends on
  // (see PR15823 why this is necessary).
  CmdArgs.push_back("--no-as-needed");
  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-lm");
  // There's no libdl on FreeBSD.
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
    CmdArgs.push_back("-ldl");
d2193 9
a2201 9
static void
collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
                         SmallVectorImpl<StringRef> &SharedRuntimes,
                         SmallVectorImpl<StringRef> &StaticRuntimes,
                         SmallVectorImpl<StringRef> &HelperStaticRuntimes) {
  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
  // Collect shared runtimes.
  if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) {
    SharedRuntimes.push_back("asan");
d2204 1
a2204 1
  // Collect static runtimes.
d2206 1
a2206 2
      (TC.getTriple().getEnvironment() == llvm::Triple::Android)) {
    // Don't link static runtimes into DSOs or if compiling for Android.
d2208 9
a2216 27
  }
  if (SanArgs.needsAsanRt()) {
    if (SanArgs.needsSharedAsanRt()) {
      HelperStaticRuntimes.push_back("asan-preinit");
    } else {
      StaticRuntimes.push_back("asan");
      if (SanArgs.linkCXXRuntimes())
        StaticRuntimes.push_back("asan_cxx");
    }
  }
  if (SanArgs.needsDfsanRt())
    StaticRuntimes.push_back("dfsan");
  if (SanArgs.needsLsanRt())
    StaticRuntimes.push_back("lsan");
  if (SanArgs.needsMsanRt())
    StaticRuntimes.push_back("msan");
  if (SanArgs.needsTsanRt())
    StaticRuntimes.push_back("tsan");
  // WARNING: UBSan should always go last.
  if (SanArgs.needsUbsanRt()) {
    // If UBSan is not combined with another sanitizer, we need to pull in
    // sanitizer_common explicitly.
    if (StaticRuntimes.empty())
      HelperStaticRuntimes.push_back("san");
    StaticRuntimes.push_back("ubsan");
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("ubsan_cxx");
d2220 54
a2273 3
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
d2275 16
a2290 18
  SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
      HelperStaticRuntimes;
  collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
                           HelperStaticRuntimes);
  for (auto RT : SharedRuntimes)
    addSanitizerRuntime(TC, Args, CmdArgs, RT, true);
  for (auto RT : HelperStaticRuntimes)
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
  bool AddExportDynamic = false;
  for (auto RT : StaticRuntimes) {
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
    AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
  }
  // If there is a static runtime with no dynamic list, force all the symbols
  // to be dynamic to be sure we export sanitizer interface functions.
  if (AddExportDynamic)
    CmdArgs.push_back("-export-dynamic");
  return !StaticRuntimes.empty();
d2380 1
a2380 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs));
d2383 1
a2383 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs));
a2452 10
// Claim options we don't want to warn if they are unused. We do this for
// options that build systems might add but are unused when assembling or only
// running the preprocessor for example.
static void claimNoWarnArgs(const ArgList &Args) {
  // Don't warn about unused -f(no-)?lto.  This can happen when we're
  // preprocessing, precompiling or assembling.
  Args.ClaimAllArgs(options::OPT_flto);
  Args.ClaimAllArgs(options::OPT_fno_lto);
}

d2533 1
a2533 2
    assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
           "Invalid action for clang tool.");
d2726 2
a2727 1
  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)))
a2766 6
  CmdArgs.push_back("-mthread-model");
  if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
    CmdArgs.push_back(A->getValue());
  else
    CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));

a2772 13
  if (Args.hasArg(options::OPT_frewrite_map_file) ||
      Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
    for (arg_iterator
             MFI = Args.filtered_begin(options::OPT_frewrite_map_file,
                                       options::OPT_frewrite_map_file_EQ),
             MFE = Args.filtered_end();
         MFI != MFE; ++MFI) {
      CmdArgs.push_back("-frewrite-map-file");
      CmdArgs.push_back((*MFI)->getValue());
      (*MFI)->claim();
    }
  }

d3142 1
a3142 2
    if (A->getOption().matches(options::OPT_gline_tables_only) ||
        A->getOption().matches(options::OPT_g1)) {
d3146 1
a3146 1
      // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
d3149 1
a3149 2
          Triple.getOS() == llvm::Triple::FreeBSD ||
          Triple.getOS() == llvm::Triple::Solaris)
d3159 1
a3159 1
      // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
d3162 1
a3162 2
          Triple.getOS() == llvm::Triple::FreeBSD ||
          Triple.getOS() == llvm::Triple::Solaris)
d3250 1
a3250 6
      SmallString<128> CoverageFilename;
      if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
        CoverageFilename = FinalOutput->getValue();
      } else {
        CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
      }
d3378 3
a3380 1
  claimNoWarnArgs(Args);
a3402 1
    // If -f(no-)trigraphs appears after the language standard flag, honor it.
d3404 1
a3404 2
                                 options::OPT_ftrigraphs,
                                 options::OPT_fno_trigraphs))
d3420 1
a3420 2
    Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
                    options::OPT_fno_trigraphs);
a3538 5
  if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
    CmdArgs.push_back("-fspell-checking-limit");
    CmdArgs.push_back(A->getValue());
  }

d3590 9
a3706 4
  if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
      getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be)
    CmdArgs.push_back("-fallow-half-arguments-and-returns");

d3772 3
a3774 3
  // -fmodules enables modules (off by default).
  // Users can pass -fno-cxx-modules to turn off modules support for
  // C++/Objective-C++ programs, which is a little less mature.
d3779 1
a3779 1
                                     true);
d3811 2
a3812 1
  Args.AddLastArg(CmdArgs, options::OPT_fmodule_name);
d3814 1
a3814 1
  // -fmodule-map-file can be used to specify files containing module
d3816 2
a3817 1
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
d3819 1
a3819 5
  // -fmodule-file can be used to specify files containing precompiled modules.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);

  // -fmodule-cache-path specifies where our implicitly-built module files
  // should be written.
a3846 3
    // Add the cache directory as a temp so the crash diagnostics pick it up.
    C.addTempFile(Args.MakeArgString(VFSDir));

d3852 3
a3854 2
  if (HaveModules)
    Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
a4179 8
  // -fexec_charset=UTF-8 is default. Reject others
  if (Arg *execCharset = Args.getLastArg(
          options::OPT_fexec_charset_EQ)) {
      StringRef value = execCharset->getValue();
      if (value != "UTF-8")
          D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args) << value;
  }

a4384 1
  bool OptDisabled = false;
d4391 1
a4391 1
    if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") {
d4393 1
a4393 2
      OptDisabled = true;
    } else
a4396 7
  // With -save-temps, we want to save the unoptimized bitcode output from the
  // CompileJobAction, so disable optimizations if they are not already
  // disabled.
  if (Args.hasArg(options::OPT_save_temps) && !OptDisabled &&
      isa<CompileJobAction>(JA))
    CmdArgs.push_back("-disable-llvm-optzns");

a4428 2
      SmallString<128> EscapedArg;
      EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
d4430 1
a4430 1
      Flags += EscapedArg;
d4440 1
a4440 2
    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
     isa<BackendJobAction>(JA));
d4452 3
a4454 4
    auto CLCommand =
        getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
    C.addCommand(llvm::make_unique<FallbackCommand>(JA, *this, Exec, CmdArgs,
                                                    std::move(CLCommand)));
d4456 1
a4456 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d4463 1
a4463 1
  if (SplitDwarf && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
a4779 2
  claimNoWarnArgs(Args);

a4858 2
      SmallString<128> EscapedArg;
      EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
d4860 1
a4860 1
      Flags += EscapedArg;
d4891 1
a4891 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a4901 2
void GnuTool::anchor() {}

d4934 1
d4937 10
a4946 2
    CmdArgs.push_back(
      Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
a4953 1
  llvm::Triple::ArchType Arch = getToolChain().getArch();
d5024 1
a5024 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5063 1
  claimNoWarnArgs(Args);
d5120 1
a5120 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5197 2
a5198 2
  const std::string RootDir =
      toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/";
d5286 1
a5286 2
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs));
d5351 2
a5352 2
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
d5356 1
a5356 1
    .Cases("cortex-m4", "cortex-m7", "v7em")
a5362 14
void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) {
  if (Args.hasArg(options::OPT_r))
    return;

  StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple));
  const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
    .Cases("v4", "v4t", "v5", "v5e", nullptr)
    .Cases("v6", "v6t2", nullptr)
    .Default("--be8");

  if (LinkFlag)
    CmdArgs.push_back(LinkFlag);
}

a5367 5
bool mips::isUCLibc(const ArgList &Args) {
  Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
  return A && A->getOption().matches(options::OPT_muclibc);
}

a5425 1
    .Case("amdgcn", llvm::Triple::amdgcn)
d5542 1
a5542 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5757 6
  // If the number of arguments surpasses the system limits, we will encode the
  // input files in a separate file, shortening the command line. To this end,
  // build a list of input file names that can be passed via a file with the
  // -filelist linker option.
  llvm::opt::ArgStringList InputFileList;

d5771 1
a5771 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5826 1
a5826 17
  // Build the input file for -filelist (list of linker input files) in case we
  // need it later
  for (const auto &II : Inputs) {
    if (!II.isFilename()) {
      // This is a linker input argument.
      // We cannot mix input arguments and file names in a -filelist input, thus
      // we prematurely stop our list (remaining files shall be passed as
      // arguments).
      if (InputFileList.size() > 0)
        break;

      continue;
    }

    InputFileList.push_back(II.getFilename());
  }

d5869 1
a5869 4
  std::unique_ptr<Command> Cmd =
    llvm::make_unique<Command>(JA, *this, Exec, CmdArgs);
  Cmd->setInputFileList(std::move(InputFileList));
  C.addCommand(std::move(Cmd));
d5891 1
a5891 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5911 1
a5911 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5934 1
a5934 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5941 1
  claimNoWarnArgs(Args);
d5954 1
a5954 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6059 109
a6167 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6174 1
  claimNoWarnArgs(Args);
d6237 1
a6237 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6369 1
a6369 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6376 1
  claimNoWarnArgs(Args);
d6389 1
a6389 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6505 1
a6505 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6512 1
  claimNoWarnArgs(Args);
d6586 1
a6586 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6685 1
a6685 1
  const ToolChain::path_list &Paths = ToolChain.getFilePaths();
a6697 1
  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
a6708 2
    if (NeedsSanitizerDeps)
      linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
d6763 2
d6769 1
a6769 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6776 1
  claimNoWarnArgs(Args);
d6843 1
a6843 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6879 1
d6881 1
a6896 18
  case llvm::Triple::armeb:
  case llvm::Triple::thumbeb:
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
    CmdArgs.push_back("-m");
    switch (getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::EABI:
    case llvm::Triple::GNUEABI:
      CmdArgs.push_back("armelfb_nbsd_eabi");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      CmdArgs.push_back("armelfb_nbsd_eabihf");
      break;
    default:
      CmdArgs.push_back("armelfb_nbsd");
      break;
    }
    break;
a6912 10
  case llvm::Triple::ppc:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32ppc_nbsd");
    break;

  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf64ppc");
    break;
a6972 2
    case llvm::Triple::ppc64:
    case llvm::Triple::ppc64le:
d7024 1
a7024 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a7031 2
  claimNoWarnArgs(Args);

d7197 1
a7197 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7281 1
a7281 5
    StringRef LibName;
    if (mips::isUCLibc(Args))
      LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
    else
      LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
d7306 1
a7306 1
                           ArgStringList &CmdArgs, const ArgList &Args) {
d7310 1
a7310 1
  switch (RLT) {
d7312 1
a7312 7
    switch (TC.getTriple().getOS()) {
    default: llvm_unreachable("unsupported OS");
    case llvm::Triple::Win32:
    case llvm::Triple::Linux:
      addClangRT(TC, Args, CmdArgs);
      break;
    }
a7319 47
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
  switch (T.getArch()) {
  case llvm::Triple::x86:
    return "elf_i386";
  case llvm::Triple::aarch64:
    return "aarch64linux";
  case llvm::Triple::aarch64_be:
    return "aarch64_be_linux";
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    return "armelf_linux_eabi";
  case llvm::Triple::armeb:
  case llvm::Triple::thumbeb:
    return "armebelf_linux_eabi"; /* TODO: check which NAME.  */
  case llvm::Triple::ppc:
    return "elf32ppclinux";
  case llvm::Triple::ppc64:
    return "elf64ppc";
  case llvm::Triple::ppc64le:
    return "elf64lppc";
  case llvm::Triple::sparc:
    return "elf32_sparc";
  case llvm::Triple::sparcv9:
    return "elf64_sparc";
  case llvm::Triple::mips:
    return "elf32btsmip";
  case llvm::Triple::mipsel:
    return "elf32ltsmip";
  case llvm::Triple::mips64:
    if (mips::hasMipsAbiArg(Args, "n32"))
      return "elf32btsmipn32";
    return "elf64btsmip";
  case llvm::Triple::mips64el:
    if (mips::hasMipsAbiArg(Args, "n32"))
      return "elf32ltsmipn32";
    return "elf64ltsmip";
  case llvm::Triple::systemz:
    return "elf64_s390";
  case llvm::Triple::x86_64:
    if (T.getEnvironment() == llvm::Triple::GNUX32)
      return "elf32_x86_64";
    return "elf_x86_64";
  default:
    llvm_unreachable("Unexpected arch");
  }
}

a7360 4
  if (ToolChain.getArch() == llvm::Triple::armeb ||
      ToolChain.getArch() == llvm::Triple::thumbeb)
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());

d7369 45
a7413 1
  CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args));
d7477 1
a7477 1
  const ToolChain::path_list &Paths = ToolChain.getFilePaths();
a7487 1
  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
d7489 2
a7511 3
      if (NeedsSanitizerDeps)
        linkSanitizerRuntimeDeps(ToolChain, CmdArgs);

d7568 1
a7568 2
  C.addCommand(
      llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
a7575 1
  claimNoWarnArgs(Args);
d7587 1
a7587 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7641 1
a7641 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a7652 1
  claimNoWarnArgs(Args);
d7669 1
a7669 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7677 1
d7680 3
a7682 1
  bool UseGCC47 = llvm::sys::fs::exists("/usr/lib/gcc47");
d7819 1
a7819 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7822 7
a7828 18
// Try to find Exe from a Visual Studio distribution.  This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
// from clang itself to prevent clang from falling back to itself.
static std::string FindVisualStudioExecutable(const ToolChain &TC,
                                              const char *Exe,
                                              const char *ClangProgramPath) {
  const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
  std::string visualStudioBinDir;
  if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath,
                                         visualStudioBinDir)) {
    SmallString<128> FilePath(visualStudioBinDir);
    llvm::sys::path::append(FilePath, Exe);
    if (llvm::sys::fs::can_execute(FilePath.c_str()))
      return FilePath.str();
  }

  return Exe;
a7836 1
  const ToolChain &TC = getToolChain();
d7838 1
a7838 2
  assert((Output.isFilename() || Output.isNothing()) && "invalid output");
  if (Output.isFilename())
d7841 3
d7846 2
a7847 1
      !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode())
a7848 32

  if (!llvm::sys::Process::GetEnv("LIB")) {
    // If the VC environment hasn't been configured (perhaps because the user
    // did not run vcvarsall), try to build a consistent link environment.  If
    // the environment variable is set however, assume the user knows what he's
    // doing.
    std::string VisualStudioDir;
    const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
    if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
      SmallString<128> LibDir(VisualStudioDir);
      llvm::sys::path::append(LibDir, "VC", "lib");
      switch (MSVC.getArch()) {
      case llvm::Triple::x86:
        // x86 just puts the libraries directly in lib
        break;
      case llvm::Triple::x86_64:
        llvm::sys::path::append(LibDir, "amd64");
        break;
      case llvm::Triple::arm:
        llvm::sys::path::append(LibDir, "arm");
        break;
      default:
        break;
      }
      CmdArgs.push_back(
          Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));
    }

    std::string WindowsSdkLibPath;
    if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
      CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
                                           WindowsSdkLibPath.c_str()));
d7853 1
a7853 1
  if (Args.hasArg(options::OPT_g_Group))
d7855 1
d7858 1
d7868 1
a7868 1
  if (TC.getSanitizerArgs().needsAsanRt()) {
d7871 4
a7874 12
    if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
      static const char *CompilerRTComponents[] = {
        "asan_dynamic",
        "asan_dynamic_runtime_thunk",
      };
      for (const auto &Component : CompilerRTComponents)
        CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
      // Make sure the dynamic runtime thunk is not optimized out at link time
      // to ensure proper SEH handling.
      CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
    } else if (DLL) {
      CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
d7876 2
a7877 6
      static const char *CompilerRTComponents[] = {
        "asan",
        "asan_cxx",
      };
      for (const auto &Component : CompilerRTComponents)
        CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
d7881 1
d7884 3
a7886 3
  // Add filenames, libraries, and other linker inputs.
  for (const auto &Input : Inputs) {
    if (Input.isFilename()) {
d7888 2
a7889 2
      continue;
    }
d7891 3
a7893 41
    const Arg &A = Input.getInputArg();

    // Render -l options differently for the MSVC linker.
    if (A.getOption().matches(options::OPT_l)) {
      StringRef Lib = A.getValue();
      const char *LinkLibArg;
      if (Lib.endswith(".lib"))
        LinkLibArg = Args.MakeArgString(Lib);
      else
        LinkLibArg = Args.MakeArgString(Lib + ".lib");
      CmdArgs.push_back(LinkLibArg);
      continue;
    }

    // Otherwise, this is some other kind of linker input option like -Wl, -z,
    // or -L. Render it, even if MSVC doesn't understand it.
    A.renderAsInput(Args, CmdArgs);
  }

  // We need to special case some linker paths.  In the case of lld, we need to
  // translate 'lld' into 'lld-link', and in the case of the regular msvc
  // linker, we need to use a special search algorithm.
  llvm::SmallString<128> linkPath;
  StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
  if (Linker.equals_lower("lld"))
    Linker = "lld-link";

  if (Linker.equals_lower("link")) {
    // If we're using the MSVC linker, it's not sufficient to just use link
    // from the program PATH, because other environments like GnuWin32 install
    // their own link.exe which may come first.
    linkPath = FindVisualStudioExecutable(TC, "link.exe",
                                          C.getDriver().getClangProgramPath());
  } else {
    linkPath = Linker;
    llvm::sys::path::replace_extension(linkPath, "exe");
    linkPath = TC.GetProgramPath(linkPath.c_str());
  }

  const char *Exec = Args.MakeArgString(linkPath);
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7904 34
a7937 4
std::unique_ptr<Command> visualstudio::Compile::GetCommand(
    Compilation &C, const JobAction &JA, const InputInfo &Output,
    const InputInfoList &Inputs, const ArgList &Args,
    const char *LinkingOutput) const {
d8015 2
a8016 4
  std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
                                                D.getClangProgramPath());
  return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                    CmdArgs);
a8027 1
  claimNoWarnArgs(Args);
d8053 1
a8053 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d8073 2
a8074 1
  if (exceptionSettings(Args, getToolChain().getTriple()))
d8080 1
a8080 179
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}

void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                          const InputInfo &Output,
                                          const InputInfoList &Inputs,
                                          const ArgList &Args,
                                          const char *LinkingOutput) const {
  claimNoWarnArgs(Args);
  const auto &TC =
      static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  ArgStringList CmdArgs;
  const char *Exec;

  switch (TC.getArch()) {
  default: llvm_unreachable("unsupported architecture");
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    break;
  case llvm::Triple::x86:
    CmdArgs.push_back("--32");
    break;
  case llvm::Triple::x86_64:
    CmdArgs.push_back("--64");
    break;
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &Input : Inputs)
    CmdArgs.push_back(Input.getFilename());

  const std::string Assembler = TC.GetProgramPath("as");
  Exec = Args.MakeArgString(Assembler);

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}

void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  const llvm::Triple &T = TC.getTriple();
  const Driver &D = TC.getDriver();
  SmallString<128> EntryPoint;
  ArgStringList CmdArgs;
  const char *Exec;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_w);
  // Other warning options are already handled somewhere else.

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_pie))
    CmdArgs.push_back("-pie");
  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");
  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("--strip-all");

  CmdArgs.push_back("-m");
  switch (TC.getArch()) {
  default: llvm_unreachable("unsupported architecture");
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    // FIXME: this is incorrect for WinCE
    CmdArgs.push_back("thumb2pe");
    break;
  case llvm::Triple::x86:
    CmdArgs.push_back("i386pe");
    EntryPoint.append("_");
    break;
  case llvm::Triple::x86_64:
    CmdArgs.push_back("i386pep");
    break;
  }

  if (Args.hasArg(options::OPT_shared)) {
    switch (T.getArch()) {
    default: llvm_unreachable("unsupported architecture");
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
    case llvm::Triple::x86_64:
      EntryPoint.append("_DllMainCRTStartup");
      break;
    case llvm::Triple::x86:
      EntryPoint.append("_DllMainCRTStartup@@12");
      break;
    }

    CmdArgs.push_back("-shared");
    CmdArgs.push_back("-Bdynamic");

    CmdArgs.push_back("--enable-auto-image-base");

    CmdArgs.push_back("--entry");
    CmdArgs.push_back(Args.MakeArgString(EntryPoint));
  } else {
    EntryPoint.append("mainCRTStartup");

    CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
                                                       : "-Bdynamic");

    if (!Args.hasArg(options::OPT_nostdlib) &&
        !Args.hasArg(options::OPT_nostartfiles)) {
      CmdArgs.push_back("--entry");
      CmdArgs.push_back(Args.MakeArgString(EntryPoint));
    }

    // FIXME: handle subsystem
  }

  // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
  CmdArgs.push_back("--allow-multiple-definition");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
    SmallString<261> ImpLib(Output.getFilename());
    llvm::sys::path::replace_extension(ImpLib, ".lib");

    CmdArgs.push_back("--out-implib");
    CmdArgs.push_back(Args.MakeArgString(ImpLib));
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    const std::string CRTPath(D.SysRoot + "/usr/lib/");
    const char *CRTBegin;

    CRTBegin =
        Args.hasArg(options::OPT_shared) ? "crtbeginS.obj" : "crtbegin.obj";
    CmdArgs.push_back(Args.MakeArgString(CRTPath + CRTBegin));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  const auto &Paths = TC.getFilePaths();
  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));

  AddLinkerInputs(TC, Inputs, Args, CmdArgs);

  if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
                     !Args.hasArg(options::OPT_static);
    if (StaticCXX)
      CmdArgs.push_back("-Bstatic");
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (StaticCXX)
      CmdArgs.push_back("-Bdynamic");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      // TODO handle /MT[d] /MD[d]
      CmdArgs.push_back("-lmsvcrt");
      AddRunTimeLibs(TC, D, CmdArgs, Args);
    }
  }

  const std::string Linker = TC.GetProgramPath("ld");
  Exec = Args.MakeArgString(Linker);

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
@


1.1.1.9
log
@Import Clang 3.6RC1 r227398.
@
text
@a85 17
// Add backslashes to escape spaces and other backslashes.
// This is used for the space-separated argument list specified with
// the -dwarf-debug-flags option.
static void EscapeSpacesAndBackslashes(const char *Arg,
                                       SmallVectorImpl<char> &Res) {
  for ( ; *Arg; ++Arg) {
    switch (*Arg) {
    default: break;
    case ' ':
    case '\\':
      Res.push_back('\\');
      break;
    }
    Res.push_back(*Arg);
  }
}

a461 2
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
d509 1
a509 1

a546 12
  } else if (FPU == "fp5-sp-d16" || FPU == "fpv5-sp-d16") {
    Features.push_back("+fp-armv8");
    Features.push_back("+fp-only-sp");
    Features.push_back("+d16");
    Features.push_back("-neon");
    Features.push_back("-crypto");
  } else if (FPU == "fp5-dp-d16" || FPU == "fpv5-dp-d16" ||
             FPU == "fp5-d16" || FPU == "fpv5-d16") {
    Features.push_back("+fp-armv8");
    Features.push_back("+d16");
    Features.push_back("-neon");
    Features.push_back("-crypto");
a560 6
  } else if (FPU == "neon-vfpv3") {
    Features.push_back("+vfp3");
    Features.push_back("+neon");
  } else if (FPU == "neon-vfpv4") {
    Features.push_back("+neon");
    Features.push_back("+vfp4");
a730 1
  // FIXME: Parts of this are duplicated in the backend, unify this somehow.
d738 2
a739 1
        Triple.getOS() == llvm::Triple::UnknownOS ||
d761 1
a761 5
      if (Triple.getOS() == llvm::Triple::NetBSD)
        ABIName = "apcs-gnu";
      else
        ABIName = "aapcs";
      break;
d809 1
a809 3
      else {
        if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
          D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
a810 1
      }
a896 13
  if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
                               options::OPT_mno_fix_cortex_a53_835769)) {
    CmdArgs.push_back("-backend-option");
    if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
      CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
    else
      CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
  } else if (Triple.getEnvironment() == llvm::Triple::Android) {
    // Enabled A53 errata (835769) workaround by default on android
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
  }

a903 5

  if (Args.hasArg(options::OPT_ffixed_x18)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-aarch64-reserve-x18");
  }
a922 4
  // MIPS3 is the default for mips64*-unknown-openbsd.
  if (Triple.getOS() == llvm::Triple::OpenBSD)
    DefMips64CPU = "mips3";

d1297 1
a1297 1
                                   std::vector<const char *> &Features) {
a1463 1
  case llvm::Triple::amdgcn:
d1637 1
a1637 1
static bool DecodeAArch64Features(const Driver &D, StringRef text,
a1745 3
  else if (Args.hasArg(options::OPT_arch))
    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), Args,
                                             Features);
a1752 3
  else if (Args.hasArg(options::OPT_arch))
    success = getAArch64MicroArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args),
                                                  Args, Features);
a1799 1
  case llvm::Triple::sparcv9:
d1851 9
d1862 10
a1871 1
static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) {
d1873 1
a1873 1
                               options::OPT_fno_exceptions))
d1875 11
a1885 1
      return true;
d1887 1
a1887 1
  return false;
d1912 2
a1913 2
  // Gather the exception settings from the command line arguments.
  bool EH = exceptionSettings(Args, Triple);
d1923 2
a1924 1
    EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
d1928 2
a1929 1
    bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore;
d1933 6
a1938 4
                                 options::OPT_fno_exceptions))
      CXXExceptionsEnabled =
          A->getOption().matches(options::OPT_fcxx_exceptions) ||
          A->getOption().matches(options::OPT_fexceptions);
d1943 1
a1943 1
      EH = true;
d1947 1
a1947 1
  if (EH)
d1973 1
a1973 1
  if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
d2041 2
a2042 1
          CmdArgs.push_back("-massembler-fatal-warnings");
d2075 2
a2076 5
  // FIXME: handle 64-bit
  if (TC.getTriple().isOSWindows() &&
      !TC.getTriple().isWindowsItaniumEnvironment())
    return "i386";
  if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
d2078 2
a2079 1
  return TC.getArchName();
d2087 2
a2088 2
  StringRef OSLibName =
      (Triple.getOS() == llvm::Triple::FreeBSD) ? "freebsd" : TC.getOS();
a2092 16
static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
                                      bool Shared = false,
                                      const char *Env = "") {
  bool IsOSWindows = TC.getTriple().isOSWindows();
  StringRef Arch = getArchNameForCompilerRTLib(TC);
  const char *Prefix = IsOSWindows ? "" : "lib";
  const char *Suffix =
      Shared ? (IsOSWindows ? ".dll" : ".so") : (IsOSWindows ? ".lib" : ".a");

  SmallString<128> Path = getCompilerRTLibDir(TC);
  llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
                                    Arch + Env + Suffix);

  return Path;
}

d2096 11
a2106 10
static void addClangRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "builtins")));

  if (!TC.getTriple().isOSWindows()) {
    // FIXME: why do we link against gcc when we are using compiler-rt?
    CmdArgs.push_back("-lgcc_s");
    if (TC.getDriver().CCCIsCXX())
      CmdArgs.push_back("-lgcc_eh");
  }
d2109 2
a2110 2
static void addProfileRT(const ToolChain &TC, const ArgList &Args,
                         ArgStringList &CmdArgs) {
d2119 6
a2124 9
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
}

static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
                                ArgStringList &CmdArgs, StringRef Sanitizer,
                                bool IsShared) {
  const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
                        ? "-android"
                        : "";
d2126 20
a2145 8
  // Static runtimes must be forced into executable, so we wrap them in
  // whole-archive.
  if (!IsShared)
    CmdArgs.push_back("-whole-archive");
  CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared,
                                                     Env)));
  if (!IsShared)
    CmdArgs.push_back("-no-whole-archive");
d2148 1
a2148 3
// Tries to use a file with the list of dynamic symbols that need to be exported
// from the runtime library. Returns true if the file was found.
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
d2150 29
a2178 5
                                    StringRef Sanitizer) {
  SmallString<128> SanRT = getCompilerRT(TC, Sanitizer);
  if (llvm::sys::fs::exists(SanRT + ".syms")) {
    CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
    return true;
a2179 2
  return false;
}
d2181 10
a2190 11
static void linkSanitizerRuntimeDeps(const ToolChain &TC,
                                     ArgStringList &CmdArgs) {
  // Force linking against the system libraries sanitizers depends on
  // (see PR15823 why this is necessary).
  CmdArgs.push_back("--no-as-needed");
  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-lm");
  // There's no libdl on FreeBSD.
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
    CmdArgs.push_back("-ldl");
d2193 9
a2201 9
static void
collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
                         SmallVectorImpl<StringRef> &SharedRuntimes,
                         SmallVectorImpl<StringRef> &StaticRuntimes,
                         SmallVectorImpl<StringRef> &HelperStaticRuntimes) {
  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
  // Collect shared runtimes.
  if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) {
    SharedRuntimes.push_back("asan");
d2204 1
a2204 1
  // Collect static runtimes.
d2206 1
a2206 2
      (TC.getTriple().getEnvironment() == llvm::Triple::Android)) {
    // Don't link static runtimes into DSOs or if compiling for Android.
d2208 9
a2216 27
  }
  if (SanArgs.needsAsanRt()) {
    if (SanArgs.needsSharedAsanRt()) {
      HelperStaticRuntimes.push_back("asan-preinit");
    } else {
      StaticRuntimes.push_back("asan");
      if (SanArgs.linkCXXRuntimes())
        StaticRuntimes.push_back("asan_cxx");
    }
  }
  if (SanArgs.needsDfsanRt())
    StaticRuntimes.push_back("dfsan");
  if (SanArgs.needsLsanRt())
    StaticRuntimes.push_back("lsan");
  if (SanArgs.needsMsanRt())
    StaticRuntimes.push_back("msan");
  if (SanArgs.needsTsanRt())
    StaticRuntimes.push_back("tsan");
  // WARNING: UBSan should always go last.
  if (SanArgs.needsUbsanRt()) {
    // If UBSan is not combined with another sanitizer, we need to pull in
    // sanitizer_common explicitly.
    if (StaticRuntimes.empty())
      HelperStaticRuntimes.push_back("san");
    StaticRuntimes.push_back("ubsan");
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("ubsan_cxx");
d2220 54
a2273 3
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
d2275 16
a2290 18
  SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
      HelperStaticRuntimes;
  collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
                           HelperStaticRuntimes);
  for (auto RT : SharedRuntimes)
    addSanitizerRuntime(TC, Args, CmdArgs, RT, true);
  for (auto RT : HelperStaticRuntimes)
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
  bool AddExportDynamic = false;
  for (auto RT : StaticRuntimes) {
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
    AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
  }
  // If there is a static runtime with no dynamic list, force all the symbols
  // to be dynamic to be sure we export sanitizer interface functions.
  if (AddExportDynamic)
    CmdArgs.push_back("-export-dynamic");
  return !StaticRuntimes.empty();
d2380 1
a2380 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs));
d2383 1
a2383 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs));
a2452 10
// Claim options we don't want to warn if they are unused. We do this for
// options that build systems might add but are unused when assembling or only
// running the preprocessor for example.
static void claimNoWarnArgs(const ArgList &Args) {
  // Don't warn about unused -f(no-)?lto.  This can happen when we're
  // preprocessing, precompiling or assembling.
  Args.ClaimAllArgs(options::OPT_flto);
  Args.ClaimAllArgs(options::OPT_fno_lto);
}

d2533 1
a2533 2
    assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
           "Invalid action for clang tool.");
d2726 2
a2727 1
  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)))
a2766 6
  CmdArgs.push_back("-mthread-model");
  if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
    CmdArgs.push_back(A->getValue());
  else
    CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));

a2772 13
  if (Args.hasArg(options::OPT_frewrite_map_file) ||
      Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
    for (arg_iterator
             MFI = Args.filtered_begin(options::OPT_frewrite_map_file,
                                       options::OPT_frewrite_map_file_EQ),
             MFE = Args.filtered_end();
         MFI != MFE; ++MFI) {
      CmdArgs.push_back("-frewrite-map-file");
      CmdArgs.push_back((*MFI)->getValue());
      (*MFI)->claim();
    }
  }

d3142 1
a3142 2
    if (A->getOption().matches(options::OPT_gline_tables_only) ||
        A->getOption().matches(options::OPT_g1)) {
d3146 1
a3146 1
      // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
d3149 1
a3149 2
          Triple.getOS() == llvm::Triple::FreeBSD ||
          Triple.getOS() == llvm::Triple::Solaris)
d3159 1
a3159 1
      // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris.
d3162 1
a3162 2
          Triple.getOS() == llvm::Triple::FreeBSD ||
          Triple.getOS() == llvm::Triple::Solaris)
d3250 1
a3250 6
      SmallString<128> CoverageFilename;
      if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
        CoverageFilename = FinalOutput->getValue();
      } else {
        CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
      }
d3378 3
a3380 1
  claimNoWarnArgs(Args);
a3402 1
    // If -f(no-)trigraphs appears after the language standard flag, honor it.
d3404 1
a3404 2
                                 options::OPT_ftrigraphs,
                                 options::OPT_fno_trigraphs))
d3420 1
a3420 2
    Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
                    options::OPT_fno_trigraphs);
a3538 5
  if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
    CmdArgs.push_back("-fspell-checking-limit");
    CmdArgs.push_back(A->getValue());
  }

d3590 9
a3706 4
  if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
      getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be)
    CmdArgs.push_back("-fallow-half-arguments-and-returns");

d3772 3
a3774 3
  // -fmodules enables modules (off by default).
  // Users can pass -fno-cxx-modules to turn off modules support for
  // C++/Objective-C++ programs, which is a little less mature.
d3779 1
a3779 1
                                     true);
d3811 2
a3812 1
  Args.AddLastArg(CmdArgs, options::OPT_fmodule_name);
d3814 1
a3814 1
  // -fmodule-map-file can be used to specify files containing module
d3816 2
a3817 1
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
d3819 1
a3819 5
  // -fmodule-file can be used to specify files containing precompiled modules.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);

  // -fmodule-cache-path specifies where our implicitly-built module files
  // should be written.
a3846 3
    // Add the cache directory as a temp so the crash diagnostics pick it up.
    C.addTempFile(Args.MakeArgString(VFSDir));

d3852 3
a3854 2
  if (HaveModules)
    Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
a4179 8
  // -fexec_charset=UTF-8 is default. Reject others
  if (Arg *execCharset = Args.getLastArg(
          options::OPT_fexec_charset_EQ)) {
      StringRef value = execCharset->getValue();
      if (value != "UTF-8")
          D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args) << value;
  }

a4384 1
  bool OptDisabled = false;
d4391 1
a4391 1
    if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") {
d4393 1
a4393 2
      OptDisabled = true;
    } else
a4396 7
  // With -save-temps, we want to save the unoptimized bitcode output from the
  // CompileJobAction, so disable optimizations if they are not already
  // disabled.
  if (Args.hasArg(options::OPT_save_temps) && !OptDisabled &&
      isa<CompileJobAction>(JA))
    CmdArgs.push_back("-disable-llvm-optzns");

a4428 2
      SmallString<128> EscapedArg;
      EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
d4430 1
a4430 1
      Flags += EscapedArg;
d4440 1
a4440 2
    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
     isa<BackendJobAction>(JA));
d4452 3
a4454 4
    auto CLCommand =
        getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
    C.addCommand(llvm::make_unique<FallbackCommand>(JA, *this, Exec, CmdArgs,
                                                    std::move(CLCommand)));
d4456 1
a4456 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d4463 1
a4463 1
  if (SplitDwarf && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
a4779 2
  claimNoWarnArgs(Args);

a4858 2
      SmallString<128> EscapedArg;
      EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg);
d4860 1
a4860 1
      Flags += EscapedArg;
d4891 1
a4891 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a4901 2
void GnuTool::anchor() {}

d4934 1
d4937 10
a4946 2
    CmdArgs.push_back(
      Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
a4953 1
  llvm::Triple::ArchType Arch = getToolChain().getArch();
d5024 1
a5024 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5063 1
  claimNoWarnArgs(Args);
d5120 1
a5120 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5197 2
a5198 2
  const std::string RootDir =
      toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/";
d5286 1
a5286 2
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs));
d5351 2
a5352 2
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
d5356 1
a5356 1
    .Cases("cortex-m4", "cortex-m7", "v7em")
a5362 14
void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) {
  if (Args.hasArg(options::OPT_r))
    return;

  StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple));
  const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
    .Cases("v4", "v4t", "v5", "v5e", nullptr)
    .Cases("v6", "v6t2", nullptr)
    .Default("--be8");

  if (LinkFlag)
    CmdArgs.push_back(LinkFlag);
}

a5367 5
bool mips::isUCLibc(const ArgList &Args) {
  Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
  return A && A->getOption().matches(options::OPT_muclibc);
}

a5425 1
    .Case("amdgcn", llvm::Triple::amdgcn)
d5542 1
a5542 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5757 6
  // If the number of arguments surpasses the system limits, we will encode the
  // input files in a separate file, shortening the command line. To this end,
  // build a list of input file names that can be passed via a file with the
  // -filelist linker option.
  llvm::opt::ArgStringList InputFileList;

d5771 1
a5771 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5826 1
a5826 17
  // Build the input file for -filelist (list of linker input files) in case we
  // need it later
  for (const auto &II : Inputs) {
    if (!II.isFilename()) {
      // This is a linker input argument.
      // We cannot mix input arguments and file names in a -filelist input, thus
      // we prematurely stop our list (remaining files shall be passed as
      // arguments).
      if (InputFileList.size() > 0)
        break;

      continue;
    }

    InputFileList.push_back(II.getFilename());
  }

d5869 1
a5869 4
  std::unique_ptr<Command> Cmd =
    llvm::make_unique<Command>(JA, *this, Exec, CmdArgs);
  Cmd->setInputFileList(std::move(InputFileList));
  C.addCommand(std::move(Cmd));
d5891 1
a5891 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5911 1
a5911 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d5934 1
a5934 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a5941 1
  claimNoWarnArgs(Args);
d5954 1
a5954 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6059 109
a6167 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6174 1
  claimNoWarnArgs(Args);
d6237 1
a6237 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6369 1
a6369 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6376 1
  claimNoWarnArgs(Args);
d6389 1
a6389 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6505 1
a6505 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6512 1
  claimNoWarnArgs(Args);
d6586 1
a6586 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6685 1
a6685 1
  const ToolChain::path_list &Paths = ToolChain.getFilePaths();
a6697 1
  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
a6708 2
    if (NeedsSanitizerDeps)
      linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
d6763 2
d6769 1
a6769 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a6776 1
  claimNoWarnArgs(Args);
d6843 1
a6843 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d6879 1
d6881 1
a6896 18
  case llvm::Triple::armeb:
  case llvm::Triple::thumbeb:
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
    CmdArgs.push_back("-m");
    switch (getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::EABI:
    case llvm::Triple::GNUEABI:
      CmdArgs.push_back("armelfb_nbsd_eabi");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      CmdArgs.push_back("armelfb_nbsd_eabihf");
      break;
    default:
      CmdArgs.push_back("armelfb_nbsd");
      break;
    }
    break;
a6912 10
  case llvm::Triple::ppc:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32ppc_nbsd");
    break;

  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf64ppc");
    break;
a6972 2
    case llvm::Triple::ppc64:
    case llvm::Triple::ppc64le:
d7024 1
a7024 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a7031 2
  claimNoWarnArgs(Args);

d7197 1
a7197 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7281 1
a7281 5
    StringRef LibName;
    if (mips::isUCLibc(Args))
      LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0";
    else
      LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";
d7306 1
a7306 1
                           ArgStringList &CmdArgs, const ArgList &Args) {
d7310 1
a7310 1
  switch (RLT) {
d7312 1
a7312 7
    switch (TC.getTriple().getOS()) {
    default: llvm_unreachable("unsupported OS");
    case llvm::Triple::Win32:
    case llvm::Triple::Linux:
      addClangRT(TC, Args, CmdArgs);
      break;
    }
a7319 47
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
  switch (T.getArch()) {
  case llvm::Triple::x86:
    return "elf_i386";
  case llvm::Triple::aarch64:
    return "aarch64linux";
  case llvm::Triple::aarch64_be:
    return "aarch64_be_linux";
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    return "armelf_linux_eabi";
  case llvm::Triple::armeb:
  case llvm::Triple::thumbeb:
    return "armebelf_linux_eabi"; /* TODO: check which NAME.  */
  case llvm::Triple::ppc:
    return "elf32ppclinux";
  case llvm::Triple::ppc64:
    return "elf64ppc";
  case llvm::Triple::ppc64le:
    return "elf64lppc";
  case llvm::Triple::sparc:
    return "elf32_sparc";
  case llvm::Triple::sparcv9:
    return "elf64_sparc";
  case llvm::Triple::mips:
    return "elf32btsmip";
  case llvm::Triple::mipsel:
    return "elf32ltsmip";
  case llvm::Triple::mips64:
    if (mips::hasMipsAbiArg(Args, "n32"))
      return "elf32btsmipn32";
    return "elf64btsmip";
  case llvm::Triple::mips64el:
    if (mips::hasMipsAbiArg(Args, "n32"))
      return "elf32ltsmipn32";
    return "elf64ltsmip";
  case llvm::Triple::systemz:
    return "elf64_s390";
  case llvm::Triple::x86_64:
    if (T.getEnvironment() == llvm::Triple::GNUX32)
      return "elf32_x86_64";
    return "elf_x86_64";
  default:
    llvm_unreachable("Unexpected arch");
  }
}

a7360 4
  if (ToolChain.getArch() == llvm::Triple::armeb ||
      ToolChain.getArch() == llvm::Triple::thumbeb)
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());

d7369 45
a7413 1
  CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args));
d7477 1
a7477 1
  const ToolChain::path_list &Paths = ToolChain.getFilePaths();
a7487 1
  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
d7489 2
a7511 3
      if (NeedsSanitizerDeps)
        linkSanitizerRuntimeDeps(ToolChain, CmdArgs);

d7568 1
a7568 2
  C.addCommand(
      llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
a7575 1
  claimNoWarnArgs(Args);
d7587 1
a7587 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7641 1
a7641 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
a7652 1
  claimNoWarnArgs(Args);
d7669 1
a7669 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7677 1
d7680 3
a7682 1
  bool UseGCC47 = llvm::sys::fs::exists("/usr/lib/gcc47");
d7819 1
a7819 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7822 7
a7828 18
// Try to find Exe from a Visual Studio distribution.  This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
// from clang itself to prevent clang from falling back to itself.
static std::string FindVisualStudioExecutable(const ToolChain &TC,
                                              const char *Exe,
                                              const char *ClangProgramPath) {
  const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
  std::string visualStudioBinDir;
  if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath,
                                         visualStudioBinDir)) {
    SmallString<128> FilePath(visualStudioBinDir);
    llvm::sys::path::append(FilePath, Exe);
    if (llvm::sys::fs::can_execute(FilePath.c_str()))
      return FilePath.str();
  }

  return Exe;
a7836 1
  const ToolChain &TC = getToolChain();
d7838 1
a7838 2
  assert((Output.isFilename() || Output.isNothing()) && "invalid output");
  if (Output.isFilename())
d7841 3
d7846 2
a7847 1
      !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode())
a7848 32

  if (!llvm::sys::Process::GetEnv("LIB")) {
    // If the VC environment hasn't been configured (perhaps because the user
    // did not run vcvarsall), try to build a consistent link environment.  If
    // the environment variable is set however, assume the user knows what he's
    // doing.
    std::string VisualStudioDir;
    const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
    if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
      SmallString<128> LibDir(VisualStudioDir);
      llvm::sys::path::append(LibDir, "VC", "lib");
      switch (MSVC.getArch()) {
      case llvm::Triple::x86:
        // x86 just puts the libraries directly in lib
        break;
      case llvm::Triple::x86_64:
        llvm::sys::path::append(LibDir, "amd64");
        break;
      case llvm::Triple::arm:
        llvm::sys::path::append(LibDir, "arm");
        break;
      default:
        break;
      }
      CmdArgs.push_back(
          Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));
    }

    std::string WindowsSdkLibPath;
    if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
      CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
                                           WindowsSdkLibPath.c_str()));
d7853 1
a7853 1
  if (Args.hasArg(options::OPT_g_Group))
d7855 1
d7858 1
d7868 1
a7868 1
  if (TC.getSanitizerArgs().needsAsanRt()) {
d7871 4
a7874 12
    if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
      static const char *CompilerRTComponents[] = {
        "asan_dynamic",
        "asan_dynamic_runtime_thunk",
      };
      for (const auto &Component : CompilerRTComponents)
        CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
      // Make sure the dynamic runtime thunk is not optimized out at link time
      // to ensure proper SEH handling.
      CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
    } else if (DLL) {
      CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
d7876 2
a7877 6
      static const char *CompilerRTComponents[] = {
        "asan",
        "asan_cxx",
      };
      for (const auto &Component : CompilerRTComponents)
        CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
d7881 1
d7884 3
a7886 3
  // Add filenames, libraries, and other linker inputs.
  for (const auto &Input : Inputs) {
    if (Input.isFilename()) {
d7888 2
a7889 2
      continue;
    }
d7891 3
a7893 41
    const Arg &A = Input.getInputArg();

    // Render -l options differently for the MSVC linker.
    if (A.getOption().matches(options::OPT_l)) {
      StringRef Lib = A.getValue();
      const char *LinkLibArg;
      if (Lib.endswith(".lib"))
        LinkLibArg = Args.MakeArgString(Lib);
      else
        LinkLibArg = Args.MakeArgString(Lib + ".lib");
      CmdArgs.push_back(LinkLibArg);
      continue;
    }

    // Otherwise, this is some other kind of linker input option like -Wl, -z,
    // or -L. Render it, even if MSVC doesn't understand it.
    A.renderAsInput(Args, CmdArgs);
  }

  // We need to special case some linker paths.  In the case of lld, we need to
  // translate 'lld' into 'lld-link', and in the case of the regular msvc
  // linker, we need to use a special search algorithm.
  llvm::SmallString<128> linkPath;
  StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
  if (Linker.equals_lower("lld"))
    Linker = "lld-link";

  if (Linker.equals_lower("link")) {
    // If we're using the MSVC linker, it's not sufficient to just use link
    // from the program PATH, because other environments like GnuWin32 install
    // their own link.exe which may come first.
    linkPath = FindVisualStudioExecutable(TC, "link.exe",
                                          C.getDriver().getClangProgramPath());
  } else {
    linkPath = Linker;
    llvm::sys::path::replace_extension(linkPath, "exe");
    linkPath = TC.GetProgramPath(linkPath.c_str());
  }

  const char *Exec = Args.MakeArgString(linkPath);
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d7904 34
a7937 4
std::unique_ptr<Command> visualstudio::Compile::GetCommand(
    Compilation &C, const JobAction &JA, const InputInfo &Output,
    const InputInfoList &Inputs, const ArgList &Args,
    const char *LinkingOutput) const {
d8015 2
a8016 4
  std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
                                                D.getClangProgramPath());
  return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                    CmdArgs);
a8027 1
  claimNoWarnArgs(Args);
d8053 1
a8053 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
d8073 2
a8074 1
  if (exceptionSettings(Args, getToolChain().getTriple()))
d8080 1
a8080 179
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}

void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                          const InputInfo &Output,
                                          const InputInfoList &Inputs,
                                          const ArgList &Args,
                                          const char *LinkingOutput) const {
  claimNoWarnArgs(Args);
  const auto &TC =
      static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  ArgStringList CmdArgs;
  const char *Exec;

  switch (TC.getArch()) {
  default: llvm_unreachable("unsupported architecture");
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    break;
  case llvm::Triple::x86:
    CmdArgs.push_back("--32");
    break;
  case llvm::Triple::x86_64:
    CmdArgs.push_back("--64");
    break;
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &Input : Inputs)
    CmdArgs.push_back(Input.getFilename());

  const std::string Assembler = TC.GetProgramPath("as");
  Exec = Args.MakeArgString(Assembler);

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}

void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  const llvm::Triple &T = TC.getTriple();
  const Driver &D = TC.getDriver();
  SmallString<128> EntryPoint;
  ArgStringList CmdArgs;
  const char *Exec;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_w);
  // Other warning options are already handled somewhere else.

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_pie))
    CmdArgs.push_back("-pie");
  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");
  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("--strip-all");

  CmdArgs.push_back("-m");
  switch (TC.getArch()) {
  default: llvm_unreachable("unsupported architecture");
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    // FIXME: this is incorrect for WinCE
    CmdArgs.push_back("thumb2pe");
    break;
  case llvm::Triple::x86:
    CmdArgs.push_back("i386pe");
    EntryPoint.append("_");
    break;
  case llvm::Triple::x86_64:
    CmdArgs.push_back("i386pep");
    break;
  }

  if (Args.hasArg(options::OPT_shared)) {
    switch (T.getArch()) {
    default: llvm_unreachable("unsupported architecture");
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
    case llvm::Triple::x86_64:
      EntryPoint.append("_DllMainCRTStartup");
      break;
    case llvm::Triple::x86:
      EntryPoint.append("_DllMainCRTStartup@@12");
      break;
    }

    CmdArgs.push_back("-shared");
    CmdArgs.push_back("-Bdynamic");

    CmdArgs.push_back("--enable-auto-image-base");

    CmdArgs.push_back("--entry");
    CmdArgs.push_back(Args.MakeArgString(EntryPoint));
  } else {
    EntryPoint.append("mainCRTStartup");

    CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
                                                       : "-Bdynamic");

    if (!Args.hasArg(options::OPT_nostdlib) &&
        !Args.hasArg(options::OPT_nostartfiles)) {
      CmdArgs.push_back("--entry");
      CmdArgs.push_back(Args.MakeArgString(EntryPoint));
    }

    // FIXME: handle subsystem
  }

  // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
  CmdArgs.push_back("--allow-multiple-definition");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
    SmallString<261> ImpLib(Output.getFilename());
    llvm::sys::path::replace_extension(ImpLib, ".lib");

    CmdArgs.push_back("--out-implib");
    CmdArgs.push_back(Args.MakeArgString(ImpLib));
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    const std::string CRTPath(D.SysRoot + "/usr/lib/");
    const char *CRTBegin;

    CRTBegin =
        Args.hasArg(options::OPT_shared) ? "crtbeginS.obj" : "crtbegin.obj";
    CmdArgs.push_back(Args.MakeArgString(CRTPath + CRTBegin));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  const auto &Paths = TC.getFilePaths();
  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));

  AddLinkerInputs(TC, Inputs, Args, CmdArgs);

  if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
                     !Args.hasArg(options::OPT_static);
    if (StaticCXX)
      CmdArgs.push_back("-Bstatic");
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (StaticCXX)
      CmdArgs.push_back("-Bdynamic");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      // TODO handle /MT[d] /MD[d]
      CmdArgs.push_back("-lmsvcrt");
      AddRunTimeLibs(TC, D, CmdArgs, Args);
    }
  }

  const std::string Linker = TC.GetProgramPath("ld");
  Exec = Args.MakeArgString(Linker);

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
@


1.1.1.10
log
@Import Clang r232565 post-3.6.0. Various bugfixes, especially for ARM.
@
text
@a15 1
#include "clang/Config/config.h"
d1541 1
a1541 1
  std::string Plugin = ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
@


1.1.1.11
log
@Import Clang 3.8.0rc3 r261930.
@
text
@d1 1
a1 1
//===--- Tools.cpp - Tools Implementations ----------------------*- C++ -*-===//
a12 1
#include "clang/Basic/CharInfo.h"
a25 1
#include "llvm/ADT/STLExtras.h"
a32 1
#include "llvm/Support/CodeGen.h"
d36 1
a41 5
#include "llvm/Support/TargetParser.h"

#ifdef LLVM_ON_UNIX
#include <unistd.h> // For getuid().
#endif
d48 12
a59 45
static void handleTargetFeaturesGroup(const ArgList &Args,
                                      std::vector<const char *> &Features,
                                      OptSpecifier Group) {
  for (const Arg *A : Args.filtered(Group)) {
    StringRef Name = A->getOption().getName();
    A->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);
    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }
}

static const char *getSparcAsmModeForCPU(StringRef Name,
                                         const llvm::Triple &Triple) {
  if (Triple.getArch() == llvm::Triple::sparcv9) {
    return llvm::StringSwitch<const char *>(Name)
          .Case("niagara", "-Av9b")
          .Case("niagara2", "-Av9b")
          .Case("niagara3", "-Av9d")
          .Case("niagara4", "-Av9d")
          .Default("-Av9");
  } else {
    return llvm::StringSwitch<const char *>(Name)
          .Case("v8", "-Av8")
          .Case("supersparc", "-Av8")
          .Case("sparclite", "-Asparclite")
          .Case("f934", "-Asparclite")
          .Case("hypersparc", "-Av8")
          .Case("sparclite86x", "-Asparclite")
          .Case("sparclet", "-Asparclet")
          .Case("tsc701", "-Asparclet")
          .Case("v9", "-Av8plus")
          .Case("ultrasparc", "-Av8plus")
          .Case("ultrasparc3", "-Av8plus")
          .Case("niagara", "-Av8plusb")
          .Case("niagara2", "-Av8plusb")
          .Case("niagara3", "-Av8plusd")
          .Case("niagara4", "-Av8plusd")
          .Default("-Av8");
d81 4
a84 4
    if (const Arg *A =
            Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic))
      D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
                                                      << "-static";
d92 1
a92 1
  for (; *Arg; ++Arg) {
d94 1
a94 2
    default:
      break;
d106 2
a107 1
static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
d133 4
a136 2
static void addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
                             const char *ArgName, const char *EnvVar) {
d162 1
a162 2
        CmdArgs.push_back(
            Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
d188 3
a190 2
static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
                            const ArgList &Args, ArgStringList &CmdArgs) {
d198 1
a198 1
    if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
d200 7
a206 1
      D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
d227 1
a227 1
      A.renderAsInput(Args, CmdArgs);
d256 2
a257 1
         !O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);
d260 4
a263 2
void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
                                    const Driver &D, const ArgList &Args,
d266 1
a266 2
                                    const InputInfoList &Inputs,
                                    const ToolChain *AuxToolChain) const {
d322 2
a323 3
    if ((isa<PrecompileJobAction>(JA) &&
         !Args.hasArg(options::OPT_fno_module_file_deps)) ||
        Args.hasArg(options::OPT_fmodule_file_deps))
d329 1
a329 1
        A->getOption().matches(options::OPT_MMD))
a334 1
  Args.AddLastArg(CmdArgs, options::OPT_MV);
d337 4
a340 1
  for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) {
d349 1
a349 1
      // -MT flag - no change
d361 4
a364 1
  for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
d380 1
a380 1
        if (llvm::sys::fs::exists(P))
d386 1
a386 1
        if (llvm::sys::fs::exists(P))
d392 1
a392 1
        if (llvm::sys::fs::exists(P)) {
d405 1
a405 1
          CmdArgs.push_back(Args.MakeArgString(P));
d409 2
a410 2
          D.Diag(diag::warn_drv_pch_not_first_include) << P
                                                       << A->getAsString(Args);
d420 3
a422 3
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_D, options::OPT_U, options::OPT_I_Group,
                   options::OPT_F, options::OPT_index_header_map});
d424 1
a424 1
  // Add -Wp, and -Xpreprocessor if using the preprocessor.
a461 5
  // Optional AuxToolChain indicates that we need to include headers
  // for more than one target. If that's the case, add include paths
  // from AuxToolChain right after include paths of the same kind for
  // the current target.

d463 1
a463 1
  if (types::isCXX(Inputs[0].getType())) {
a464 3
    if (AuxToolChain)
      AuxToolChain->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
  }
a467 6
  if (AuxToolChain)
      AuxToolChain->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);

  // Add CUDA include arguments, if needed.
  if (types::isCuda(Inputs[0].getType()))
    getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
a491 1
  case llvm::Triple::hexagon:
a504 2
  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
a508 35
// ARM tools start.

// Get SubArch (vN).
static int getARMSubArchVersionNumber(const llvm::Triple &Triple) {
  llvm::StringRef Arch = Triple.getArchName();
  return llvm::ARM::parseArchVersion(Arch);
}

// True if M-profile.
static bool isARMMProfile(const llvm::Triple &Triple) {
  llvm::StringRef Arch = Triple.getArchName();
  unsigned Profile = llvm::ARM::parseArchProfile(Arch);
  return Profile == llvm::ARM::PK_M;
}

// Get Arch/CPU from args.
static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
                                  llvm::StringRef &CPU, bool FromAs = false) {
  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
    CPU = A->getValue();
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
    Arch = A->getValue();
  if (!FromAs)
    return;

  for (const Arg *A :
       Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
    StringRef Value = A->getValue();
    if (Value.startswith("-mcpu="))
      CPU = Value.substr(6);
    if (Value.startswith("-march="))
      Arch = Value.substr(7);
  }
}

a509 1
// FIXME: Use ARMTargetParser.
d511 16
a526 4
                                const ArgList &Args, StringRef HWDiv,
                                std::vector<const char *> &Features) {
  unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
  if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
d531 3
d535 1
a535 1
                              const ArgList &Args, StringRef FPU,
d537 1
a537 4
  unsigned FPUID = llvm::ARM::parseFPU(FPU);
  if (!llvm::ARM::getFPUFeatures(FPUID, Features))
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
d539 68
a606 41
// Decode ARM features from string like +[no]featureA+[no]featureB+...
static bool DecodeARMFeatures(const Driver &D, StringRef text,
                              std::vector<const char *> &Features) {
  SmallVector<StringRef, 8> Split;
  text.split(Split, StringRef("+"), -1, false);

  for (StringRef Feature : Split) {
    const char *FeatureName = llvm::ARM::getArchExtFeature(Feature);
    if (FeatureName)
      Features.push_back(FeatureName);
    else
      return false;
  }
  return true;
}

// Check if -march is valid by checking if it can be canonicalised and parsed.
// getARMArch is used here instead of just checking the -march value in order
// to handle -march=native correctly.
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
                             llvm::StringRef ArchName,
                             std::vector<const char *> &Features,
                             const llvm::Triple &Triple) {
  std::pair<StringRef, StringRef> Split = ArchName.split("+");

  std::string MArch = arm::getARMArch(ArchName, Triple);
  if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID ||
      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
                            llvm::StringRef CPUName, llvm::StringRef ArchName,
                            std::vector<const char *> &Features,
                            const llvm::Triple &Triple) {
  std::pair<StringRef, StringRef> Split = CPUName.split("+");

  std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
  if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() ||
      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
a609 7
static bool useAAPCSForMachO(const llvm::Triple &T) {
  // The backend is hardwired to assume AAPCS for M-class processors, ensure
  // the frontend matches that.
  return T.getEnvironment() == llvm::Triple::EABI ||
         T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
}

d612 16
a627 21
arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
  const Driver &D = TC.getDriver();
  const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(Args));
  auto SubArch = getARMSubArchVersionNumber(Triple);
  arm::FloatABI ABI = FloatABI::Invalid;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
                          options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float)) {
      ABI = FloatABI::Soft;
    } else if (A->getOption().matches(options::OPT_mhard_float)) {
      ABI = FloatABI::Hard;
    } else {
      ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
                .Case("soft", FloatABI::Soft)
                .Case("softfp", FloatABI::SoftFP)
                .Case("hard", FloatABI::Hard)
                .Default(FloatABI::Invalid);
      if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        ABI = FloatABI::Soft;
a629 8

    // It is incorrect to select hard float ABI on MachO platforms if the ABI is
    // "apcs-gnu".
    if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) &&
        ABI == FloatABI::Hard) {
      D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args)
                                                       << Triple.getArchName();
    }
d633 1
a633 1
  if (ABI == FloatABI::Invalid) {
d637 1
a637 2
    case llvm::Triple::IOS:
    case llvm::Triple::TvOS: {
d639 9
a647 1
      ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
a649 3
    case llvm::Triple::WatchOS:
      ABI = FloatABI::Hard;
      break;
d653 1
a653 1
      ABI = FloatABI::Hard;
d657 1
a657 1
      switch (Triple.getEnvironment()) {
d659 1
a659 1
        ABI = FloatABI::Hard;
d663 1
a663 1
        ABI = FloatABI::Soft;
d669 1
a669 1
      switch (Triple.getEnvironment()) {
d671 5
d677 1
a677 1
        ABI = FloatABI::Hard;
a678 1
      case llvm::Triple::GNUEABI:
d681 1
a681 1
        ABI = FloatABI::SoftFP;
d683 7
a689 2
      case llvm::Triple::Android:
        ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
d691 1
d694 1
a694 1
        ABI = FloatABI::Soft;
d703 1
a703 2
  assert(ABI != FloatABI::Invalid && "must select an ABI");
  return ABI;
d706 1
a706 2
static void getARMTargetFeatures(const ToolChain &TC,
                                 const llvm::Triple &Triple,
d710 1
a710 8
  const Driver &D = TC.getDriver();

  bool KernelOrKext =
      Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
  arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
  const Arg *WaCPU = nullptr, *WaFPU = nullptr;
  const Arg *WaHDiv = nullptr, *WaArch = nullptr;

d725 1
a725 1
    if (ABI == arm::FloatABI::Soft)
d729 1
a729 1
    if (ABI != arm::FloatABI::Hard)
a730 32
  } else {
    // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
    // to the assembler correctly.
    for (const Arg *A :
         Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
      StringRef Value = A->getValue();
      if (Value.startswith("-mfpu=")) {
        WaFPU = A;
      } else if (Value.startswith("-mcpu=")) {
        WaCPU = A;
      } else if (Value.startswith("-mhwdiv=")) {
        WaHDiv = A;
      } else if (Value.startswith("-march=")) {
        WaArch = A;
      }
    }
  }

  // Check -march. ClangAs gives preference to -Wa,-march=.
  const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
  StringRef ArchName;
  if (WaArch) {
    if (ArchArg)
      D.Diag(clang::diag::warn_drv_unused_argument)
          << ArchArg->getAsString(Args);
    ArchName = StringRef(WaArch->getValue()).substr(7);
    checkARMArchName(D, WaArch, Args, ArchName, Features, Triple);
    // FIXME: Set Arch.
    D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
  } else if (ArchArg) {
    ArchName = ArchArg->getValue();
    checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple);
d733 5
a737 45
  // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
  const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
  StringRef CPUName;
  if (WaCPU) {
    if (CPUArg)
      D.Diag(clang::diag::warn_drv_unused_argument)
          << CPUArg->getAsString(Args);
    CPUName = StringRef(WaCPU->getValue()).substr(6);
    checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple);
  } else if (CPUArg) {
    CPUName = CPUArg->getValue();
    checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple);
  }

  // Add CPU features for generic CPUs
  if (CPUName == "native") {
    llvm::StringMap<bool> HostFeatures;
    if (llvm::sys::getHostCPUFeatures(HostFeatures))
      for (auto &F : HostFeatures)
        Features.push_back(
            Args.MakeArgString((F.second ? "+" : "-") + F.first()));
  }

  // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
  const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
  if (WaFPU) {
    if (FPUArg)
      D.Diag(clang::diag::warn_drv_unused_argument)
          << FPUArg->getAsString(Args);
    getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
                      Features);
  } else if (FPUArg) {
    getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
  }

  // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
  const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
  if (WaHDiv) {
    if (HDivArg)
      D.Diag(clang::diag::warn_drv_unused_argument)
          << HDivArg->getAsString(Args);
    getARMHWDivFeatures(D, WaHDiv, Args,
                        StringRef(WaHDiv->getValue()).substr(8), Features);
  } else if (HDivArg)
    getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
d741 1
a741 1
  if (ABI == arm::FloatABI::Soft) {
d747 3
a749 2
  // En/disable crc code generation.
  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
d755 1
d757 8
a764 3
  if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_1a) {
    Features.insert(Features.begin(), "+v8.1a");
  }
a765 62
  // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
  // neither options are specified, see if we are compiling for kernel/kext and
  // decide whether to pass "+long-calls" based on the OS and its version.
  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
                               options::OPT_mno_long_calls)) {
    if (A->getOption().matches(options::OPT_mlong_calls))
      Features.push_back("+long-calls");
  } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
             !Triple.isWatchOS()) {
      Features.push_back("+long-calls");
  }

  // Kernel code has more strict alignment requirements.
  if (KernelOrKext)
    Features.push_back("+strict-align");
  else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                                    options::OPT_munaligned_access)) {
    if (A->getOption().matches(options::OPT_munaligned_access)) {
      // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
      if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
        D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
    } else
      Features.push_back("+strict-align");
  } else {
    // Assume pre-ARMv6 doesn't support unaligned accesses.
    //
    // ARMv6 may or may not support unaligned accesses depending on the
    // SCTLR.U bit, which is architecture-specific. We assume ARMv6
    // Darwin and NetBSD targets support unaligned accesses, and others don't.
    //
    // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
    // which raises an alignment fault on unaligned accesses. Linux
    // defaults this bit to 0 and handles it as a system-wide (not
    // per-process) setting. It is therefore safe to assume that ARMv7+
    // Linux targets support unaligned accesses. The same goes for NaCl.
    //
    // The above behavior is consistent with GCC.
    int VersionNum = getARMSubArchVersionNumber(Triple);
    if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
      if (VersionNum < 6 ||
          Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
        Features.push_back("+strict-align");
    } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
      if (VersionNum < 7)
        Features.push_back("+strict-align");
    } else
      Features.push_back("+strict-align");
  }

  // llvm does not support reserving registers in general. There is support
  // for reserving r9 on ARM though (defined as a platform-specific register
  // in ARM EABI).
  if (Args.hasArg(options::OPT_ffixed_r9))
    Features.push_back("+reserve-r9");

  // The kext linker doesn't know how to deal with movw/movt.
  if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
    Features.push_back("+no-movt");
}

void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
                             ArgStringList &CmdArgs, bool KernelOrKext) const {
d767 1
d774 5
a778 1
    if (useAAPCSForMachO(Triple)) {
a779 2
    } else if (Triple.isWatchOS()) {
      ABIName = "aapcs16";
d788 1
a788 1
    switch (Triple.getEnvironment()) {
d810 2
a811 2
  arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
  if (ABI == arm::FloatABI::Soft) {
d813 1
d818 1
a818 1
  } else if (ABI == arm::FloatABI::SoftFP) {
d824 1
a824 1
    assert(ABI == arm::FloatABI::Hard && "Invalid float abi!");
d829 32
a860 1
  // Forward the -mglobal-merge option for explicit control over the pass.
a862 1
    CmdArgs.push_back("-backend-option");
d864 1
a864 3
      CmdArgs.push_back("-arm-global-merge=false");
    else
      CmdArgs.push_back("-arm-global-merge=true");
d868 2
a869 1
                    options::OPT_mno_implicit_float, true))
d871 8
a879 1
// ARM tools end.
d888 1
a888 1
    CPU = StringRef(A->getValue()).lower();
d891 1
a891 1
    CPU = Mcpu.split("+").first.lower();
d933 9
d949 1
a949 1
  } else if (Triple.isAndroid()) {
d955 2
a956 1
  // Forward the -mglobal-merge option for explicit control over the pass.
d959 5
d965 1
a965 4
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-aarch64-global-merge=false");
    else
      CmdArgs.push_back("-aarch64-global-merge=true");
d971 4
a974 2
void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
                            StringRef &CPUName, StringRef &ABIName) {
a985 4
  // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
  if (Triple.isAndroid())
    DefMips64CPU = "mips64r6";

d990 2
a991 1
  if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ))
d999 3
a1001 3
                  .Case("32", "o32")
                  .Case("64", "n64")
                  .Default(ABIName);
d1032 3
a1034 3
                  .Cases("o32", "eabi", DefMips32CPU)
                  .Cases("n32", "n64", DefMips64CPU)
                  .Default("");
a1039 10
std::string mips::getMipsABILibSuffix(const ArgList &Args,
                                      const llvm::Triple &Triple) {
  StringRef CPUName, ABIName;
  tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
  return llvm::StringSwitch<std::string>(ABIName)
      .Case("o32", "")
      .Case("n32", "32")
      .Case("n64", "64");
}

d1043 3
a1045 3
      .Case("o32", "32")
      .Case("n64", "64")
      .Default(ABI);
d1050 5
a1054 5
static mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args) {
  mips::FloatABI ABI = mips::FloatABI::Invalid;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
                          options::OPT_mfloat_abi_EQ)) {
d1056 1
a1056 1
      ABI = mips::FloatABI::Soft;
d1058 1
a1058 1
      ABI = mips::FloatABI::Hard;
d1060 2
a1061 5
      ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
                .Case("soft", mips::FloatABI::Soft)
                .Case("hard", mips::FloatABI::Hard)
                .Default(mips::FloatABI::Invalid);
      if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
d1063 1
a1063 1
        ABI = mips::FloatABI::Hard;
d1069 1
a1069 1
  if (ABI == mips::FloatABI::Invalid) {
d1073 1
a1073 1
    ABI = mips::FloatABI::Hard;
d1076 1
a1076 2
  assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
  return ABI;
d1099 11
d1113 2
a1114 2
  mips::FloatABI FloatABI = getMipsFloatABI(D, Args);
  if (FloatABI == mips::FloatABI::Soft) {
d1123 5
a1127 15
    if (Val == "2008") {
      if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
        Features.push_back("+nan2008");
      else {
        Features.push_back("-nan2008");
        D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
      }
    } else if (Val == "legacy") {
      if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
        Features.push_back("-nan2008");
      else {
        Features.push_back("+nan2008");
        D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
      }
    } else
d1156 1
a1156 1
  } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
d1176 3
a1178 2
  mips::FloatABI ABI = getMipsFloatABI(D, Args);
  if (ABI == mips::FloatABI::Soft) {
d1183 2
a1184 1
  } else {
d1186 1
a1186 1
    assert(ABI == mips::FloatABI::Hard && "Invalid float abi!");
d1236 45
a1280 45
        .Case("common", "generic")
        .Case("440", "440")
        .Case("440fp", "440")
        .Case("450", "450")
        .Case("601", "601")
        .Case("602", "602")
        .Case("603", "603")
        .Case("603e", "603e")
        .Case("603ev", "603ev")
        .Case("604", "604")
        .Case("604e", "604e")
        .Case("620", "620")
        .Case("630", "pwr3")
        .Case("G3", "g3")
        .Case("7400", "7400")
        .Case("G4", "g4")
        .Case("7450", "7450")
        .Case("G4+", "g4+")
        .Case("750", "750")
        .Case("970", "970")
        .Case("G5", "g5")
        .Case("a2", "a2")
        .Case("a2q", "a2q")
        .Case("e500mc", "e500mc")
        .Case("e5500", "e5500")
        .Case("power3", "pwr3")
        .Case("power4", "pwr4")
        .Case("power5", "pwr5")
        .Case("power5x", "pwr5x")
        .Case("power6", "pwr6")
        .Case("power6x", "pwr6x")
        .Case("power7", "pwr7")
        .Case("power8", "pwr8")
        .Case("pwr3", "pwr3")
        .Case("pwr4", "pwr4")
        .Case("pwr5", "pwr5")
        .Case("pwr5x", "pwr5x")
        .Case("pwr6", "pwr6")
        .Case("pwr6x", "pwr6x")
        .Case("pwr7", "pwr7")
        .Case("pwr8", "pwr8")
        .Case("powerpc", "ppc")
        .Case("powerpc64", "ppc64")
        .Case("powerpc64le", "ppc64le")
        .Default("");
d1286 1
a1286 2
static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                 const ArgList &Args,
d1288 5
a1292 1
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
d1294 3
a1296 10
  ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
  if (FloatABI == ppc::FloatABI::Soft &&
      !(Triple.getArch() == llvm::Triple::ppc64 ||
        Triple.getArch() == llvm::Triple::ppc64le))
    Features.push_back("+soft-float");
  else if (FloatABI == ppc::FloatABI::Soft &&
           (Triple.getArch() == llvm::Triple::ppc64 ||
            Triple.getArch() == llvm::Triple::ppc64le))
    D.Diag(diag::err_drv_invalid_mfloat_abi)
        << "soft float is not supported for ppc64";
d1298 3
a1300 4
  // Altivec is a bit weird, allow overriding of the Altivec feature here.
  AddTargetFeature(Args, Features, options::OPT_faltivec,
                   options::OPT_fno_altivec, "altivec");
}
d1302 6
a1307 20
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
  ppc::FloatABI ABI = ppc::FloatABI::Invalid;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
                          options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      ABI = ppc::FloatABI::Soft;
    else if (A->getOption().matches(options::OPT_mhard_float))
      ABI = ppc::FloatABI::Hard;
    else {
      ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
                .Case("soft", ppc::FloatABI::Soft)
                .Case("hard", ppc::FloatABI::Hard)
                .Default(ppc::FloatABI::Invalid);
      if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        ABI = ppc::FloatABI::Hard;
      }
    }
  }
d1309 1
a1309 3
  // If unspecified, choose the default based on the platform.
  if (ABI == ppc::FloatABI::Invalid) {
    ABI = ppc::FloatABI::Hard;
d1312 3
a1314 1
  return ABI;
d1321 5
a1325 15
  if (getToolChain().getTriple().isOSLinux())
    switch (getToolChain().getArch()) {
    case llvm::Triple::ppc64: {
      // When targeting a processor that supports QPX, or if QPX is
      // specifically enabled, default to using the ABI that supports QPX (so
      // long as it is not specifically disabled).
      bool HasQPX = false;
      if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
        HasQPX = A->getValue() == StringRef("a2q");
      HasQPX = Args.hasFlag(options::OPT_mqpx, options::OPT_mno_qpx, HasQPX);
      if (HasQPX) {
        ABIName = "elfv1-qpx";
        break;
      }

a1327 1
    }
a1332 22
    }

  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
    // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore
    // the option if given as we don't have backend support for any targets
    // that don't use the altivec abi.
    if (StringRef(A->getValue()) != "altivec")
      ABIName = A->getValue();

  ppc::FloatABI FloatABI =
      ppc::getPPCFloatABI(getToolChain().getDriver(), Args);

  if (FloatABI == ppc::FloatABI::Soft) {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == ppc::FloatABI::Hard && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
d1351 8
a1358 8
        .Cases("rv630", "rv635", "r600")
        .Cases("rv610", "rv620", "rs780", "rs880")
        .Case("rv740", "rv770")
        .Case("palm", "cedar")
        .Cases("sumo", "sumo2", "sumo")
        .Case("hemlock", "cypress")
        .Case("aruba", "cayman")
        .Default(GPUName);
d1363 3
a1365 6
void Clang::AddSparcTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();
  std::string Triple = getToolChain().ComputeEffectiveClangTriple(Args);

  bool SoftFloatABI = false;
d1368 36
a1403 12
    if (A->getOption().matches(options::OPT_msoft_float))
      SoftFloatABI = true;
  }

  // Only the hard-float ABI on Sparc is standardized, and it is the
  // default. GCC also supports a nonstandard soft-float ABI mode, and
  // perhaps LLVM should implement that, too. However, since llvm
  // currently does not support Sparc soft-float, at all, display an
  // error if it's requested.
  if (SoftFloatABI) {
    D.Diag(diag::err_drv_unsupported_opt_for_target) << "-msoft-float"
                                                     << Triple;
a1412 18
static void getSystemZTargetFeatures(const ArgList &Args,
                                     std::vector<const char *> &Features) {
  // -m(no-)htm overrides use of the transactional-execution facility.
  if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
    if (A->getOption().matches(options::OPT_mhtm))
      Features.push_back("+transactional-execution");
    else
      Features.push_back("-transactional-execution");
  }
  // -m(no-)vx overrides use of the vector facility.
  if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
    if (A->getOption().matches(options::OPT_mvx))
      Features.push_back("+vector");
    else
      Features.push_back("-vector");
  }
}

a1432 22
  if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
    // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
    StringRef Arch = A->getValue();
    const char *CPU;
    if (Triple.getArch() == llvm::Triple::x86) {
      CPU = llvm::StringSwitch<const char *>(Arch)
                .Case("IA32", "i386")
                .Case("SSE", "pentium3")
                .Case("SSE2", "pentium4")
                .Case("AVX", "sandybridge")
                .Case("AVX2", "haswell")
                .Default(nullptr);
    } else {
      CPU = llvm::StringSwitch<const char *>(Arch)
                .Case("AVX", "sandybridge")
                .Case("AVX2", "haswell")
                .Default(nullptr);
    }
    if (CPU)
      return CPU;
  }

a1447 4
  // Set up default CPU name for PS4 compilers.
  if (Triple.isPS4CPU())
    return "btver2";

d1449 1
a1449 1
  if (Triple.isAndroid())
d1471 2
a1472 22
/// Get the (LLVM) name of the WebAssembly cpu we are targeting.
static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
  // If we have -mcpu=, use that.
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPU = A->getValue();

#ifdef __wasm__
    // Handle "native" by examining the host. "native" isn't meaningful when
    // cross compiling, so only support this when the host is also WebAssembly.
    if (CPU == "native")
      return llvm::sys::getHostCPUName();
#endif

    return CPU;
  }

  return "generic";
}

static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
                              bool FromAs = false) {
  switch (T.getArch()) {
d1483 3
a1485 5
  case llvm::Triple::thumbeb: {
    StringRef MArch, MCPU;
    getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
    return arm::getARMTargetCPU(MCPU, MArch, T);
  }
a1495 6
  case llvm::Triple::nvptx:
  case llvm::Triple::nvptx64:
    if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
      return A->getValue();
    return "";

a1514 1
  case llvm::Triple::sparcel:
d1525 1
a1525 2
    return "hexagon" +
           toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
a1532 4

  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
    return getWebAssemblyTargetCPU(Args);
d1537 1
a1537 1
                          ArgStringList &CmdArgs, bool IsThinLTO) {
d1542 1
a1542 2
  std::string Plugin =
      ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
a1551 47

  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    StringRef OOpt;
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      OOpt = "3";
    else if (A->getOption().matches(options::OPT_O))
      OOpt = A->getValue();
    else if (A->getOption().matches(options::OPT_O0))
      OOpt = "0";
    if (!OOpt.empty())
      CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt));
  }

  if (IsThinLTO)
    CmdArgs.push_back("-plugin-opt=thinlto");
}

/// This is a helper function for validating the optional refinement step
/// parameter in reciprocal argument strings. Return false if there is an error
/// parsing the refinement step. Otherwise, return true and set the Position
/// of the refinement step in the input string.
static bool getRefinementStep(StringRef In, const Driver &D,
                              const Arg &A, size_t &Position) {
  const char RefinementStepToken = ':';
  Position = In.find(RefinementStepToken);
  if (Position != StringRef::npos) {
    StringRef Option = A.getOption().getName();
    StringRef RefStep = In.substr(Position + 1);
    // Allow exactly one numeric character for the additional refinement
    // step parameter. This is reasonable for all currently-supported
    // operations and architectures because we would expect that a larger value
    // of refinement steps would cause the estimate "optimization" to
    // under-perform the native operation. Also, if the estimate does not
    // converge quickly, it probably will not ever converge, so further
    // refinement steps will not produce a better answer.
    if (RefStep.size() != 1) {
      D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
      return false;
    }
    char RefStepChar = RefStep[0];
    if (RefStepChar < '0' || RefStepChar > '9') {
      D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
      return false;
    }
  }
  return true;
d1554 2
a1555 101
/// The -mrecip flag requires processing of many optional parameters.
static void ParseMRecip(const Driver &D, const ArgList &Args,
                        ArgStringList &OutStrings) {
  StringRef DisabledPrefixIn = "!";
  StringRef DisabledPrefixOut = "!";
  StringRef EnabledPrefixOut = "";
  StringRef Out = "-mrecip=";

  Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
  if (!A)
    return;

  unsigned NumOptions = A->getNumValues();
  if (NumOptions == 0) {
    // No option is the same as "all".
    OutStrings.push_back(Args.MakeArgString(Out + "all"));
    return;
  }

  // Pass through "all", "none", or "default" with an optional refinement step.
  if (NumOptions == 1) {
    StringRef Val = A->getValue(0);
    size_t RefStepLoc;
    if (!getRefinementStep(Val, D, *A, RefStepLoc))
      return;
    StringRef ValBase = Val.slice(0, RefStepLoc);
    if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
      OutStrings.push_back(Args.MakeArgString(Out + Val));
      return;
    }
  }

  // Each reciprocal type may be enabled or disabled individually.
  // Check each input value for validity, concatenate them all back together,
  // and pass through.

  llvm::StringMap<bool> OptionStrings;
  OptionStrings.insert(std::make_pair("divd", false));
  OptionStrings.insert(std::make_pair("divf", false));
  OptionStrings.insert(std::make_pair("vec-divd", false));
  OptionStrings.insert(std::make_pair("vec-divf", false));
  OptionStrings.insert(std::make_pair("sqrtd", false));
  OptionStrings.insert(std::make_pair("sqrtf", false));
  OptionStrings.insert(std::make_pair("vec-sqrtd", false));
  OptionStrings.insert(std::make_pair("vec-sqrtf", false));

  for (unsigned i = 0; i != NumOptions; ++i) {
    StringRef Val = A->getValue(i);

    bool IsDisabled = Val.startswith(DisabledPrefixIn);
    // Ignore the disablement token for string matching.
    if (IsDisabled)
      Val = Val.substr(1);

    size_t RefStep;
    if (!getRefinementStep(Val, D, *A, RefStep))
      return;

    StringRef ValBase = Val.slice(0, RefStep);
    llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
    if (OptionIter == OptionStrings.end()) {
      // Try again specifying float suffix.
      OptionIter = OptionStrings.find(ValBase.str() + 'f');
      if (OptionIter == OptionStrings.end()) {
        // The input name did not match any known option string.
        D.Diag(diag::err_drv_unknown_argument) << Val;
        return;
      }
      // The option was specified without a float or double suffix.
      // Make sure that the double entry was not already specified.
      // The float entry will be checked below.
      if (OptionStrings[ValBase.str() + 'd']) {
        D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
        return;
      }
    }

    if (OptionIter->second == true) {
      // Duplicate option specified.
      D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
      return;
    }

    // Mark the matched option as found. Do not allow duplicate specifiers.
    OptionIter->second = true;

    // If the precision was not specified, also mark the double entry as found.
    if (ValBase.back() != 'f' && ValBase.back() != 'd')
      OptionStrings[ValBase.str() + 'd'] = true;

    // Build the output string.
    StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
    Out = Args.MakeArgString(Out + Prefix + Val);
    if (i != NumOptions - 1)
      Out = Args.MakeArgString(Out + ",");
  }

  OutStrings.push_back(Args.MakeArgString(Out));
}

static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
a1557 11
  // If -march=native, autodetect the feature list.
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    if (StringRef(A->getValue()) == "native") {
      llvm::StringMap<bool> HostFeatures;
      if (llvm::sys::getHostCPUFeatures(HostFeatures))
        for (auto &F : HostFeatures)
          Features.push_back(
              Args.MakeArgString((F.second ? "+" : "-") + F.first()));
    }
  }

d1569 3
a1571 4
  const llvm::Triple::ArchType ArchType = Triple.getArch();
  // Add features to be compatible with gcc for Android.
  if (Triple.isAndroid()) {
    if (ArchType == llvm::Triple::x86_64) {
d1578 1
a1578 1
  // Set features according to the -arch flag on MSVC.
d1583 2
a1584 1
    if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
d1591 1
a1591 1
    if (ArchType == llvm::Triple::x86) {
d1605 16
a1620 1
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
d1625 3
a1627 1
  if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
d1636 4
a1639 3
  if (Arg *A = Args.getLastArg(
          options::OPT_msoft_float, options::OPT_mno_soft_float,
          options::OPT_mimplicit_float, options::OPT_mno_implicit_float)) {
d1659 22
d1683 1
d1687 5
a1691 5
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
    std::string N = llvm::utostr(G.getValue());
    std::string Opt = std::string("-hexagon-small-data-threshold=") + N;
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString(Opt));
d1697 2
a1698 14
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-enable-hexagon-ieee-rnd-near");
  }
  CmdArgs.push_back("-mllvm");
  CmdArgs.push_back("-machine-sink-split=0");
}

void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
                                     ArgStringList &CmdArgs) const {
  // Default to "hidden" visibility.
  if (!Args.hasArg(options::OPT_fvisibility_EQ,
                   options::OPT_fvisibility_ms_compat)) {
    CmdArgs.push_back("-fvisibility");
    CmdArgs.push_back("hidden");
d1700 2
d1710 2
a1711 2
  for (StringRef Feature : Split) {
    const char *result = llvm::StringSwitch<const char *>(Feature)
a1715 2
                             .Case("fp16", "+fullfp16")
                             .Case("profile", "+spe")
a1719 2
                             .Case("nofp16", "-fullfp16")
                             .Case("noprofile", "-spe")
d1723 1
a1723 1
    else if (Feature == "neon" || Feature == "noneon")
d1737 1
a1737 2
  if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" ||
      CPU == "cortex-a72" || CPU == "cortex-a35" || CPU == "exynos-m1") {
d1757 2
a1758 10
  std::string MarchLowerCase = March.lower();
  std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");

  if (Split.first == "armv8-a" || Split.first == "armv8a") {
    // ok, no additional features.
  } else if (Split.first == "armv8.1-a" || Split.first == "armv8.1a") {
    Features.push_back("+v8.1a");
  } else if (Split.first == "armv8.2-a" || Split.first == "armv8.2a" ) {
    Features.push_back("+v8.2a");
  } else {
a1759 1
  }
d1772 1
a1772 2
  std::string McpuLowerCase = Mcpu.lower();
  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
a1781 1
  std::string MtuneLowerCase = Mtune.lower();
d1783 3
a1785 3
  if (MtuneLowerCase == "native")
    MtuneLowerCase = llvm::sys::getHostCPUName();
  if (MtuneLowerCase == "cyclone") {
d1798 1
a1798 2
  std::string McpuLowerCase = Mcpu.lower();
  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
d1838 2
a1839 1
  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
a1844 39

  if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                               options::OPT_munaligned_access))
    if (A->getOption().matches(options::OPT_mno_unaligned_access))
      Features.push_back("+strict-align");

  if (Args.hasArg(options::OPT_ffixed_x18))
    Features.push_back("+reserve-x18");
}

static void getHexagonTargetFeatures(const ArgList &Args,
                                     std::vector<const char *> &Features) {
  bool HasHVX = false, HasHVXD = false;

  // FIXME: This should be able to use handleTargetFeaturesGroup except it is
  // doing dependent option handling here rather than in initFeatureMap or a
  // similar handler.
  for (auto &A : Args) {
    auto &Opt = A->getOption();
    if (Opt.matches(options::OPT_mhexagon_hvx))
      HasHVX = true;
    else if (Opt.matches(options::OPT_mno_hexagon_hvx))
      HasHVXD = HasHVX = false;
    else if (Opt.matches(options::OPT_mhexagon_hvx_double))
      HasHVXD = HasHVX = true;
    else if (Opt.matches(options::OPT_mno_hexagon_hvx_double))
      HasHVXD = false;
    else
      continue;
    A->claim();
  }

  Features.push_back(HasHVX  ? "+hvx" : "-hvx");
  Features.push_back(HasHVXD ? "+hvx-double" : "-hvx-double");
}

static void getWebAssemblyTargetFeatures(const ArgList &Args,
                                         std::vector<const char *> &Features) {
  handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
d1847 1
a1847 1
static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
a1849 1
  const Driver &D = TC.getDriver();
d1865 1
a1865 1
    getARMTargetFeatures(TC, Triple, Args, Features, ForAS);
d1871 1
a1871 1
    getPPCTargetFeatures(D, Triple, Args, Features);
d1873 3
a1875 2
  case llvm::Triple::systemz:
    getSystemZTargetFeatures(Args, Features);
a1884 7
  case llvm::Triple::hexagon:
    getHexagonTargetFeatures(Args, Features);
    break;
  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
    getWebAssemblyTargetFeatures(Args, Features);
    break;
d1921 1
a1921 1
  return (!Triple.isMacOSXVersionLT(10, 5) &&
d1926 16
a1941 4
/// Adds exception related arguments to the driver command arguments. There's a
/// master flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example
/// disable C++ exceptions but enable Objective-C exceptions.
d1943 2
a1944 1
                             const ToolChain &TC, bool KernelOrKext,
a1946 3
  const Driver &D = TC.getDriver();
  const llvm::Triple &Triple = TC.getTriple();

d1959 2
a1960 3
  // See if the user explicitly enabled exceptions.
  bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
                         false);
d1966 2
a1967 1
                   options::OPT_fno_objc_exceptions, true)) {
d1974 5
a1978 9
    // Disable C++ EH by default on XCore, PS4, and MSVC.
    // FIXME: Remove MSVC from this list once things work.
    bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore &&
                                !Triple.isPS4CPU() &&
                                !Triple.isWindowsMSVCEnvironment();
    Arg *ExceptionArg = Args.getLastArg(
        options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
        options::OPT_fexceptions, options::OPT_fno_exceptions);
    if (ExceptionArg)
d1980 2
a1981 2
          ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) ||
          ExceptionArg->getOption().matches(options::OPT_fexceptions);
a1983 15
      if (Triple.isPS4CPU()) {
        ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
        assert(ExceptionArg &&
               "On the PS4 exceptions should only be enabled if passing "
               "an argument");
        if (RTTIMode == ToolChain::RM_DisabledExplicitly) {
          const Arg *RTTIArg = TC.getRTTIArg();
          assert(RTTIArg && "RTTI disabled explicitly but no RTTIArg!");
          D.Diag(diag::err_drv_argument_not_allowed_with)
              << RTTIArg->getAsString(Args) << ExceptionArg->getAsString(Args);
        } else if (RTTIMode == ToolChain::RM_EnabledImplicitly)
          D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
      } else
        assert(TC.getRTTIMode() != ToolChain::RM_DisabledImplicitly);

d1994 2
a1995 1
static bool ShouldDisableAutolink(const ArgList &Args, const ToolChain &TC) {
d2008 3
a2010 3
  bool UseDwarfDirectory =
      Args.hasFlag(options::OPT_fdwarf_directory_asm,
                   options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs());
d2045 1
a2045 62
                      RelaxDefault);
}

// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
// to the corresponding DebugInfoKind.
static CodeGenOptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
  assert(A.getOption().matches(options::OPT_gN_Group) &&
         "Not a -g option that specifies a debug-info level");
  if (A.getOption().matches(options::OPT_g0) ||
      A.getOption().matches(options::OPT_ggdb0))
    return CodeGenOptions::NoDebugInfo;
  if (A.getOption().matches(options::OPT_gline_tables_only) ||
      A.getOption().matches(options::OPT_ggdb1))
    return CodeGenOptions::DebugLineTablesOnly;
  return CodeGenOptions::LimitedDebugInfo;
}

// Extract the integer N from a string spelled "-dwarf-N", returning 0
// on mismatch. The StringRef input (rather than an Arg) allows
// for use by the "-Xassembler" option parser.
static unsigned DwarfVersionNum(StringRef ArgValue) {
  return llvm::StringSwitch<unsigned>(ArgValue)
      .Case("-gdwarf-2", 2)
      .Case("-gdwarf-3", 3)
      .Case("-gdwarf-4", 4)
      .Case("-gdwarf-5", 5)
      .Default(0);
}

static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
                                    CodeGenOptions::DebugInfoKind DebugInfoKind,
                                    unsigned DwarfVersion,
                                    llvm::DebuggerKind DebuggerTuning) {
  switch (DebugInfoKind) {
  case CodeGenOptions::DebugLineTablesOnly:
    CmdArgs.push_back("-debug-info-kind=line-tables-only");
    break;
  case CodeGenOptions::LimitedDebugInfo:
    CmdArgs.push_back("-debug-info-kind=limited");
    break;
  case CodeGenOptions::FullDebugInfo:
    CmdArgs.push_back("-debug-info-kind=standalone");
    break;
  default:
    break;
  }
  if (DwarfVersion > 0)
    CmdArgs.push_back(
        Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
  switch (DebuggerTuning) {
  case llvm::DebuggerKind::GDB:
    CmdArgs.push_back("-debugger-tuning=gdb");
    break;
  case llvm::DebuggerKind::LLDB:
    CmdArgs.push_back("-debugger-tuning=lldb");
    break;
  case llvm::DebuggerKind::SCE:
    CmdArgs.push_back("-debugger-tuning=sce");
    break;
  default:
    break;
  }
d2052 2
a2053 2
  if (UseRelaxAll(C, Args))
    CmdArgs.push_back("-mrelax-all");
d2055 15
a2069 22
  // Only default to -mincremental-linker-compatible if we think we are
  // targeting the MSVC linker.
  bool DefaultIncrementalLinkerCompatible =
      C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
  if (Args.hasFlag(options::OPT_mincremental_linker_compatible,
                   options::OPT_mno_incremental_linker_compatible,
                   DefaultIncrementalLinkerCompatible))
    CmdArgs.push_back("-mincremental-linker-compatible");

  // When passing -I arguments to the assembler we sometimes need to
  // unconditionally take the next argument.  For example, when parsing
  // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
  // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
  // arg after parsing the '-I' arg.
  bool TakeNextArg = false;

  // When using an integrated assembler, translate -Wa, and -Xassembler
  // options.
  bool CompressDebugSections = false;
  for (const Arg *A :
       Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
    A->claim();
d2071 5
a2075 32
    for (StringRef Value : A->getValues()) {
      if (TakeNextArg) {
        CmdArgs.push_back(Value.data());
        TakeNextArg = false;
        continue;
      }

      switch (C.getDefaultToolChain().getArch()) {
      default:
        break;
      case llvm::Triple::mips:
      case llvm::Triple::mipsel:
      case llvm::Triple::mips64:
      case llvm::Triple::mips64el:
        if (Value == "--trap") {
          CmdArgs.push_back("-target-feature");
          CmdArgs.push_back("+use-tcc-in-div");
          continue;
        }
        if (Value == "--break") {
          CmdArgs.push_back("-target-feature");
          CmdArgs.push_back("-use-tcc-in-div");
          continue;
        }
        if (Value.startswith("-msoft-float")) {
          CmdArgs.push_back("-target-feature");
          CmdArgs.push_back("+soft-float");
          continue;
        }
        if (Value.startswith("-mhard-float")) {
          CmdArgs.push_back("-target-feature");
          CmdArgs.push_back("-soft-float");
a2077 2
        break;
      }
d2079 21
a2099 24
      if (Value == "-force_cpusubtype_ALL") {
        // Do nothing, this is the default and we don't support anything else.
      } else if (Value == "-L") {
        CmdArgs.push_back("-msave-temp-labels");
      } else if (Value == "--fatal-warnings") {
        CmdArgs.push_back("-massembler-fatal-warnings");
      } else if (Value == "--noexecstack") {
        CmdArgs.push_back("-mnoexecstack");
      } else if (Value == "-compress-debug-sections" ||
                 Value == "--compress-debug-sections") {
        CompressDebugSections = true;
      } else if (Value == "-nocompress-debug-sections" ||
                 Value == "--nocompress-debug-sections") {
        CompressDebugSections = false;
      } else if (Value.startswith("-I")) {
        CmdArgs.push_back(Value.data());
        // We need to consume the next argument if the current arg is a plain
        // -I. The next arg will be the include directory.
        if (Value == "-I")
          TakeNextArg = true;
      } else if (Value.startswith("-gdwarf-")) {
        // "-gdwarf-N" options are not cc1as options.
        unsigned DwarfVersion = DwarfVersionNum(Value);
        if (DwarfVersion == 0) { // Send it onward, and let cc1as complain.
d2102 2
a2103 3
          RenderDebugEnablingArgs(
              Args, CmdArgs, CodeGenOptions::LimitedDebugInfo, DwarfVersion,
              llvm::DebuggerKind::Default);
a2104 6
      } else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
                 Value.startswith("-mhwdiv") || Value.startswith("-march")) {
        // Do nothing, we'll validate it later.
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
d2107 44
a2150 7
  }
  if (CompressDebugSections) {
    if (llvm::zlib::isAvailable())
      CmdArgs.push_back("-compress-debug-sections");
    else
      D.Diag(diag::warn_debug_compression_unavailable);
  }
d2158 1
a2158 2
  CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
}
d2160 5
a2164 44
namespace {
enum OpenMPRuntimeKind {
  /// An unknown OpenMP runtime. We can't generate effective OpenMP code
  /// without knowing what runtime to target.
  OMPRT_Unknown,

  /// The LLVM OpenMP runtime. When completed and integrated, this will become
  /// the default for Clang.
  OMPRT_OMP,

  /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
  /// this runtime but can swallow the pragmas, and find and link against the
  /// runtime library itself.
  OMPRT_GOMP,

  /// The legacy name for the LLVM OpenMP runtime from when it was the Intel
  /// OpenMP runtime. We support this mode for users with existing dependencies
  /// on this runtime library name.
  OMPRT_IOMP5
};
}

/// Compute the desired OpenMP runtime from the flag provided.
static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC,
                                          const ArgList &Args) {
  StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);

  const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
  if (A)
    RuntimeName = A->getValue();

  auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
                .Case("libomp", OMPRT_OMP)
                .Case("libgomp", OMPRT_GOMP)
                .Case("libiomp5", OMPRT_IOMP5)
                .Default(OMPRT_Unknown);

  if (RT == OMPRT_Unknown) {
    if (A)
      TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << A->getValue();
    else
      // FIXME: We could use a nicer diagnostic here.
      TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
a2165 2

  return RT;
d2168 8
a2175 4
static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
                              const ArgList &Args) {
  if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
                    options::OPT_fno_openmp, false))
d2178 1
a2178 14
  switch (getOpenMPRuntime(TC, Args)) {
  case OMPRT_OMP:
    CmdArgs.push_back("-lomp");
    break;
  case OMPRT_GOMP:
    CmdArgs.push_back("-lgomp");
    break;
  case OMPRT_IOMP5:
    CmdArgs.push_back("-liomp5");
    break;
  case OMPRT_Unknown:
    // Already diagnosed.
    break;
  }
d2184 4
d2190 6
a2195 3
  if (!IsShared) CmdArgs.push_back("-whole-archive");
  CmdArgs.push_back(TC.getCompilerRTArgString(Args, Sanitizer, IsShared));
  if (!IsShared) CmdArgs.push_back("-no-whole-archive");
d2203 1
a2203 1
  SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
d2236 2
a2237 1
  if (Args.hasArg(options::OPT_shared) || TC.getTriple().isAndroid()) {
d2254 1
a2254 1
  if (SanArgs.needsMsanRt()) {
d2256 1
a2256 4
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("msan_cxx");
  }
  if (SanArgs.needsTsanRt()) {
d2258 1
a2258 3
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("tsan_cxx");
  }
d2260 5
a2264 1
    StaticRuntimes.push_back("ubsan_standalone");
d2266 1
a2266 1
      StaticRuntimes.push_back("ubsan_standalone_cxx");
a2267 6
  if (SanArgs.needsSafeStackRt())
    StaticRuntimes.push_back("safestack");
  if (SanArgs.needsCfiRt())
    StaticRuntimes.push_back("cfi");
  if (SanArgs.needsCfiDiagRt())
    StaticRuntimes.push_back("cfi_diag");
a2293 8
static bool areOptimizationsEnabled(const ArgList &Args) {
  // Find the last -O arg and see if it is non-zero.
  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    return !A->getOption().matches(options::OPT_O0);
  // Defaults to -O0.
  return false;
}

d2297 13
a2310 4
  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
    // XCore never wants frame pointers, regardless of OS.
    // WebAssembly never wants frame pointers.
d2313 1
a2313 32
    break;
  }

  if (Triple.isOSLinux()) {
    switch (Triple.getArch()) {
    // Don't use a frame pointer on linux if optimizing for certain targets.
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::systemz:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      return !areOptimizationsEnabled(Args);
    default:
      return true;
    }
  }

  if (Triple.isOSWindows()) {
    switch (Triple.getArch()) {
    case llvm::Triple::x86:
      return !areOptimizationsEnabled(Args);
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      // Windows on ARM builds with FPO disabled to aid fast stack walking
      return true;
    default:
      // All other supported Windows ISAs use xdata unwind information, so frame
      // pointers are not generally useful.
      return false;
    }
a2314 2

  return true;
a2321 2
  if (Args.hasArg(options::OPT_pg))
    return true;
a2330 5
  if (Args.hasArg(options::OPT_pg))
    return true;

  if (Triple.isPS4CPU())
    return false;
d2344 2
a2345 1
static const char *SplitDebugName(const ArgList &Args, const InputInfo &Input) {
d2355 1
a2355 1
    SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
d2362 4
a2365 3
static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
                           const JobAction &JA, const ArgList &Args,
                           const InputInfo &Output, const char *OutFile) {
d2377 2
a2378 2
  const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
  InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
d2381 1
a2381 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
d2384 1
a2384 1
  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II));
d2434 5
a2438 1
static VersionTuple getMSCompatibilityVersion(unsigned Version) {
d2440 1
a2440 1
    return VersionTuple(Version);
d2443 2
a2444 1
    return VersionTuple(Version / 100, Version % 100);
d2447 1
a2447 1
  for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
d2449 3
a2451 1
  return VersionTuple(Version / 100, Version % 100, Build);
a2459 1
  Args.ClaimAllArgs(options::OPT_flto_EQ);
a2463 356
static void appendUserToPath(SmallVectorImpl<char> &Result) {
#ifdef LLVM_ON_UNIX
  const char *Username = getenv("LOGNAME");
#else
  const char *Username = getenv("USERNAME");
#endif
  if (Username) {
    // Validate that LoginName can be used in a path, and get its length.
    size_t Len = 0;
    for (const char *P = Username; *P; ++P, ++Len) {
      if (!isAlphanumeric(*P) && *P != '_') {
        Username = nullptr;
        break;
      }
    }

    if (Username && Len > 0) {
      Result.append(Username, Username + Len);
      return;
    }
  }

// Fallback to user id.
#ifdef LLVM_ON_UNIX
  std::string UID = llvm::utostr(getuid());
#else
  // FIXME: Windows seems to have an 'SID' that might work.
  std::string UID = "9999";
#endif
  Result.append(UID.begin(), UID.end());
}

VersionTuple visualstudio::getMSVCVersion(const Driver *D,
                                          const llvm::Triple &Triple,
                                          const llvm::opt::ArgList &Args,
                                          bool IsWindowsMSVC) {
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   IsWindowsMSVC) ||
      Args.hasArg(options::OPT_fmsc_version) ||
      Args.hasArg(options::OPT_fms_compatibility_version)) {
    const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
    const Arg *MSCompatibilityVersion =
        Args.getLastArg(options::OPT_fms_compatibility_version);

    if (MSCVersion && MSCompatibilityVersion) {
      if (D)
        D->Diag(diag::err_drv_argument_not_allowed_with)
            << MSCVersion->getAsString(Args)
            << MSCompatibilityVersion->getAsString(Args);
      return VersionTuple();
    }

    if (MSCompatibilityVersion) {
      VersionTuple MSVT;
      if (MSVT.tryParse(MSCompatibilityVersion->getValue()) && D)
        D->Diag(diag::err_drv_invalid_value)
            << MSCompatibilityVersion->getAsString(Args)
            << MSCompatibilityVersion->getValue();
      return MSVT;
    }

    if (MSCVersion) {
      unsigned Version = 0;
      if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version) && D)
        D->Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args)
                                             << MSCVersion->getValue();
      return getMSCompatibilityVersion(Version);
    }

    unsigned Major, Minor, Micro;
    Triple.getEnvironmentVersion(Major, Minor, Micro);
    if (Major || Minor || Micro)
      return VersionTuple(Major, Minor, Micro);

    return VersionTuple(18);
  }
  return VersionTuple();
}

static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
                                   const InputInfo &Output, const ArgList &Args,
                                   ArgStringList &CmdArgs) {
  auto *ProfileGenerateArg = Args.getLastArg(
      options::OPT_fprofile_instr_generate,
      options::OPT_fprofile_instr_generate_EQ, options::OPT_fprofile_generate,
      options::OPT_fprofile_generate_EQ,
      options::OPT_fno_profile_instr_generate);
  if (ProfileGenerateArg &&
      ProfileGenerateArg->getOption().matches(
          options::OPT_fno_profile_instr_generate))
    ProfileGenerateArg = nullptr;

  auto *ProfileUseArg = Args.getLastArg(
      options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
      options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
      options::OPT_fno_profile_instr_use);
  if (ProfileUseArg &&
      ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
    ProfileUseArg = nullptr;

  if (ProfileGenerateArg && ProfileUseArg)
    D.Diag(diag::err_drv_argument_not_allowed_with)
        << ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling();

  if (ProfileGenerateArg) {
    if (ProfileGenerateArg->getOption().matches(
            options::OPT_fprofile_instr_generate_EQ))
      ProfileGenerateArg->render(Args, CmdArgs);
    else if (ProfileGenerateArg->getOption().matches(
                 options::OPT_fprofile_generate_EQ)) {
      SmallString<128> Path(ProfileGenerateArg->getValue());
      llvm::sys::path::append(Path, "default.profraw");
      CmdArgs.push_back(
          Args.MakeArgString(Twine("-fprofile-instr-generate=") + Path));
    } else
      Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
  }

  if (ProfileUseArg) {
    if (ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ))
      ProfileUseArg->render(Args, CmdArgs);
    else if ((ProfileUseArg->getOption().matches(
                  options::OPT_fprofile_use_EQ) ||
              ProfileUseArg->getOption().matches(
                  options::OPT_fprofile_instr_use))) {
      SmallString<128> Path(
          ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
      if (Path.empty() || llvm::sys::fs::is_directory(Path))
        llvm::sys::path::append(Path, "default.profdata");
      CmdArgs.push_back(
          Args.MakeArgString(Twine("-fprofile-instr-use=") + Path));
    }
  }

  if (Args.hasArg(options::OPT_ftest_coverage) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-notes");
  if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                   false) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-data");

  if (Args.hasFlag(options::OPT_fcoverage_mapping,
                   options::OPT_fno_coverage_mapping, false) &&
      !ProfileGenerateArg)
    D.Diag(diag::err_drv_argument_only_allowed_with)
        << "-fcoverage-mapping"
        << "-fprofile-instr-generate";

  if (Args.hasFlag(options::OPT_fcoverage_mapping,
                   options::OPT_fno_coverage_mapping, false))
    CmdArgs.push_back("-fcoverage-mapping");

  if (C.getArgs().hasArg(options::OPT_c) ||
      C.getArgs().hasArg(options::OPT_S)) {
    if (Output.isFilename()) {
      CmdArgs.push_back("-coverage-file");
      SmallString<128> CoverageFilename;
      if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
        CoverageFilename = FinalOutput->getValue();
      } else {
        CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
      }
      if (llvm::sys::path::is_relative(CoverageFilename)) {
        SmallString<128> Pwd;
        if (!llvm::sys::fs::current_path(Pwd)) {
          llvm::sys::path::append(Pwd, CoverageFilename);
          CoverageFilename.swap(Pwd);
        }
      }
      CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
    }
  }
}

static void addPS4ProfileRTArgs(const ToolChain &TC, const ArgList &Args,
                                ArgStringList &CmdArgs) {
  if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                    false) ||
       Args.hasFlag(options::OPT_fprofile_generate,
                    options::OPT_fno_profile_instr_generate, false) ||
       Args.hasFlag(options::OPT_fprofile_generate_EQ,
                    options::OPT_fno_profile_instr_generate, false) ||
       Args.hasFlag(options::OPT_fprofile_instr_generate,
                    options::OPT_fno_profile_instr_generate, false) ||
       Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
                    options::OPT_fno_profile_instr_generate, false) ||
       Args.hasArg(options::OPT_fcreate_profile) ||
       Args.hasArg(options::OPT_coverage)))
    CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a");
}

/// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments.  Then,
/// smooshes them together with platform defaults, to decide whether
/// this compile should be using PIC mode or not. Returns a tuple of
/// (RelocationModel, PICLevel, IsPIE).
static std::tuple<llvm::Reloc::Model, unsigned, bool>
ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
             const ArgList &Args) {
  // FIXME: why does this code...and so much everywhere else, use both
  // ToolChain.getTriple() and Triple?
  bool PIE = ToolChain.isPIEDefault();
  bool PIC = PIE || ToolChain.isPICDefault();
  // The Darwin/MachO default to use PIC does not apply when using -static.
  if (ToolChain.getTriple().isOSBinFormatMachO() &&
      Args.hasArg(options::OPT_static))
    PIE = PIC = false;
  bool IsPICLevelTwo = PIC;

  bool KernelOrKext =
      Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);

  // Android-specific defaults for PIC/PIE
  if (ToolChain.getTriple().isAndroid()) {
    switch (ToolChain.getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
    case llvm::Triple::aarch64:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      PIC = true; // "-fpic"
      break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      PIC = true; // "-fPIC"
      IsPICLevelTwo = true;
      break;

    default:
      break;
    }
  }

  // OpenBSD-specific defaults for PIE
  if (ToolChain.getTriple().getOS() == llvm::Triple::OpenBSD) {
    switch (ToolChain.getArch()) {
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
    case llvm::Triple::sparcel:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      IsPICLevelTwo = false; // "-fpie"
      break;

    case llvm::Triple::ppc:
    case llvm::Triple::sparc:
    case llvm::Triple::sparcv9:
      IsPICLevelTwo = true; // "-fPIE"
      break;

    default:
      break;
    }
  }

  // The last argument relating to either PIC or PIE wins, and no
  // other argument is used. If the last argument is any flavor of the
  // '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
  // option implicitly enables PIC at the same level.
  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                    options::OPT_fpic, options::OPT_fno_pic,
                                    options::OPT_fPIE, options::OPT_fno_PIE,
                                    options::OPT_fpie, options::OPT_fno_pie);
  // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
  // is forced, then neither PIC nor PIE flags will have no effect.
  if (!ToolChain.isPICDefaultForced()) {
    if (LastPICArg) {
      Option O = LastPICArg->getOption();
      if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
          O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
        PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
        PIC =
            PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
        IsPICLevelTwo =
            O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
      } else {
        PIE = PIC = false;
        if (Triple.isPS4CPU()) {
          Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
          StringRef Model = ModelArg ? ModelArg->getValue() : "";
          if (Model != "kernel") {
            PIC = true;
            ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic)
                << LastPICArg->getSpelling();
          }
        }
      }
    }
  }

  // Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
  // PIC level would've been set to level 1, force it back to level 2 PIC
  // instead.
  if (PIC && (ToolChain.getTriple().isOSDarwin() || Triple.isPS4CPU()))
    IsPICLevelTwo |= ToolChain.isPICDefault();

  // This kernel flags are a trump-card: they will disable PIC/PIE
  // generation, independent of the argument order.
  if (KernelOrKext && ((!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
                       !Triple.isWatchOS()))
    PIC = PIE = false;

  if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
    // This is a very special mode. It trumps the other modes, almost no one
    // uses it, and it isn't even valid on any OS but Darwin.
    if (!ToolChain.getTriple().isOSDarwin())
      ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
          << A->getSpelling() << ToolChain.getTriple().str();

    // FIXME: Warn when this flag trumps some other PIC or PIE flag.

    // Only a forced PIC mode can cause the actual compile to have PIC defines
    // etc., no flags are sufficient. This behavior was selected to closely
    // match that of llvm-gcc and Apple GCC before that.
    PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced();

    return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2 : 0, false);
  }

  if (PIC)
    return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2 : 1, PIE);

  return std::make_tuple(llvm::Reloc::Static, 0, false);
}

static const char *RelocationModelName(llvm::Reloc::Model Model) {
  switch (Model) {
  case llvm::Reloc::Default:
    return nullptr;
  case llvm::Reloc::Static:
    return "static";
  case llvm::Reloc::PIC_:
    return "pic";
  case llvm::Reloc::DynamicNoPIC:
    return "dynamic-no-pic";
  }
  llvm_unreachable("Unknown Reloc::Model kind");
}

static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
                             ArgStringList &CmdArgs) {
  llvm::Reloc::Model RelocationModel;
  unsigned PICLevel;
  bool IsPIE;
  std::tie(RelocationModel, PICLevel, IsPIE) =
      ParsePICArgs(ToolChain, ToolChain.getTriple(), Args);

  if (RelocationModel != llvm::Reloc::Static)
    CmdArgs.push_back("-KPIC");
}

d2465 6
a2470 7
                         const InputInfo &Output, const InputInfoList &Inputs,
                         const ArgList &Args, const char *LinkingOutput) const {
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  const llvm::Triple Triple(TripleStr);

  bool KernelOrKext =
      Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
a2477 1
  bool IsPS4CPU = getToolChain().getTriple().isPS4CPU();
d2479 1
a2479 8
  // Check number of inputs for sanity. We need at least one input.
  assert(Inputs.size() >= 1 && "Must have at least one input.");
  const InputInfo &Input = Inputs[0];
  // CUDA compilation may have multiple inputs (source file + results of
  // device-side compilations). All other jobs are expected to have exactly one
  // input.
  bool IsCuda = types::isCuda(Input.getType());
  assert((IsCuda || Inputs.size() == 1) && "Unable to handle multiple inputs.");
d2488 1
d2491 4
a2494 22
  const ToolChain *AuxToolChain = nullptr;
  if (IsCuda) {
    // FIXME: We need a (better) way to pass information about
    // particular compilation pass we're constructing here. For now we
    // can check which toolchain we're using and pick the other one to
    // extract the triple.
    if (&getToolChain() == C.getCudaDeviceToolChain())
      AuxToolChain = C.getCudaHostToolChain();
    else if (&getToolChain() == C.getCudaHostToolChain())
      AuxToolChain = C.getCudaDeviceToolChain();
    else
      llvm_unreachable("Can't figure out CUDA compilation mode.");
    assert(AuxToolChain != nullptr && "No aux toolchain.");
    CmdArgs.push_back("-aux-triple");
    CmdArgs.push_back(Args.MakeArgString(AuxToolChain->getTriple().str()));
    CmdArgs.push_back("-fcuda-target-overloads");
    CmdArgs.push_back("-fcuda-disable-target-call-checks");
  }

  if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm ||
                               Triple.getArch() == llvm::Triple::thumb)) {
    unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
d2496 1
a2496 1
    Triple.getArchName().substr(Offset).getAsInteger(10, Version);
d2498 1
a2498 1
      D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName()
d2509 1
a2509 1

d2530 1
a2530 1
    (void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
d2546 1
d2568 2
a2569 1
      assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
a2570 17

    // Preserve use-list order by default when emitting bitcode, so that
    // loading the bitcode up in 'opt' or 'llc' and running passes gives the
    // same result as running passes here.  For LTO, we don't need to preserve
    // the use-list order, since serialization to bitcode is part of the flow.
    if (JA.getType() == types::TY_LLVM_BC)
      CmdArgs.push_back("-emit-llvm-uselists");

    if (D.isUsingLTO())
      Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
  }

  if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) {
    if (!types::isLLVMIR(Input.getType()))
      D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
                                                       << "-x ir";
    Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
d2579 1
a2579 1
// Disable the verification pass in -asserts builds.
d2587 1
a2587 1
  CmdArgs.push_back(getBaseInputName(Args, Input));
a2609 6
      // Disable some unix checkers for PS4.
      if (IsPS4CPU) {
        CmdArgs.push_back("-analyzer-disable-checker=unix.API");
        CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
      }

d2612 1
a2612 1

d2614 2
a2615 2

      if (types::isCXX(Input.getType()))
d2618 1
a2618 12
      if (!IsPS4CPU) {
        CmdArgs.push_back(
            "-analyzer-checker=security.insecureAPI.UncheckedReturn");
        CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
        CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
        CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
        CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
        CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
      }

      // Default nullability checks.
      CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull");
d2620 6
a2625 1
          "-analyzer-checker=nullability.NullReturnedFromNonnull");
d2647 45
a2691 5
  llvm::Reloc::Model RelocationModel;
  unsigned PICLevel;
  bool IsPIE;
  std::tie(RelocationModel, PICLevel, IsPIE) =
      ParsePICArgs(getToolChain(), Triple, Args);
d2693 3
a2695 4
  const char *RMName = RelocationModelName(RelocationModel);
  if (RMName) {
    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back(RMName);
d2697 28
a2724 6
  if (PICLevel > 0) {
    CmdArgs.push_back("-pic-level");
    CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
    if (IsPIE) {
      CmdArgs.push_back("-pie-level");
      CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
d2728 48
a2775 3
  if (Arg *A = Args.getLastArg(options::OPT_meabi)) {
    CmdArgs.push_back("-meabi");
    CmdArgs.push_back(A->getValue());
a2783 2
  Args.AddLastArg(CmdArgs, options::OPT_fveclib);

d2792 5
a2796 2
    for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file,
                                      options::OPT_frewrite_map_file_EQ)) {
d2798 2
a2799 2
      CmdArgs.push_back(A->getValue());
      A->claim();
d2819 1
a2819 1
          << A->getSpelling() << getToolChain().getTriple().str();
d2840 2
a2841 2
  OptSpecifier StrictAliasingAliasOption =
      OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing;
a2853 4
  if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
                   options::OPT_fno_strict_vtable_pointers,
                   false))
    CmdArgs.push_back("-fstrict-vtable-pointers");
d2864 3
a2866 3
  OptSpecifier FastMathAliasOption =
      OFastEnabled ? options::OPT_Ofast : options::OPT_ffast_math;

d2872 6
a2877 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_ffinite_math_only,
          options::OPT_fno_finite_math_only, options::OPT_fhonor_infinities,
          options::OPT_fno_honor_infinities))
d2882 6
a2887 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_ffinite_math_only,
          options::OPT_fno_finite_math_only, options::OPT_fhonor_nans,
          options::OPT_fno_honor_nans))
d2895 4
a2898 4
  if (Arg *A =
          Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                          options::OPT_fno_fast_math, options::OPT_fmath_errno,
                          options::OPT_fno_math_errno)) {
d2917 6
a2922 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
          options::OPT_fno_unsafe_math_optimizations,
          options::OPT_fassociative_math, options::OPT_fno_associative_math))
d2928 6
a2933 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
          options::OPT_fno_unsafe_math_optimizations,
          options::OPT_freciprocal_math, options::OPT_fno_reciprocal_math))
d2939 6
a2944 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
          options::OPT_fno_unsafe_math_optimizations,
          options::OPT_fsigned_zeros, options::OPT_fno_signed_zeros))
d2950 6
a2955 5
  if (Arg *A = Args.getLastArg(
          options::OPT_ffast_math, FastMathAliasOption,
          options::OPT_fno_fast_math, options::OPT_funsafe_math_optimizations,
          options::OPT_fno_unsafe_math_optimizations,
          options::OPT_ftrapping_math, options::OPT_fno_trapping_math))
a2963 5
  if (!SignedZeros)
    CmdArgs.push_back("-fno-signed-zeros");

  if (ReciprocalMath)
    CmdArgs.push_back("-freciprocal-math");
d2965 1
a2965 1
  // Validate and pass through -fp-contract option.
d2975 1
a2975 1
            << A->getOption().getName() << Val;
a2983 2
  ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);

d2991 2
a2992 2
    if (!A->getOption().matches(options::OPT_fno_fast_math))
      CmdArgs.push_back("-ffast-math");
d3030 1
a3030 2
  if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
                   false)) {
d3055 1
a3055 1
  (void)Args.hasArg(options::OPT_mtune_EQ);
d3063 3
a3065 1
  std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
d3077 1
a3077 1
  getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, false);
d3080 1
a3080 1
  switch (getToolChain().getArch()) {
d3088 1
a3088 2
    // Use the effective triple, which takes into account the deployment target.
    AddARMTargetArgs(Triple, Args, CmdArgs, KernelOrKext);
a3109 1
  case llvm::Triple::sparcel:
a3121 5

  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
    AddWebAssemblyTargetArgs(Args, CmdArgs);
    break;
a3123 16
  // The 'g' groups options involve a somewhat intricate sequence of decisions
  // about what to pass from the driver to the frontend, but by the time they
  // reach cc1 they've been factored into three well-defined orthogonal choices:
  //  * what level of debug info to generate
  //  * what dwarf version to write
  //  * what debugger tuning to use
  // This avoids having to monkey around further in cc1 other than to disable
  // codeview if not running in a Windows environment. Perhaps even that
  // decision should be made in the driver as well though.
  unsigned DwarfVersion = 0;
  llvm::DebuggerKind DebuggerTuning = getToolChain().getDefaultDebuggerTuning();
  // These two are potentially updated by AddClangCLArgs.
  enum CodeGenOptions::DebugInfoKind DebugInfoKind =
      CodeGenOptions::NoDebugInfo;
  bool EmitCodeView = false;

d3126 1
a3126 1
    AddClangCLArgs(Args, CmdArgs, &DebugInfoKind, &EmitCodeView);
d3139 1
a3139 1
  types::ID InputType = Input.getType();
d3142 2
a3143 1
    if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() &&
d3148 1
a3148 1
            << Unsupported->getOption().getName();
d3156 2
a3157 2
    CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename
                                               : "-");
d3164 2
a3165 2
    CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename
                                                 : "-");
d3168 2
a3170 1
  Arg *SplitDwarfArg = Args.getLastArg(options::OPT_gsplit_dwarf);
d3172 28
a3199 38
    // If the last option explicitly specified a debug-info level, use it.
    if (A->getOption().matches(options::OPT_gN_Group)) {
      DebugInfoKind = DebugLevelToInfoKind(*A);
      // If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
      // But -gsplit-dwarf is not a g_group option, hence we have to check the
      // order explicitly. (If -gsplit-dwarf wins, we fix DebugInfoKind later.)
      if (SplitDwarfArg && DebugInfoKind < CodeGenOptions::LimitedDebugInfo &&
          A->getIndex() > SplitDwarfArg->getIndex())
        SplitDwarfArg = nullptr;
    } else
      // For any other 'g' option, use Limited.
      DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
  }

  // If a debugger tuning argument appeared, remember it.
  if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
                               options::OPT_ggdbN_Group)) {
    if (A->getOption().matches(options::OPT_glldb))
      DebuggerTuning = llvm::DebuggerKind::LLDB;
    else if (A->getOption().matches(options::OPT_gsce))
      DebuggerTuning = llvm::DebuggerKind::SCE;
    else
      DebuggerTuning = llvm::DebuggerKind::GDB;
  }

  // If a -gdwarf argument appeared, remember it.
  if (Arg *A = Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
                               options::OPT_gdwarf_4, options::OPT_gdwarf_5))
    DwarfVersion = DwarfVersionNum(A->getSpelling());

  // Forward -gcodeview.
  // 'EmitCodeView might have been set by CL-compatibility argument parsing.
  if (Args.hasArg(options::OPT_gcodeview) || EmitCodeView) {
    // DwarfVersion remains at 0 if no explicit choice was made.
    CmdArgs.push_back("-gcodeview");
  } else if (DwarfVersion == 0 &&
             DebugInfoKind != CodeGenOptions::NoDebugInfo) {
    DwarfVersion = getToolChain().GetDefaultDwarfVersion();
a3203 2

  // PS4 defaults to no column info
d3205 1
a3205 1
                   /*Default=*/ !IsPS4CPU))
a3208 6
  if (Args.hasArg(options::OPT_gmodules)) {
    DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
    CmdArgs.push_back("-dwarf-ext-refs");
    CmdArgs.push_back("-fmodule-format=obj");
  }

d3212 3
a3214 2
  if (getToolChain().getTriple().isOSLinux() && SplitDwarfArg) {
    DebugInfoKind = CodeGenOptions::LimitedDebugInfo;
a3218 13
  // After we've dealt with all combinations of things that could
  // make DebugInfoKind be other than None or DebugLineTablesOnly,
  // figure out if we need to "upgrade" it to standalone debug info.
  // We parse these two '-f' options whether or not they will be used,
  // to claim them even if you wrote "-fstandalone-debug -gline-tables-only"
  bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
                                    options::OPT_fno_standalone_debug,
                                    getToolChain().GetDefaultStandaloneDebug());
  if (DebugInfoKind == CodeGenOptions::LimitedDebugInfo && NeedFullDebug)
    DebugInfoKind = CodeGenOptions::FullDebugInfo;
  RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
                          DebuggerTuning);

d3227 1
a3227 2
  // Always enabled on the PS4.
  if (Args.hasArg(options::OPT_gdwarf_aranges) || IsPS4CPU) {
a3237 6
  // CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
  // default.
  bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI ||
                             Triple.getArch() == llvm::Triple::wasm32 ||
                             Triple.getArch() == llvm::Triple::wasm64;

d3239 1
a3239 1
                   options::OPT_fno_function_sections, UseSeparateSections)) {
d3243 2
a3244 2
  if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
                   UseSeparateSections)) {
d3248 22
a3269 3
  if (!Args.hasFlag(options::OPT_funique_section_names,
                    options::OPT_fno_unique_section_names, true))
    CmdArgs.push_back("-fno-unique-section-names");
d3271 4
a3274 1
  Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
d3276 2
a3277 1
  addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
d3279 20
a3298 3
  // Add runtime flag for PS4 when PGO or Coverage are enabled.
  if (getToolChain().getTriple().isPS4CPU())
    addPS4ProfileRTArgs(getToolChain(), Args, CmdArgs);
d3306 1
a3306 1
      CmdArgs.push_back("-nostdsysteminc");
d3350 2
a3351 2
      D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
                                                      << "-ccc-arcmt-migrate";
a3374 1
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
d3391 1
a3391 2
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs,
                            AuxToolChain);
d3410 4
a3413 4
  for (const Arg *A :
       Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
    D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
    A->claim();
a3429 1
  bool ImplyVCPPCXXVer = false;
d3453 2
a3454 2
      Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=",
                                /*Joined=*/true);
d3456 1
a3456 1
      ImplyVCPPCXXVer = true;
a3507 9
  for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
    StringRef Map = A->getValue();
    if (Map.find('=') == StringRef::npos)
      D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
    else
      CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
    A->claim();
  }

d3543 1
d3621 2
d3624 3
a3626 8
  // Emulated TLS is enabled by default on Android, and can be enabled manually
  // with -femulated-tls.
  bool EmulatedTLSDefault = Triple.isAndroid();
  if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
                   EmulatedTLSDefault))
    CmdArgs.push_back("-femulated-tls");
  // AltiVec-like language extensions aren't relevant for assembling.
  if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm) {
a3627 2
    Args.AddLastArg(CmdArgs, options::OPT_fzvector);
  }
a3630 26
  // Forward flags for OpenMP
  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
                   options::OPT_fno_openmp, false))
    switch (getOpenMPRuntime(getToolChain(), Args)) {
    case OMPRT_OMP:
    case OMPRT_IOMP5:
      // Clang can generate useful OpenMP code for these two runtime libraries.
      CmdArgs.push_back("-fopenmp");

      // If no option regarding the use of TLS in OpenMP codegeneration is
      // given, decide a default based on the target. Otherwise rely on the
      // options and pass the right information to the frontend.
      if (!Args.hasFlag(options::OPT_fopenmp_use_tls,
                        options::OPT_fnoopenmp_use_tls, /*Default=*/true))
        CmdArgs.push_back("-fnoopenmp-use-tls");
      break;
    default:
      // By default, if Clang doesn't know how to generate useful OpenMP code
      // for a specific runtime library, we just don't pass the '-fopenmp' flag
      // down to the actual compilation.
      // FIXME: It would be better to have a mode which *only* omits IR
      // generation based on the OpenMP support so that we get consistent
      // semantic analysis, etc.
      break;
    }

d3632 1
a3632 1
  Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType);
d3635 6
a3640 13
  if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) {
    const llvm::Triple::ArchType Arch = getToolChain().getArch();
    if (!(Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 ||
          Arch == llvm::Triple::ppc64le))
      D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
                                                       << "ppc/ppc64/ppc64le";
  }

  // -fzvector is incompatible with -faltivec.
  if (Arg *A = Args.getLastArg(options::OPT_fzvector))
    if (Args.hasArg(options::OPT_faltivec))
      D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
                                                      << "-faltivec";
d3650 1
a3650 2
  if (Args.getLastArg(options::OPT_fapple_kext) ||
      (Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
d3668 2
a3669 1
  if (Arg *A = Args.getLastArg(options::OPT_fwrapv, options::OPT_fno_wrapv)) {
d3689 1
d3692 4
a3695 9
  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
    Args.ClaimAllArgs(options::OPT_fno_stack_protector);
    Args.ClaimAllArgs(options::OPT_fstack_protector_all);
    Args.ClaimAllArgs(options::OPT_fstack_protector_strong);
    Args.ClaimAllArgs(options::OPT_fstack_protector);
  } else if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                                      options::OPT_fstack_protector_all,
                                      options::OPT_fstack_protector_strong,
                                      options::OPT_fstack_protector)) {
d3697 2
a3698 3
      StackProtectorLevel = std::max<unsigned>(
          LangOptions::SSPOn,
          getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
d3705 1
a3705 1
        getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
d3713 3
a3715 2
  for (const Arg *A : Args.filtered(options::OPT__param)) {
    StringRef Str(A->getValue());
d3722 1
a3722 1
      A->claim();
d3728 6
a3733 1
                   false))
d3735 1
d3742 2
a3743 16
  if (Args.hasArg(options::OPT_mstack_probe_size)) {
    StringRef Size = Args.getLastArgValue(options::OPT_mstack_probe_size);

    if (!Size.empty())
      CmdArgs.push_back(Args.MakeArgString("-mstack-probe-size=" + Size));
    else
      CmdArgs.push_back("-mstack-probe-size=0");
  }

  switch (getToolChain().getArch()) {
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
a3744 5
    break;

  default:
    break;
  }
d3755 2
a3756 3
  } else if (Triple.isOSWindows() &&
             (Triple.getArch() == llvm::Triple::arm ||
              Triple.getArch() == llvm::Triple::thumb)) {
d3762 11
d3783 9
a3791 5
  // -fbuiltin is default unless -mkernel is used.
  bool UseBuiltins =
      Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
                   !Args.hasArg(options::OPT_mkernel));
  if (!UseBuiltins)
a3793 20
  // -ffreestanding implies -fno-builtin.
  if (Args.hasArg(options::OPT_ffreestanding))
    UseBuiltins = false;

  // Process the -fno-builtin-* options.
  for (const auto &Arg : Args) {
    const Option &O = Arg->getOption();
    if (!O.matches(options::OPT_fno_builtin_))
      continue;

    Arg->claim();
    // If -fno-builtin is specified, then there's no need to pass the option to
    // the frontend.
    if (!UseBuiltins)
      continue;

    StringRef FuncName = Arg->getValue();
    CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
  }

d3801 3
a3803 3
      (Args.hasArg(options::OPT_fgnu_runtime) &&
       Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
       !Args.hasArg(options::OPT_fno_blocks))) {
d3806 1
a3806 1
    if (!Args.hasArg(options::OPT_fgnu_runtime) &&
d3811 1
a3811 1
  // -fmodules enables the use of precompiled modules (off by default).
d3813 1
a3813 1
  // C++/Objective-C++ programs.
d3816 3
a3818 2
    bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
                                     options::OPT_fno_cxx_modules, true);
d3825 5
a3829 5
  // -fmodule-maps enables implicit reading of module map files. By default,
  // this is enabled if we are using precompiled modules.
  if (Args.hasFlag(options::OPT_fimplicit_module_maps,
                   options::OPT_fno_implicit_module_maps, HaveModules)) {
    CmdArgs.push_back("-fimplicit-module-maps");
d3835 2
a3836 1
                   options::OPT_fno_modules_decluse, false)) {
d3843 2
a3844 1
                   options::OPT_fno_modules_strict_decluse, false)) {
a3847 6
  // -fno-implicit-modules turns off implicitly compiling modules on demand.
  if (!Args.hasFlag(options::OPT_fimplicit_modules,
                    options::OPT_fno_implicit_modules)) {
    CmdArgs.push_back("-fno-implicit-modules");
  }

d3857 1
a3857 4
  if (HaveModules)
    Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
  else
    Args.ClaimAllArgs(options::OPT_fmodule_file);
d3861 1
a3861 1
  SmallString<128> Path;
d3863 1
a3863 1
    Path = A->getValue();
d3868 4
a3871 4
      Path = Output.getFilename();
      llvm::sys::path::replace_extension(Path, ".cache");
      llvm::sys::path::append(Path, "modules");
    } else if (Path.empty()) {
d3873 4
a3876 4
      llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Path);
      llvm::sys::path::append(Path, "org.llvm.clang.");
      appendUserToPath(Path);
      llvm::sys::path::append(Path, "ModuleCache");
d3879 2
a3880 2
    Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
    CmdArgs.push_back(Args.MakeArgString(Path));
d3914 4
a3917 3
    CmdArgs.push_back(Args.MakeArgString(
        "-fbuild-session-timestamp=" +
        Twine((uint64_t)Status.getLastModificationTime().toEpochTime())));
d3933 2
a3934 1
                   options::OPT_faccess_control, false))
d3939 2
a3940 1
                   options::OPT_felide_constructors, false))
d3943 4
a3946 1
  ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
d3948 10
a3957 4
  if (KernelOrKext || (types::isCXX(InputType) &&
                       (RTTIMode == ToolChain::RM_DisabledExplicitly ||
                        RTTIMode == ToolChain::RM_DisabledImplicitly)))
    CmdArgs.push_back("-fno-rtti");
d3960 4
a3963 2
  if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums,
                   getToolChain().getArch() == llvm::Triple::hexagon))
d3967 2
a3968 8
  if (Arg *A = Args.getLastArg(
          options::OPT_fsigned_char, options::OPT_fno_signed_char,
          options::OPT_funsigned_char, options::OPT_fno_unsigned_char)) {
    if (A->getOption().matches(options::OPT_funsigned_char) ||
        A->getOption().matches(options::OPT_fno_signed_char)) {
      CmdArgs.push_back("-fno-signed-char");
    }
  } else if (!isSignedCharDefault(getToolChain().getTriple())) {
d3970 5
a3974 1
  }
d3977 5
a3981 9
  if (!Args.hasFlag(
          options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
          !IsWindowsCygnus && !IsWindowsGNU &&
              getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
              getToolChain().getArch() != llvm::Triple::hexagon &&
              getToolChain().getArch() != llvm::Triple::xcore &&
              ((getToolChain().getTriple().getVendor() !=
                llvm::Triple::MipsTechnologies) ||
               getToolChain().getTriple().hasEnvironment())) ||
a3989 5
  // -fno-use-line-directives is default.
  if (Args.hasFlag(options::OPT_fuse_line_directives,
                   options::OPT_fno_use_line_directives, false))
    CmdArgs.push_back("-fuse-line-directives");

d3991 1
a3991 1
  if (Args.hasFlag(options::OPT_fms_compatibility,
d3993 3
a3995 3
                   (IsWindowsMSVC &&
                    Args.hasFlag(options::OPT_fms_extensions,
                                 options::OPT_fno_ms_extensions, true))))
d3998 18
a4015 6
  // -fms-compatibility-version=18.00 is default.
  VersionTuple MSVT = visualstudio::getMSVCVersion(
      &D, getToolChain().getTriple(), Args, IsWindowsMSVC);
  if (!MSVT.empty())
    CmdArgs.push_back(
        Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
d4017 2
a4018 4
  bool IsMSVC2015Compatible = MSVT.getMajor() >= 19;
  if (ImplyVCPPCXXVer) {
    if (IsMSVC2015Compatible)
      CmdArgs.push_back("-std=c++14");
d4020 1
a4020 1
      CmdArgs.push_back("-std=c++11");
a4027 14
  // -fno-declspec is default, except for PS4.
  if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
                   getToolChain().getTriple().isPS4()))
    CmdArgs.push_back("-fdeclspec");
  else if (Args.hasArg(options::OPT_fno_declspec))
    CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.

  // -fthreadsafe-static is default, except for MSVC compatibility versions less
  // than 19.
  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
                    options::OPT_fno_threadsafe_statics,
                    !IsWindowsMSVC || IsMSVC2015Compatible))
    CmdArgs.push_back("-fno-threadsafe-statics");

d4040 2
a4041 1
  if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline,
d4061 1
a4061 1
                          getToolChain().getArch()))) {
d4072 1
a4072 1
  if (getToolChain().getArch() == llvm::Triple::x86 &&
d4078 1
a4078 1

d4083 1
a4083 1

a4107 1

d4122 2
a4123 1
      D.Diag(diag::err_drv_objc_gc_arr) << GCArg->getAsString(Args);
d4128 2
a4129 1
      D.Diag(diag::warn_drv_objc_gc_unsupported) << GCArg->getAsString(Args);
a4132 21
  // Pass down -fobjc-weak or -fno-objc-weak if present.
  if (types::isObjC(InputType)) {
    auto WeakArg = Args.getLastArg(options::OPT_fobjc_weak,
                                   options::OPT_fno_objc_weak);
    if (!WeakArg) {
      // nothing to do
    } else if (GCArg) {
      if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
        D.Diag(diag::err_objc_weak_with_gc);
    } else if (!objcRuntime.allowsWeak()) {
      if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
        D.Diag(diag::err_objc_weak_unsupported);
    } else {
      WeakArg->render(Args, CmdArgs);
    }
  }

  if (Args.hasFlag(options::OPT_fapplication_extension,
                   options::OPT_fno_application_extension, false))
    CmdArgs.push_back("-fapplication-extension");

d4135 2
a4136 2
    addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, objcRuntime,
                     CmdArgs);
d4138 1
a4138 1
  if (getToolChain().UseSjLjExceptions(Args))
a4145 6
  // -fsized-deallocation is off by default, as it is an ABI-breaking change for
  // most platforms.
  if (Args.hasFlag(options::OPT_fsized_deallocation,
                   options::OPT_fno_sized_deallocation, false))
    CmdArgs.push_back("-fsized-deallocation");

d4162 2
a4163 1
                   options::OPT_fno_pascal_strings, false))
d4192 8
a4199 5
  // -fcommon is the default unless compiling kernel code or the target says so
  bool NoCommonDefault =
      KernelOrKext || isNoCommonDefault(getToolChain().getTriple());
  if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
                    !NoCommonDefault))
d4207 1
a4207 1
        << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
d4210 2
a4211 1
  if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope))
d4213 1
a4213 1
        << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
d4216 5
a4220 5
  if (Arg *inputCharset = Args.getLastArg(options::OPT_finput_charset_EQ)) {
    StringRef value = inputCharset->getValue();
    if (value != "UTF-8")
      D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args)
                                          << value;
d4224 5
a4228 5
  if (Arg *execCharset = Args.getLastArg(options::OPT_fexec_charset_EQ)) {
    StringRef value = execCharset->getValue();
    if (value != "UTF-8")
      D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args)
                                          << value;
d4247 1
a4247 1
          Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
d4252 2
a4253 1
  if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
d4259 2
a4260 2
          options::OPT_fdiagnostics_show_note_include_stack,
          options::OPT_fno_diagnostics_show_note_include_stack)) {
d4262 1
a4262 1
            options::OPT_fdiagnostics_show_note_include_stack))
d4300 1
a4300 1
            << ("-fdiagnostics-color=" + value).str();
d4314 2
a4315 1
  if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
d4323 1
a4328 5
  // -fgnu-inline-asm is default.
  if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
                    options::OPT_fno_gnu_inline_asm, true))
    CmdArgs.push_back("-fno-gnu-inline-asm");

d4333 2
a4334 2
  OptSpecifier VectorizeAliasOption =
      EnableVec ? options::OPT_O_Group : options::OPT_fvectorize;
d4341 2
a4342 2
  OptSpecifier SLPVectAliasOption =
      EnableSLPVec ? options::OPT_O_Group : options::OPT_fslp_vectorize;
d4377 1
a4377 1
  // le32-specific flags:
d4384 3
a4386 3
// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
//
// FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
d4418 1
a4418 1

a4432 7
  // Turn -fplugin=name.so into -load name.so
  for (const Arg *A : Args.filtered(options::OPT_fplugin_EQ)) {
    CmdArgs.push_back("-load");
    CmdArgs.push_back(A->getValue());
    A->claim();
  }

d4436 4
a4439 2
  for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
    A->claim();
d4443 1
a4443 1
    if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
d4445 1
d4447 1
a4447 1
      A->render(Args, CmdArgs);
d4451 5
a4455 4
  // CompileJobAction, use -disable-llvm-passes to get pristine IR generated
  // by the frontend.
  if (C.getDriver().isSaveTempsEnabled() && isa<CompileJobAction>(JA))
    CmdArgs.push_back("-disable-llvm-passes");
d4466 2
a4467 1
  addDashXForInput(Args, Input, CmdArgs);
d4469 5
a4473 4
  if (Input.isFilename())
    CmdArgs.push_back(Input.getFilename());
  else
    Input.getInputArg().renderAsInput(Args, CmdArgs);
d4488 1
a4488 1
    for (const char *OriginalArg : OriginalArgs) {
d4490 1
a4490 1
      EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
d4495 1
a4495 1
    CmdArgs.push_back(Args.MakeArgString(Flags));
d4500 4
a4503 3
  bool SplitDwarf = SplitDwarfArg && getToolChain().getTriple().isOSLinux() &&
                    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
                     isa<BackendJobAction>(JA));
d4507 1
a4507 1
    SplitDwarfOut = SplitDebugName(Args, Input);
a4510 8
  // Host-side cuda compilation receives device-side outputs as Inputs[1...].
  // Include them with -fcuda-include-gpubinary.
  if (IsCuda && Inputs.size() > 1)
    for (auto I = std::next(Inputs.begin()), E = Inputs.end(); I != E; ++I) {
      CmdArgs.push_back("-fcuda-include-gpubinary");
      CmdArgs.push_back(I->getFilename());
    }

d4517 2
a4518 2
    C.addCommand(llvm::make_unique<FallbackCommand>(
        JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand)));
d4520 1
a4520 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d4523 1
d4532 2
a4533 2
      D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
                                                      << A->getAsString(Args);
d4558 3
a4560 3
  Arg *runtimeArg =
      args.getLastArg(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
                      options::OPT_fobjc_runtime_EQ);
d4570 1
a4570 1
          << value;
d4593 2
a4594 1
      getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << value;
d4597 4
a4600 4
    bool nonFragileABIIsDefault =
        (rewriteKind == RK_NonFragile ||
         (rewriteKind == RK_None &&
          getToolChain().IsObjCNonFragileABIDefault()));
d4604 1
a4604 1
// Determine the non-fragile ABI version to use.
d4611 2
a4612 2
      if (Arg *abiArg =
              args.getLastArg(options::OPT_fobjc_nonfragile_abi_version_EQ)) {
d4620 1
a4620 1
              << value;
d4649 1
a4649 1
    // -fnext-runtime
d4655 1
a4655 1
      // Otherwise, build for a generic macosx port.
d4660 1
a4660 1
    // -fgnu-runtime
d4663 1
a4663 1
    // Legacy behaviour is to target the gnustep runtime if we are in
d4666 1
a4666 1
      runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1, 6));
d4671 2
a4672 2
  cmdArgs.push_back(
      args.MakeArgString("-fobjc-runtime=" + runtime.getAsString()));
a4681 1
namespace {
a4687 1
} // end anonymous namespace
d4699 1
a4699 3

  std::vector<std::string> EHArgs =
      Args.getAllArgValues(options::OPT__SLASH_EH);
d4703 4
a4706 11
      case 'a':
        EH.Asynch = maybeConsumeDash(EHVal, I);
        continue;
      case 'c':
        EH.NoExceptC = maybeConsumeDash(EHVal, I);
        continue;
      case 's':
        EH.Synch = maybeConsumeDash(EHVal, I);
        continue;
      default:
        break;
a4711 1

d4715 1
a4715 3
void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs,
                           enum CodeGenOptions::DebugInfoKind *DebugInfoKind,
                           bool *EmitCodeView) const {
d4726 9
a4734 4
  StringRef FlagForCRT;
  switch (RTOptionID) {
  case options::OPT__SLASH_MD:
    if (Args.hasArg(options::OPT__SLASH_LDd))
d4736 11
a4746 12
    CmdArgs.push_back("-D_MT");
    CmdArgs.push_back("-D_DLL");
    FlagForCRT = "--dependent-lib=msvcrt";
    break;
  case options::OPT__SLASH_MDd:
    CmdArgs.push_back("-D_DEBUG");
    CmdArgs.push_back("-D_MT");
    CmdArgs.push_back("-D_DLL");
    FlagForCRT = "--dependent-lib=msvcrtd";
    break;
  case options::OPT__SLASH_MT:
    if (Args.hasArg(options::OPT__SLASH_LDd))
d4748 5
a4752 10
    CmdArgs.push_back("-D_MT");
    FlagForCRT = "--dependent-lib=libcmt";
    break;
  case options::OPT__SLASH_MTd:
    CmdArgs.push_back("-D_DEBUG");
    CmdArgs.push_back("-D_MT");
    FlagForCRT = "--dependent-lib=libcmtd";
    break;
  default:
    llvm_unreachable("Unexpected option ID.");
d4755 4
a4758 10
  if (Args.hasArg(options::OPT__SLASH_Zl)) {
    CmdArgs.push_back("-D_VC_NODEFAULTLIB");
  } else {
    CmdArgs.push_back(FlagForCRT.data());

    // This provides POSIX compatibility (maps 'open' to '_open'), which most
    // users want.  The /Za flag to cl.exe turns this off, but it's not
    // implemented in clang.
    CmdArgs.push_back("--dependent-lib=oldnames");
  }
a4770 10
  // Emit CodeView if -Z7 is present.
  *EmitCodeView = Args.hasArg(options::OPT__SLASH_Z7);
  bool EmitDwarf = Args.hasArg(options::OPT_gdwarf);
  // If we are emitting CV but not DWARF, don't build information that LLVM
  // can't yet process.
  if (*EmitCodeView && !EmitDwarf)
    *DebugInfoKind = CodeGenOptions::DebugLineTablesOnly;
  if (*EmitCodeView)
    CmdArgs.push_back("-gcodeview");

d4775 1
a4776 1
    CmdArgs.push_back("-fexceptions");
a4784 13
  unsigned VolatileOptionID;
  if (getToolChain().getArch() == llvm::Triple::x86_64 ||
      getToolChain().getArch() == llvm::Triple::x86)
    VolatileOptionID = options::OPT__SLASH_volatile_ms;
  else
    VolatileOptionID = options::OPT__SLASH_volatile_iso;

  if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group))
    VolatileOptionID = A->getOption().getID();

  if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
    CmdArgs.push_back("-fms-volatile");

d4823 1
a4823 1
visualstudio::Compiler *Clang::getCLFallback() const {
d4825 1
a4825 1
    CLFallback.reset(new visualstudio::Compiler(getToolChain()));
a4828 11
void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
                                ArgStringList &CmdArgs) const {
  StringRef CPUName;
  StringRef ABIName;
  const llvm::Triple &Triple = getToolChain().getTriple();
  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName.data());
}

d4830 2
a4831 1
                           const InputInfo &Output, const InputInfoList &Inputs,
a4838 4
  std::string TripleStr =
      getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
  const llvm::Triple Triple(TripleStr);

d4853 2
d4865 1
a4865 1
  CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
d4868 2
a4869 1
  std::string CPU = getCPUName(Args, Triple, /*FromAs*/ true);
d4876 2
a4877 1
  getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, true);
d4880 1
a4880 4
  (void)Args.hasArg(options::OPT_force__cpusubtype__ALL);

  // Pass along any -I options so we get proper .include search paths.
  Args.AddAllArgs(CmdArgs, options::OPT_I_Group);
a4892 2
    bool WantDebug = false;
    unsigned DwarfVersion = 0;
d4894 10
a4903 12
    if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
      WantDebug = !A->getOption().matches(options::OPT_g0) &&
        !A->getOption().matches(options::OPT_ggdb0);
      if (WantDebug)
        DwarfVersion = DwarfVersionNum(A->getSpelling());
    }
    if (DwarfVersion == 0)
      DwarfVersion = getToolChain().GetDefaultDwarfVersion();
    RenderDebugEnablingArgs(Args, CmdArgs,
                            (WantDebug ? CodeGenOptions::LimitedDebugInfo
                                       : CodeGenOptions::NoDebugInfo),
                            DwarfVersion, llvm::DebuggerKind::Default);
a4911 17

    // And pass along -I options
    Args.AddAllArgs(CmdArgs, options::OPT_I);
  }

  // Handle -fPIC et al -- the relocation-model affects the assembler
  // for some targets.
  llvm::Reloc::Model RelocationModel;
  unsigned PICLevel;
  bool IsPIE;
  std::tie(RelocationModel, PICLevel, IsPIE) =
      ParsePICArgs(getToolChain(), Triple, Args);

  const char *RMName = RelocationModelName(RelocationModel);
  if (RMName) {
    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back(RMName);
d4924 1
a4924 1
    for (const char *OriginalArg : OriginalArgs) {
d4926 1
a4926 1
      EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
d4931 1
a4931 1
    CmdArgs.push_back(Args.MakeArgString(Flags));
a4935 13
  // Add target specific flags.
  switch (getToolChain().getArch()) {
  default:
    break;

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    AddMIPSTargetArgs(Args, CmdArgs);
    break;
  }

d4941 4
a4944 1
  Args.ClaimAllArgs(options::OPT_W_Group);
d4959 1
a4959 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d4967 1
a4967 1
                   SplitDebugName(Args, Input));
d4974 2
a4975 1
                               const InputInfoList &Inputs, const ArgList &Args,
a4981 6
      // It is unfortunate that we have to claim here, as this means
      // we will basically never report anything interesting for
      // platforms using a generic gcc, even if we are just using gcc
      // to get to the assembler.
      A->claim();

d4992 5
d5007 1
a5007 1
        Args.MakeArgString(getToolChain().getDefaultUniversalArchName()));
d5015 2
a5016 5
  switch (getToolChain().getArch()) {
  default:
    break;
  case llvm::Triple::x86:
  case llvm::Triple::ppc:
d5018 2
a5019 4
    break;
  case llvm::Triple::x86_64:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
a5020 5
    break;
  case llvm::Triple::sparcel:
    CmdArgs.push_back("-EL");
    break;
  }
d5030 2
a5031 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d5043 2
a5044 1
    if (types::isLLVMIR(II.getType()))
d5046 1
a5046 1
          << getToolChain().getTripleString();
d5048 2
a5049 1
      D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString();
d5052 1
a5052 1
          << getToolChain().getTripleString();
d5084 3
a5086 2
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d5089 2
a5090 2
void gcc::Preprocessor::RenderExtraToolArgs(const JobAction &JA,
                                            ArgStringList &CmdArgs) const {
d5094 2
a5095 2
void gcc::Compiler::RenderExtraToolArgs(const JobAction &JA,
                                        ArgStringList &CmdArgs) const {
a5097 1
  switch (JA.getType()) {
d5099 2
a5100 4
  case types::TY_LLVM_IR:
  case types::TY_LTO_IR:
  case types::TY_LLVM_BC:
  case types::TY_LTO_BC:
d5102 5
a5106 7
    break;
  // We assume we've got an "integrated" assembler in that gcc will produce an
  // object file itself.
  case types::TY_Object:
    CmdArgs.push_back("-c");
    break;
  case types::TY_PP_Asm:
a5107 6
    break;
  case types::TY_Nothing:
    CmdArgs.push_back("-fsyntax-only");
    break;
  default:
    D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());
d5111 2
a5112 2
void gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
                                      ArgStringList &CmdArgs) const {
d5117 3
a5119 2
void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
                                             ArgStringList &CmdArgs) const {
d5121 5
a5125 6

void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
d5128 1
a5128 2
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
  const Driver &D = HTC.getDriver();
d5131 3
a5133 2
  std::string MArchString = "-march=hexagon";
  CmdArgs.push_back(Args.MakeArgString(MArchString));
a5136 6
  std::string AsName = "hexagon-llvm-mc";
  std::string MCpuString = "-mcpu=hexagon" +
        toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
  CmdArgs.push_back("-filetype=obj");
  CmdArgs.push_back(Args.MakeArgString(MCpuString));

d5145 4
a5148 4
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
    std::string N = llvm::utostr(G.getValue());
    CmdArgs.push_back(Args.MakeArgString(std::string("-gpsize=") + N));
  }
d5150 2
a5151 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d5163 2
a5164 1
    if (types::isLLVMIR(II.getType()))
d5166 1
a5166 1
          << HTC.getTripleString();
d5169 1
a5169 1
          << HTC.getTripleString();
d5172 1
a5172 1
          << HTC.getTripleString();
d5177 1
a5177 2
      // Don't render as input, we need gcc to do the translations.
      // FIXME: What is this?
d5181 3
a5183 2
  auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str()));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d5186 3
a5188 2
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
                                          ArgStringList &CmdArgs) const {
d5191 9
a5199 6
static void
constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
                         const toolchains::HexagonToolChain &HTC,
                         const InputInfo &Output, const InputInfoList &Inputs,
                         const ArgList &Args, ArgStringList &CmdArgs,
                         const char *LinkingOutput) {
d5201 1
a5201 1
  const Driver &D = HTC.getDriver();
d5206 7
a5212 8
  bool IsStatic = Args.hasArg(options::OPT_static);
  bool IsShared = Args.hasArg(options::OPT_shared);
  bool IsPIE = Args.hasArg(options::OPT_pie);
  bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
  bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
  bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
  bool UseG0 = false;
  bool UseShared = IsShared && !IsStatic;
d5217 1
d5227 1
a5227 7
  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  if (Args.hasArg(options::OPT_r))
    CmdArgs.push_back("-r");

  for (const auto &Opt : HTC.ExtraOpts)
d5230 2
a5231 5
  CmdArgs.push_back("-march=hexagon");
  std::string CpuVer =
        toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str();
  std::string MCpuString = "-mcpu=hexagon" + CpuVer;
  CmdArgs.push_back(Args.MakeArgString(MCpuString));
d5233 1
a5233 1
  if (IsShared) {
d5235 2
a5236 2
    // The following should be the default, but doing as hexagon-gcc does.
    CmdArgs.push_back("-call_shared");
d5239 1
a5239 1
  if (IsStatic)
d5242 1
a5242 1
  if (IsPIE && !IsShared)
d5245 4
a5248 4
  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
    std::string N = llvm::utostr(G.getValue());
    CmdArgs.push_back(Args.MakeArgString(std::string("-G") + N));
    UseG0 = G.getValue() == 0;
d5257 10
d5270 2
a5271 2
  std::vector<std::string> OsLibs;
  bool HasStandalone = false;
d5273 9
a5281 8
  for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
    A->claim();
    OsLibs.emplace_back(A->getValue());
    HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
  }
  if (OsLibs.empty()) {
    OsLibs.push_back("standalone");
    HasStandalone = true;
d5287 6
a5292 21
  const std::string MCpuSuffix = "/" + CpuVer;
  const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
  const std::string RootDir =
      HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
  const std::string StartSubDir =
      "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);

  auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
                      const char *Name) -> std::string {
    std::string RelName = SubDir + Name;
    std::string P = HTC.GetFilePath(RelName.c_str());
    if (llvm::sys::fs::exists(P))
      return P;
    return RootDir + RelName;
  };

  if (IncStdLib && IncStartFiles) {
    if (!IsShared) {
      if (HasStandalone) {
        std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
        CmdArgs.push_back(Args.MakeArgString(Crt0SA));
d5294 1
a5294 2
      std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
      CmdArgs.push_back(Args.MakeArgString(Crt0));
d5296 2
a5297 4
    std::string Init = UseShared
          ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
          : Find(RootDir, StartSubDir, "/init.o");
    CmdArgs.push_back(Args.MakeArgString(Init));
d5303 1
a5303 1
  const ToolChain::path_list &LibPaths = HTC.getFilePaths();
d5310 5
a5314 3
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
                   options::OPT_t, options::OPT_u_Group});
d5316 1
a5316 1
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs);
d5321 1
a5321 1
  if (IncStdLib && IncDefLibs) {
d5323 1
a5323 1
      HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
d5329 4
a5332 3
    if (!IsShared) {
      for (const std::string &Lib : OsLibs)
        CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
d5343 3
a5345 5
  if (IncStdLib && IncStartFiles) {
    std::string Fini = UseShared
          ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
          : Find(RootDir, StartSubDir, "/fini.o");
    CmdArgs.push_back(Args.MakeArgString(Fini));
a5346 1
}
d5348 1
a5348 12
void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());

  ArgStringList CmdArgs;
  constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
                           LinkingOutput);

  std::string Linker = HTC.GetProgramPath("hexagon-link");
d5350 1
a5350 1
                                          CmdArgs, Inputs));
d5354 9
a5362 55
void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {

  std::string Linker = getToolChain().GetProgramPath(getShortName());
  ArgStringList CmdArgs;
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs, Inputs));
}
// AMDGPU tools end.

wasm::Linker::Linker(const ToolChain &TC)
  : GnuTool("wasm::Linker", "lld", TC) {}

bool wasm::Linker::isLinkJob() const {
  return true;
}

bool wasm::Linker::hasIntegratedCPP() const {
  return false;
}

void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  const char *Linker = Args.MakeArgString(getToolChain().GetLinkerPath());
  ArgStringList CmdArgs;
  CmdArgs.push_back("-flavor");
  CmdArgs.push_back("ld");

  // Enable garbage collection of unused input sections by default, since code
  // size is of particular importance. This is significantly facilitated by
  // the enabling of -ffunction-sections and -fdata-sections in
  // Clang::ConstructJob.
  if (areOptimizationsEnabled(Args))
    CmdArgs.push_back("--gc-sections");

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs));
}

const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
  std::string MArch;
  if (!Arch.empty())
    MArch = Arch;
  else
d5364 1
a5364 1
  MArch = StringRef(MArch).split("+").first.lower();
d5370 3
a5372 8
      // Translate the native cpu into the architecture suffix for that CPU.
      StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
      // If there is no valid architecture suffix for this CPU we don't know how
      // to handle it, so return no architecture.
      if (Suffix.empty())
        MArch = "";
      else
        MArch = std::string("arm") + Suffix.str();
a5375 13
  return MArch;
}

/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
  std::string MArch = getARMArch(Arch, Triple);
  // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
  // here means an -march=native that we can't handle, so instead return no CPU.
  if (MArch.empty())
    return StringRef();

  // We need to return an empty string here on invalid MArch values as the
  // various places that call this function can't cope with a null result.
d5380 2
a5381 2
std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
                                 const llvm::Triple &Triple) {
d5384 2
a5385 2
  if (!CPU.empty()) {
    std::string MCPU = StringRef(CPU).split("+").first.lower();
d5393 1
a5393 1
  return getARMCPUForMArch(Arch, Triple);
d5397 2
a5398 1
/// CPU  (or Arch, if CPU is generic).
d5400 25
a5424 20
StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
                                       const llvm::Triple &Triple) {
  unsigned ArchKind;
  if (CPU == "generic") {
    std::string ARMArch = tools::arm::getARMArch(Arch, Triple);
    ArchKind = llvm::ARM::parseArch(ARMArch);
    if (ArchKind == llvm::ARM::AK_INVALID)
      // In case of generic Arch, i.e. "arm",
      // extract arch from default cpu of the Triple
      ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
  } else {
    // FIXME: horrible hack to get around the fact that Cortex-A7 is only an
    // armv7k triple if it's actually been specified via "-arch armv7k".
    ArchKind = (Arch == "armv7k" || Arch == "thumbv7k")
                          ? (unsigned)llvm::ARM::AK_ARMV7K
                          : llvm::ARM::parseCPUArch(CPU);
  }
  if (ArchKind == llvm::ARM::AK_INVALID)
    return "";
  return llvm::ARM::getSubArch(ArchKind);
d5427 1
a5427 2
void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
                            const llvm::Triple &Triple) {
d5431 8
a5438 27
  // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
  // to generate BE-8 executables.
  if (getARMSubArchVersionNumber(Triple) >= 7 || isARMMProfile(Triple))
    CmdArgs.push_back("--be8");
}

mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
  // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008
  // was first introduced in Release 3. However, other compilers have
  // traditionally allowed it for Release 2 so we should do the same.
  return (NanEncoding)llvm::StringSwitch<int>(CPU)
      .Case("mips1", NanLegacy)
      .Case("mips2", NanLegacy)
      .Case("mips3", NanLegacy)
      .Case("mips4", NanLegacy)
      .Case("mips5", NanLegacy)
      .Case("mips32", NanLegacy)
      .Case("mips32r2", NanLegacy | Nan2008)
      .Case("mips32r3", NanLegacy | Nan2008)
      .Case("mips32r5", NanLegacy | Nan2008)
      .Case("mips32r6", Nan2008)
      .Case("mips64", NanLegacy)
      .Case("mips64r2", NanLegacy | Nan2008)
      .Case("mips64r3", NanLegacy | Nan2008)
      .Case("mips64r5", NanLegacy | Nan2008)
      .Case("mips64r6", Nan2008)
      .Default(NanLegacy);
d5454 3
a5456 3
        .Case("2008", true)
        .Case("legacy", false)
        .Default(false);
d5460 2
a5461 2
      .Cases("mips32r6", "mips64r6", true)
      .Default(false);
d5467 1
a5467 1
                         StringRef ABIName, mips::FloatABI FloatABI) {
a5474 5
  // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
  // present.
  if (FloatABI == mips::FloatABI::Soft)
    return false;

d5476 4
a5479 18
      .Cases("mips2", "mips3", "mips4", "mips5", true)
      .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
      .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
      .Default(false);
}

bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
                         StringRef CPUName, StringRef ABIName,
                         mips::FloatABI FloatABI) {
  bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);

  // FPXX shouldn't be used if -msingle-float is present.
  if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
                               options::OPT_mdouble_float))
    if (A->getOption().matches(options::OPT_msingle_float))
      UseFPXX = false;

  return UseFPXX;
d5496 19
a5514 19
      .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
      .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
      .Case("ppc64", llvm::Triple::ppc64)
      .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
      .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
             llvm::Triple::x86)
      .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
      // This is derived from the driver driver.
      .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
      .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
      .Cases("armv7s", "xscale", llvm::Triple::arm)
      .Case("arm64", llvm::Triple::aarch64)
      .Case("r600", llvm::Triple::r600)
      .Case("amdgcn", llvm::Triple::amdgcn)
      .Case("nvptx", llvm::Triple::nvptx)
      .Case("nvptx64", llvm::Triple::nvptx64)
      .Case("amdil", llvm::Triple::amdil)
      .Case("spir", llvm::Triple::spir)
      .Default(llvm::Triple::UnknownArch);
d5518 1
a5518 1
  const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
d5530 3
a5532 2
                                    const InputInfo &Input) {
  return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput()));
d5537 1
a5537 1
  const char *Str = getBaseInputName(Args, Inputs[0]);
d5559 1
a5559 1
void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
a5563 62
  const ToolChain &ToolChain = getToolChain();
  const Driver &D = ToolChain.getDriver();
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  // CloudABI only supports static linkage.
  CmdArgs.push_back("-Bstatic");
  CmdArgs.push_back("--eh-frame-hdr");
  CmdArgs.push_back("--gc-sections");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
                   options::OPT_t, options::OPT_Z_Flag, options::OPT_r});

  if (D.isUsingLTO())
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX())
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lcompiler_rt");
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));

  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
d5576 1
a5576 1
  // If -fno-integrated-as is used add -Q to the darwin assember driver to make
d5580 1
a5580 1
  // information forwarded by -target-assembler-version.
d5612 2
a5613 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d5624 3
a5626 2
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d5644 1
a5644 1
bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
d5655 4
a5658 3
void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
                                 ArgStringList &CmdArgs,
                                 const InputInfoList &Inputs) const {
d5662 1
a5662 1
  unsigned Version[3] = {0, 0, 0};
d5665 2
a5666 2
    if (!Driver::GetReleaseVersion(A->getValue(), Version[0], Version[1],
                                   Version[2], HadExtra) ||
d5668 2
a5669 1
      D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args);
d5680 9
a5688 34
  // If we are using App Extension restrictions, pass a flag to the linker
  // telling it that the compiled code has been audited.
  if (Args.hasFlag(options::OPT_fapplication_extension,
                   options::OPT_fno_application_extension, false))
    CmdArgs.push_back("-application_extension");

  if (D.isUsingLTO()) {
    // If we are using LTO, then automatically create a temporary file path for
    // the linker to use, so that it's lifetime will extend past a possible
    // dsymutil step.
    if (Version[0] >= 116 && NeedsTempPath(Inputs)) {
      const char *TmpPath = C.getArgs().MakeArgString(
          D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
      C.addTempFile(TmpPath);
      CmdArgs.push_back("-object_path_lto");
      CmdArgs.push_back(TmpPath);
    }

    // Use -lto_library option to specify the libLTO.dylib path. Try to find
    // it in clang installed libraries. If not found, the option is not used
    // and 'ld' will use its default mechanism to search for libLTO.dylib.
    if (Version[0] >= 133) {
      // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
      StringRef P = llvm::sys::path::parent_path(D.getInstalledDir());
      SmallString<128> LibLTOPath(P);
      llvm::sys::path::append(LibLTOPath, "lib");
      llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
      if (llvm::sys::fs::exists(LibLTOPath)) {
        CmdArgs.push_back("-lto_library");
        CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
      } else {
        D.Diag(diag::warn_drv_lto_libpath);
      }
    }
d5713 2
a5714 2
      D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
                                                       << "-dynamiclib";
d5729 2
a5730 2
      D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
                                                      << "-dynamiclib";
d5768 3
a5770 3
  if (const Arg *A =
          Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
                          options::OPT_fno_pie, options::OPT_fno_PIE)) {
d5829 11
a5839 5
void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
d5859 1
a5859 1
        Args.MakeArgString(getToolChain().GetProgramPath("touch"));
d5861 1
a5861 1
    C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, None));
d5869 7
a5875 5
  // It seems that the 'e' option is completely ignored for dynamic executables
  // (the default), and with static executables, the last one wins, as expected.
  Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
                            options::OPT_Z_Flag, options::OPT_u_Group,
                            options::OPT_e, options::OPT_r});
d5886 2
a5887 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
d5890 23
a5912 7
  // SafeStack requires its own runtime libraries
  // These libraries should be linked first, to make sure the
  // __safestack_init constructor executes before everything else
  if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
    getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
                                          "libclang_rt.safestack_osx.a",
                                          /*AlwaysLink=*/true);
a5914 2
  Args.AddAllArgs(CmdArgs, options::OPT_L);

a5932 3
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
    addOpenMPRuntime(CmdArgs, getToolChain(), Args);

d5934 2
a5935 1
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d5954 2
a5955 3
  getMachOToolChain().addProfileRTLibs(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d5965 2
a5966 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d5973 2
a5974 14
  // -iframework should be forwarded as -F.
  for (const Arg *A : Args.filtered(options::OPT_iframework))
    CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
      if (A->getValue() == StringRef("Accelerate")) {
        CmdArgs.push_back("-framework");
        CmdArgs.push_back("Accelerate");
      }
    }
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
d5976 1
a5976 1
      llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs);
d6000 1
a6000 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6019 2
a6020 2
      Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6042 2
a6043 2
      Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6046 1
a6046 1
void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
d6054 2
a6055 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d6064 1
a6064 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6067 24
a6090 5
void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
d6096 2
a6097 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
d6111 1
a6111 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("ld.so.1")));
d6122 15
a6136 4
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
d6138 1
a6138 6
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
    CmdArgs.push_back(
        Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o")));
    CmdArgs.push_back(
        Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
  }
d6140 4
a6143 4
  getToolChain().AddFilePathLibArgs(Args, CmdArgs);

  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
                            options::OPT_e, options::OPT_r});
d6147 2
a6148 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
a6151 1
    CmdArgs.push_back("-lc");
d6154 1
d6159 3
a6161 3
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    CmdArgs.push_back(
        Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
d6163 1
a6163 1
  CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
d6165 1
a6165 1
  getToolChain().addProfileRTLibs(Args, CmdArgs);
d6167 3
a6169 2
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6172 5
a6176 5
void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
d6179 1
a6193 1
  case llvm::Triple::sparcel: {
d6195 1
a6195 3
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
a6196 1
  }
d6198 1
a6198 1
  case llvm::Triple::sparcv9: {
d6200 2
a6201 3
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
a6202 1
  }
d6218 1
a6218 1
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
d6226 5
a6230 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d6238 3
a6240 2
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6243 5
a6247 5
void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
d6264 2
a6265 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
d6295 2
a6296 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6298 3
a6300 3
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(
            Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
d6302 4
a6305 4
        CmdArgs.push_back(
            Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
d6307 2
a6308 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
d6315 2
a6316 2
  CmdArgs.push_back(
      Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
d6318 7
a6324 3
  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
                            options::OPT_e, options::OPT_s, options::OPT_t,
                            options::OPT_Z_Flag, options::OPT_r});
d6328 2
a6329 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d6332 1
a6332 1
      if (Args.hasArg(options::OPT_pg))
d6343 3
a6345 2
      if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
d6347 1
a6347 1
        CmdArgs.push_back("-lpthread");
d6352 1
a6352 1
        CmdArgs.push_back("-lc_p");
d6354 1
a6354 1
        CmdArgs.push_back("-lc");
d6360 2
a6361 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6363 2
a6364 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
d6366 2
a6367 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
d6370 3
a6372 2
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6375 5
a6379 5
void bitrig::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
d6383 2
a6384 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d6393 1
a6393 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6396 5
a6400 5
void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
d6404 2
a6405 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
d6432 2
a6433 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6436 2
a6437 2
        CmdArgs.push_back(
            Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
d6439 4
a6442 4
        CmdArgs.push_back(
            Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
d6444 2
a6445 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
d6449 3
a6451 2
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_L, options::OPT_T_Group, options::OPT_e});
d6455 2
a6456 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d6466 2
a6467 1
      if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
d6481 1
a6481 1
    switch (getToolChain().getArch()) {
d6497 2
a6498 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6500 2
a6501 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
d6503 2
a6504 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
d6507 3
a6509 2
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6512 5
a6516 5
void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
d6522 1
a6522 4
  switch (getToolChain().getArch()) {
  default:
    break;
  case llvm::Triple::x86:
d6524 1
a6524 2
    break;
  case llvm::Triple::ppc:
d6526 4
a6529 5
    break;
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
d6546 8
a6553 14
    if (Arg *A = Args.getLastArg(options::OPT_G)) {
      StringRef v = A->getValue();
      CmdArgs.push_back(Args.MakeArgString("-G" + v));
      A->claim();
    }

    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
    break;
  }
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb: {
    arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
d6555 1
a6555 1
    if (ABI == arm::FloatABI::Hard)
d6557 1
a6557 1
    else
d6559 1
d6561 1
a6561 1
    switch (getToolChain().getTriple().getEnvironment()) {
d6571 8
a6578 10
    break;
  }
  case llvm::Triple::sparc:
  case llvm::Triple::sparcel:
  case llvm::Triple::sparcv9: {
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
    break;
  }
d6581 2
a6582 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d6591 1
a6591 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6594 7
a6600 7
void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  const toolchains::FreeBSD &ToolChain =
      static_cast<const toolchains::FreeBSD &>(getToolChain());
a6601 1
  const llvm::Triple::ArchType Arch = ToolChain.getArch();
d6603 2
a6604 2
      !Args.hasArg(options::OPT_shared) &&
      (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
d6634 1
d6645 1
a6645 1
  if (Arch == llvm::Triple::x86) {
d6650 1
a6650 1
  if (Arch == llvm::Triple::ppc) {
a6654 11
  if (Arg *A = Args.getLastArg(options::OPT_G)) {
    if (ToolChain.getArch() == llvm::Triple::mips ||
      ToolChain.getArch() == llvm::Triple::mipsel ||
      ToolChain.getArch() == llvm::Triple::mips64 ||
      ToolChain.getArch() == llvm::Triple::mips64el) {
      StringRef v = A->getValue();
      CmdArgs.push_back(Args.MakeArgString("-G" + v));
      A->claim();
    }
  }

d6662 2
a6663 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6690 3
a6692 1
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
d6700 2
a6701 2
  if (D.isUsingLTO())
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
d6706 2
a6707 2
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    addOpenMPRuntime(CmdArgs, ToolChain, Args);
d6762 2
a6763 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6771 1
a6771 1
  ToolChain.addProfileRTLibs(Args, CmdArgs);
d6773 3
a6775 2
  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6778 1
a6778 1
void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
d6796 2
a6797 5
    StringRef MArch, MCPU;
    getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
    std::string Arch =
        arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple());
    CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
d6821 1
a6821 1
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
a6825 1
  case llvm::Triple::sparcel: {
d6827 1
a6827 3
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
a6828 1
  }
d6830 1
a6830 1
  case llvm::Triple::sparcv9: {
d6832 2
a6833 3
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
a6834 1
  }
d6837 1
a6837 1
    break;
d6840 2
a6841 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d6850 1
a6850 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d6853 5
a6857 5
void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
d6904 1
a6904 3
    arm::appendEBLinkFlags(
        Args, CmdArgs,
        llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
d6928 8
a6935 8
    } else if (mips::hasMipsAbiArg(Args, "64")) {
      CmdArgs.push_back("-m");
      if (getToolChain().getArch() == llvm::Triple::mips64)
        CmdArgs.push_back("elf64btsmip");
      else
        CmdArgs.push_back("elf64ltsmip");
    }
    break;
d6968 2
a6969 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d6971 11
a6981 11
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
d6999 1
a6999 1
    switch (getToolChain().getArch()) {
a7007 2
    case llvm::Triple::sparc:
    case llvm::Triple::sparcv9:
d7017 2
a7018 2
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    addOpenMPRuntime(CmdArgs, getToolChain(), Args);
d7044 2
a7045 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d7047 2
a7048 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
d7050 4
a7053 3
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
d7056 1
a7056 1
  getToolChain().addProfileRTLibs(Args, CmdArgs);
d7059 1
a7059 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7062 5
a7066 5
void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
a7068 3
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple = llvm::Triple(TripleStr);

d7070 1
a7071 9
  llvm::Reloc::Model RelocationModel;
  unsigned PICLevel;
  bool IsPIE;
  std::tie(RelocationModel, PICLevel, IsPIE) =
      ParsePICArgs(getToolChain(), Triple, Args);

  switch (getToolChain().getArch()) {
  default:
    break;
d7074 1
a7074 1
  case llvm::Triple::x86:
d7076 1
a7076 2
    break;
  case llvm::Triple::x86_64:
d7081 1
a7081 2
    break;
  case llvm::Triple::ppc:
d7085 1
a7085 2
    break;
  case llvm::Triple::ppc64:
d7089 1
a7089 2
    break;
  case llvm::Triple::ppc64le:
d7094 1
a7094 3
    break;
  case llvm::Triple::sparc:
  case llvm::Triple::sparcel: {
d7096 3
a7098 6
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
    break;
  }
  case llvm::Triple::sparcv9: {
d7100 6
a7105 12
    std::string CPU = getCPUName(Args, getToolChain().getTriple());
    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
    break;
  }
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb: {
    const llvm::Triple &Triple2 = getToolChain().getTriple();
    switch (Triple2.getSubArch()) {
    case llvm::Triple::ARMSubArch_v7:
d7107 2
a7108 2
      break;
    case llvm::Triple::ARMSubArch_v8:
a7109 4
      break;
    default:
      break;
    }
d7111 3
a7113 12
    switch (arm::getARMFloatABI(getToolChain(), Args)) {
    case arm::FloatABI::Invalid: llvm_unreachable("must have an ABI!");
    case arm::FloatABI::Soft:
      CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=soft"));
      break;
    case arm::FloatABI::SoftFP:
      CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=softfp"));
      break;
    case arm::FloatABI::Hard:
      CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=hard"));
      break;
    }
d7122 2
a7123 2
        StringRef(A->getValue()).lower() == "krait")
      CmdArgs.push_back("-march=armv7-a");
d7127 4
a7130 6
    break;
  }
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
d7144 12
a7155 1
    if (RelocationModel == llvm::Reloc::Static)
d7178 2
a7179 3
    } else if (mips::shouldUseFPXX(
                   Args, getToolChain().getTriple(), CPUName, ABIName,
                   getMipsFloatABI(getToolChain().getDriver(), Args)))
d7184 2
a7185 2
    if (Arg *A =
            Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16)) {
a7209 3
    Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,
                    options::OPT_msingle_float);

d7213 2
a7214 4
    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
    break;
  }
  case llvm::Triple::systemz: {
a7218 2
    break;
  }
d7221 5
a7225 2
  Args.AddAllArgs(CmdArgs, options::OPT_I);
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d7234 1
a7234 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7242 1
a7242 1
                   SplitDebugName(Args, Inputs[0]));
d7247 1
a7247 2
  bool isAndroid = Triple.isAndroid();
  bool isCygMing = Triple.isOSCygMing();
d7257 1
a7257 1
    if (!D.CCCIsCXX() && !isCygMing)
d7260 1
a7260 1
    if (!D.CCCIsCXX() && !isCygMing)
d7280 1
a7280 3
  const llvm::Triple::ArchType Arch = ToolChain.getArch();

  if (ToolChain.getTriple().isAndroid()) {
d7285 2
a7286 2
  } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::sparc ||
             Arch == llvm::Triple::sparcel)
d7288 1
a7288 1
  else if (Arch == llvm::Triple::aarch64)
d7290 1
a7290 1
  else if (Arch == llvm::Triple::aarch64_be)
d7292 3
a7294 3
  else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF ||
        arm::getARMFloatABI(ToolChain, Args) == arm::FloatABI::Hard)
d7298 20
a7317 11
  } else if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) {
    // TODO: check which dynamic linker name.
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF ||
        arm::getARMFloatABI(ToolChain, Args) == arm::FloatABI::Hard)
      return "/lib/ld-linux-armhf.so.3";
    else
      return "/lib/ld-linux.so.3";
  } else if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
             Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el) {
    std::string LibDir =
        "/lib" + mips::getMipsABILibSuffix(Args, ToolChain.getTriple());
a7318 1
    bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple());
d7321 1
a7321 5
    else if (!ToolChain.getTriple().hasEnvironment()) {
      bool LE = (ToolChain.getTriple().getArch() == llvm::Triple::mipsel) ||
                (ToolChain.getTriple().getArch() == llvm::Triple::mips64el);
      LibName = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1";
    } else
d7325 1
a7325 1
  } else if (Arch == llvm::Triple::ppc)
d7327 1
a7327 1
  else if (Arch == llvm::Triple::ppc64) {
d7331 1
a7331 1
  } else if (Arch == llvm::Triple::ppc64le) {
d7335 3
a7337 3
  } else if (Arch == llvm::Triple::systemz)
    return "/lib/ld64.so.1";
  else if (Arch == llvm::Triple::sparcv9)
d7339 1
a7339 1
  else if (Arch == llvm::Triple::x86_64 &&
d7354 1
a7354 2
    default:
      llvm_unreachable("unsupported OS");
a7387 1
  case llvm::Triple::sparcel:
d7414 7
a7420 7
void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  const toolchains::Linux &ToolChain =
      static_cast<const toolchains::Linux &>(getToolChain());
d7422 2
a7423 6

  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple = llvm::Triple(TripleStr);

  const llvm::Triple::ArchType Arch = ToolChain.getArch();
  const bool isAndroid = ToolChain.getTriple().isAndroid();
d7425 7
a7431 5
      !Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) &&
      (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
  const bool HasCRTBeginEndFiles =
      ToolChain.getTriple().hasEnvironment() ||
      (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies);
a7442 8
  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  if (llvm::sys::path::filename(Exec) == "lld") {
    CmdArgs.push_back("-flavor");
    CmdArgs.push_back("old-gnu");
    CmdArgs.push_back("-target");
    CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
  }

d7455 3
a7457 2
  if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
    arm::appendEBLinkFlags(Args, CmdArgs, Triple);
d7470 4
a7473 2
    if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
        Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb)
d7481 4
a7484 2
  if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
      Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
d7495 2
a7496 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d7499 1
a7499 1
      if (!Args.hasArg(options::OPT_shared)) {
d7522 1
a7522 3

    if (HasCRTBeginEndFiles)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
d7531 4
a7534 1
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
d7536 2
a7537 2
  if (D.isUsingLTO())
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
d7545 1
a7545 1
  getToolChain().addProfileRTLibs(Args, CmdArgs);
d7548 2
a7549 1
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d7551 1
a7551 1
                               !Args.hasArg(options::OPT_static);
a7558 2
  // Silence warnings when linking C code with a C++ '-stdlib' argument.
  Args.ClaimAllArgs(options::OPT_stdlib_EQ);
d7568 15
a7582 2
      bool WantPthread = Args.hasArg(options::OPT_pthread) ||
                         Args.hasArg(options::OPT_pthreads);
d7584 9
a7592 25
      if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
                       options::OPT_fno_openmp, false)) {
        // OpenMP runtimes implies pthreads when using the GNU toolchain.
        // FIXME: Does this really make sense for all GNU toolchains?
        WantPthread = true;

        // Also link the particular OpenMP runtimes.
        switch (getOpenMPRuntime(ToolChain, Args)) {
        case OMPRT_OMP:
          CmdArgs.push_back("-lomp");
          break;
        case OMPRT_GOMP:
          CmdArgs.push_back("-lgomp");

          // FIXME: Exclude this for platforms with libgomp that don't require
          // librt. Most modern Linux platforms require it, but some may not.
          CmdArgs.push_back("-lrt");
          break;
        case OMPRT_IOMP5:
          CmdArgs.push_back("-liomp5");
          break;
        case OMPRT_Unknown:
          // Already diagnosed.
          break;
        }
a7593 1

d7596 3
a7598 1
      if (WantPthread && !isAndroid)
d7618 1
a7618 2
      if (HasCRTBeginEndFiles)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
d7624 2
a7625 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7628 5
a7632 177
// NaCl ARM assembly (inline or standalone) can be written with a set of macros
// for the various SFI requirements like register masking. The assembly tool
// inserts the file containing the macros as an input into all the assembly
// jobs.
void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
  const toolchains::NaClToolChain &ToolChain =
      static_cast<const toolchains::NaClToolChain &>(getToolChain());
  InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(),
                       "nacl-arm-macros.s");
  InputInfoList NewInputs;
  NewInputs.push_back(NaClMacros);
  NewInputs.append(Inputs.begin(), Inputs.end());
  gnutools::Assembler::ConstructJob(C, JA, Output, NewInputs, Args,
                                    LinkingOutput);
}

// This is quite similar to gnutools::Linker::ConstructJob with changes that
// we use static by default, do not yet support sanitizers or LTO, and a few
// others. Eventually we can support more of that and hopefully migrate back
// to gnutools::Linker.
void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {

  const toolchains::NaClToolChain &ToolChain =
      static_cast<const toolchains::NaClToolChain &>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const llvm::Triple::ArchType Arch = ToolChain.getArch();
  const bool IsStatic =
      !Args.hasArg(options::OPT_dynamic) && !Args.hasArg(options::OPT_shared);

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  // NaClToolChain doesn't have ExtraOpts like Linux; the only relevant flag
  // from there is --build-id, which we do want.
  CmdArgs.push_back("--build-id");

  if (!IsStatic)
    CmdArgs.push_back("--eh-frame-hdr");

  CmdArgs.push_back("-m");
  if (Arch == llvm::Triple::x86)
    CmdArgs.push_back("elf_i386_nacl");
  else if (Arch == llvm::Triple::arm)
    CmdArgs.push_back("armelf_nacl");
  else if (Arch == llvm::Triple::x86_64)
    CmdArgs.push_back("elf_x86_64_nacl");
  else if (Arch == llvm::Triple::mipsel)
    CmdArgs.push_back("mipselelf_nacl");
  else
    D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName()
                                              << "Native Client";

  if (IsStatic)
    CmdArgs.push_back("-static");
  else if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("-shared");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

    const char *crtbegin;
    if (IsStatic)
      crtbegin = "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared))
      crtbegin = "crtbeginS.o";
    else
      crtbegin = "crtbegin.o";
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_u);

  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (D.CCCIsCXX() &&
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    bool OnlyLibstdcxxStatic =
        Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic;
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bstatic");
    ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bdynamic");
    CmdArgs.push_back("-lm");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      // Always use groups, since it has no effect on dynamic libraries.
      CmdArgs.push_back("--start-group");
      CmdArgs.push_back("-lc");
      // NaCl's libc++ currently requires libpthread, so just always include it
      // in the group for C++.
      if (Args.hasArg(options::OPT_pthread) ||
          Args.hasArg(options::OPT_pthreads) || D.CCCIsCXX()) {
        // Gold, used by Mips, handles nested groups differently than ld, and
        // without '-lnacl' it prefers symbols from libpthread.a over libnacl.a,
        // which is not a desired behaviour here.
        // See https://sourceware.org/ml/binutils/2015-03/msg00034.html
        if (getToolChain().getArch() == llvm::Triple::mipsel)
          CmdArgs.push_back("-lnacl");

        CmdArgs.push_back("-lpthread");
      }

      CmdArgs.push_back("-lgcc");
      CmdArgs.push_back("--as-needed");
      if (IsStatic)
        CmdArgs.push_back("-lgcc_eh");
      else
        CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");

      // Mips needs to create and use pnacl_legacy library that contains
      // definitions from bitcode/pnaclmm.c and definitions for
      // __nacl_tp_tls_offset() and __nacl_tp_tdb_offset().
      if (getToolChain().getArch() == llvm::Triple::mipsel)
        CmdArgs.push_back("-lpnacl_legacy");

      CmdArgs.push_back("--end-group");
    }

    if (!Args.hasArg(options::OPT_nostartfiles)) {
      const char *crtend;
      if (Args.hasArg(options::OPT_shared))
        crtend = "crtendS.o";
      else
        crtend = "crtend.o";

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
    }
  }

  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
d7645 1
a7645 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7648 5
a7652 5
void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
d7663 6
a7668 6
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
    CmdArgs.push_back(
        Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
d7671 3
a7673 2
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_L, options::OPT_T_Group, options::OPT_e});
d7677 1
a7677 1
  getToolChain().addProfileRTLibs(Args, CmdArgs);
d7679 2
a7680 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
d7687 2
a7688 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d7695 1
a7695 1
        Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
d7699 1
a7699 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7706 5
a7710 5
void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                        const InputInfo &Output,
                                        const InputInfoList &Inputs,
                                        const ArgList &Args,
                                        const char *LinkingOutput) const {
d7728 1
a7728 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7731 5
a7735 5
void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
d7738 1
d7755 1
a7755 2
    CmdArgs.push_back("--hash-style=gnu");
    CmdArgs.push_back("--enable-new-dtags");
d7772 2
a7773 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d7776 2
a7777 2
        CmdArgs.push_back(
            Args.MakeArgString(getToolChain().GetFilePath("gcrt1.o")));
d7780 2
a7781 2
          CmdArgs.push_back(
              Args.MakeArgString(getToolChain().GetFilePath("Scrt1.o")));
d7783 2
a7784 2
          CmdArgs.push_back(
              Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
d7787 2
a7788 1
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
d7790 2
a7791 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
d7793 2
a7794 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
d7797 3
a7799 2
  Args.AddAllArgs(CmdArgs,
                  {options::OPT_L, options::OPT_T_Group, options::OPT_e});
d7803 8
a7810 2
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    CmdArgs.push_back("-L/usr/lib/gcc50");
d7813 7
a7819 2
      CmdArgs.push_back("-rpath");
      CmdArgs.push_back("/usr/lib/gcc50");
d7834 3
a7836 2
    if (Args.hasArg(options::OPT_static) ||
        Args.hasArg(options::OPT_static_libgcc)) {
d7839 2
a7840 2
    } else {
      if (Args.hasArg(options::OPT_shared_libgcc)) {
d7844 1
a7844 1
      } else {
d7849 7
d7860 2
a7861 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d7863 2
a7864 2
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
d7866 4
a7869 3
      CmdArgs.push_back(
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
d7872 1
a7872 1
  getToolChain().addProfileRTLibs(Args, CmdArgs);
d7875 1
a7875 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d7898 5
a7902 5
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                        const InputInfo &Output,
                                        const InputInfoList &Inputs,
                                        const ArgList &Args,
                                        const char *LinkingOutput) const {
d7908 2
a7909 2
    CmdArgs.push_back(
        Args.MakeArgString(std::string("-out:") + Output.getFilename()));
d7911 2
a7912 2
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
      !C.getDriver().IsCLMode())
d7918 2
a7919 2
    // the environment variable is set however, assume the user knows what
    // they're doing.
a7939 7

      if (MSVC.useUniversalCRT(VisualStudioDir)) {
        std::string UniversalCRTLibPath;
        if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
          CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
                                               UniversalCRTLibPath.c_str()));
      }
d7950 1
a7950 1
  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
d7953 1
a7953 2
  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
                         options::OPT_shared);
d7959 2
a7960 1
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
d7967 6
a7972 2
      for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
d7977 1
a7977 1
      CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
d7979 6
a7984 2
      for (const auto &Lib : {"asan", "asan_cxx"})
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
a7989 21
  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
                   options::OPT_fno_openmp, false)) {
    CmdArgs.push_back("-nodefaultlib:vcomp.lib");
    CmdArgs.push_back("-nodefaultlib:vcompd.lib");
    CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
                                         TC.getDriver().Dir + "/../lib"));
    switch (getOpenMPRuntime(getToolChain(), Args)) {
    case OMPRT_OMP:
      CmdArgs.push_back("-defaultlib:libomp.lib");
      break;
    case OMPRT_IOMP5:
      CmdArgs.push_back("-defaultlib:libiomp5md.lib");
      break;
    case OMPRT_GOMP:
      break;
    case OMPRT_Unknown:
      // Already diagnosed.
      break;
    }
  }

a8015 2
  TC.addProfileRTLibs(Args, CmdArgs);

d8037 1
a8037 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d8040 5
a8044 5
void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
                                          const InputInfo &Output,
                                          const InputInfoList &Inputs,
                                          const ArgList &Args,
                                          const char *LinkingOutput) const {
d8048 1
a8048 1
std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
d8054 1
a8054 1
  CmdArgs.push_back("/c");  // Compile only.
d8061 2
a8062 1
  Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
a8064 3
  if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
                                                                      : "/Oi-");
a8068 2
      CmdArgs.push_back("/Og");

d8070 4
a8073 6
      if (OptLevel == "s" || OptLevel == "z")
        CmdArgs.push_back("/Os");
      else
        CmdArgs.push_back("/Ot");

      CmdArgs.push_back("/Ob2");
a8075 7
  if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
                               options::OPT_fno_omit_frame_pointer))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
                          ? "/Oy"
                          : "/Oy-");
  if (!Args.hasArg(options::OPT_fwritable_strings))
    CmdArgs.push_back("/GF");
d8077 1
a8077 1
  // Flags for which clang-cl has an alias.
d8094 1
a8094 2
  if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
                  options::OPT__SLASH_Z7))
d8097 1
a8097 2
  std::vector<std::string> Includes =
      Args.getAllArgValues(options::OPT_include);
a8104 1
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
d8111 1
d8124 2
a8125 2
  const char *Fo =
      Args.MakeArgString(std::string("/Fo") + Output.getFilename());
d8132 1
a8132 1
                                    CmdArgs, Inputs);
d8135 9
a8143 6
/// MinGW Tools
void MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
d8147 11
a8157 5
  if (getToolChain().getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("--32");
  } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
    CmdArgs.push_back("--64");
  }
d8159 3
a8161 1
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
d8163 2
a8164 2
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
d8169 2
a8170 6
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));

  if (Args.hasArg(options::OPT_gsplit_dwarf))
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs[0]));
d8173 6
a8178 5
void MinGW::Linker::AddLibGCC(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
  if (Args.hasArg(options::OPT_mthreads))
    CmdArgs.push_back("-lmingwthrd");
  CmdArgs.push_back("-lmingw32");
d8180 3
a8182 15
  // Make use of compiler-rt if --rtlib option is used
  ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
  if (RLT == ToolChain::RLT_Libgcc) {
    bool Static = Args.hasArg(options::OPT_static_libgcc) ||
                  Args.hasArg(options::OPT_static);
    bool Shared = Args.hasArg(options::OPT_shared);
    bool CXX = getToolChain().getDriver().CCCIsCXX();

    if (Static || (!CXX && !Shared)) {
      CmdArgs.push_back("-lgcc");
      CmdArgs.push_back("-lgcc_eh");
    } else {
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("-lgcc");
    }
d8184 1
a8184 1
    AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
d8187 2
a8188 4
  CmdArgs.push_back("-lmoldname");
  CmdArgs.push_back("-lmingwex");
  CmdArgs.push_back("-lmsvcrt");
}
d8190 1
a8190 216
void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const ToolChain &TC = getToolChain();
  const Driver &D = TC.getDriver();
  // const SanitizerArgs &Sanitize = TC.getSanitizerArgs();

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  StringRef LinkerName = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "ld");
  if (LinkerName.equals_lower("lld")) {
    CmdArgs.push_back("-flavor");
    CmdArgs.push_back("gnu");
  } else if (!LinkerName.equals_lower("ld")) {
    D.Diag(diag::err_drv_unsupported_linker) << LinkerName;
  }

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  CmdArgs.push_back("-m");
  if (TC.getArch() == llvm::Triple::x86)
    CmdArgs.push_back("i386pe");
  if (TC.getArch() == llvm::Triple::x86_64)
    CmdArgs.push_back("i386pep");
  if (TC.getArch() == llvm::Triple::arm)
    CmdArgs.push_back("thumb2pe");

  if (Args.hasArg(options::OPT_mwindows)) {
    CmdArgs.push_back("--subsystem");
    CmdArgs.push_back("windows");
  } else if (Args.hasArg(options::OPT_mconsole)) {
    CmdArgs.push_back("--subsystem");
    CmdArgs.push_back("console");
  }

  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-Bstatic");
  else {
    if (Args.hasArg(options::OPT_mdll))
      CmdArgs.push_back("--dll");
    else if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("--shared");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-e");
      if (TC.getArch() == llvm::Triple::x86)
        CmdArgs.push_back("_DllMainCRTStartup@@12");
      else
        CmdArgs.push_back("DllMainCRTStartup");
      CmdArgs.push_back("--enable-auto-image-base");
    }
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  Args.AddAllArgs(CmdArgs, options::OPT_e);
  // FIXME: add -N, -n flags
  Args.AddLastArg(CmdArgs, options::OPT_r);
  Args.AddLastArg(CmdArgs, options::OPT_s);
  Args.AddLastArg(CmdArgs, options::OPT_t);
  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
  Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
      CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
    } else {
      if (Args.hasArg(options::OPT_municode))
        CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
    }
    if (Args.hasArg(options::OPT_pg))
      CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  TC.AddFilePathLibArgs(Args, CmdArgs);
  AddLinkerInputs(TC, Inputs, Args, CmdArgs);

  // TODO: Add ASan stuff here

  // TODO: Add profile stuff here

  if (D.CCCIsCXX() &&
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
                               !Args.hasArg(options::OPT_static);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bstatic");
    TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bdynamic");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--start-group");

      if (Args.hasArg(options::OPT_fstack_protector) ||
          Args.hasArg(options::OPT_fstack_protector_strong) ||
          Args.hasArg(options::OPT_fstack_protector_all)) {
        CmdArgs.push_back("-lssp_nonshared");
        CmdArgs.push_back("-lssp");
      }
      if (Args.hasArg(options::OPT_fopenmp))
        CmdArgs.push_back("-lgomp");

      AddLibGCC(Args, CmdArgs);

      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lgmon");

      if (Args.hasArg(options::OPT_pthread))
        CmdArgs.push_back("-lpthread");

      // add system libraries
      if (Args.hasArg(options::OPT_mwindows)) {
        CmdArgs.push_back("-lgdi32");
        CmdArgs.push_back("-lcomdlg32");
      }
      CmdArgs.push_back("-ladvapi32");
      CmdArgs.push_back("-lshell32");
      CmdArgs.push_back("-luser32");
      CmdArgs.push_back("-lkernel32");

      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--end-group");
      else if (!LinkerName.equals_lower("lld"))
        AddLibGCC(Args, CmdArgs);
    }

    if (!Args.hasArg(options::OPT_nostartfiles)) {
      // Add crtfastmath.o if available and fast math is enabled.
      TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs);

      CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
    }
  }
  const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data()));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

/// XCore Tools
// We pass assemble and link construction to the xcc tool.

void XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  claimNoWarnArgs(Args);
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  CmdArgs.push_back("-c");

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  if (Arg *A = Args.getLastArg(options::OPT_g_Group))
    if (!A->getOption().matches(options::OPT_g0))
      CmdArgs.push_back("-g");

  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   false))
    CmdArgs.push_back("-fverbose-asm");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  // Pass -fexceptions through to the linker if it was present.
  if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
                   false))
d8196 1
a8196 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d8199 5
a8203 5
void CrossWindows::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
d8211 1
a8211 2
  default:
    llvm_unreachable("unsupported architecture");
d8234 1
a8234 1
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
d8237 5
a8241 5
void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                        const InputInfo &Output,
                                        const InputInfoList &Inputs,
                                        const ArgList &Args,
                                        const char *LinkingOutput) const {
d8270 1
a8270 2
  default:
    llvm_unreachable("unsupported architecture");
d8287 1
a8287 2
    default:
      llvm_unreachable("unsupported architecture");
d8311 2
a8312 1
    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d8334 2
a8335 1
  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
d8345 5
a8349 1
  TC.AddFilePathLibArgs(Args, CmdArgs);
d8371 2
a8372 158
  if (TC.getSanitizerArgs().needsAsanRt()) {
    // TODO handle /MT[d] /MD[d]
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
    } else {
      for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
        CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
        // Make sure the dynamic runtime thunk is not optimized out at link time
        // to ensure proper SEH handling.
        CmdArgs.push_back(Args.MakeArgString("--undefined"));
        CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
                                                 ? "___asan_seh_interceptor"
                                                 : "__asan_seh_interceptor"));
    }
  }

  Exec = Args.MakeArgString(TC.GetLinkerPath());

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
                                          const InputInfo &Output,
                                          const InputInfoList &Inputs,
                                          const ArgList &Args,
                                          const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  assert(Inputs.size() == 1);
  const InputInfo &II = Inputs[0];
  assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX ||
         II.getType() == types::TY_PP_CXX);

  if (JA.getKind() == Action::PreprocessJobClass) {
    Args.ClaimAllArgs();
    CmdArgs.push_back("-E");
  } else {
    assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
    CmdArgs.push_back("-S");
    CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
  }
  CmdArgs.push_back("-mcpu=myriad2");
  CmdArgs.push_back("-DMYRIAD2");

  // Append all -I, -iquote, -isystem paths, defines/undefines,
  // 'f' flags, optimize flags, and warning options.
  // These are spelled the same way in clang and moviCompile.
  Args.AddAllArgs(CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group,
                            options::OPT_std_EQ, options::OPT_D, options::OPT_U,
                            options::OPT_f_Group, options::OPT_f_clang_Group,
                            options::OPT_g_Group, options::OPT_M_Group,
                            options::OPT_O_Group, options::OPT_W_Group});

  // If we're producing a dependency file, and assembly is the final action,
  // then the name of the target in the dependency file should be the '.o'
  // file, not the '.s' file produced by this step. For example, instead of
  //  /tmp/mumble.s: mumble.c .../someheader.h
  // the filename on the lefthand side should be "mumble.o"
  if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) &&
      C.getActions().size() == 1 &&
      C.getActions()[0]->getKind() == Action::AssembleJobClass) {
    Arg *A = Args.getLastArg(options::OPT_o);
    if (A) {
      CmdArgs.push_back("-MT");
      CmdArgs.push_back(Args.MakeArgString(A->getValue()));
    }
  }

  CmdArgs.push_back(II.getFilename());
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  std::string Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                          CmdArgs, Inputs));
}

void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1);
  const InputInfo &II = Inputs[0];
  assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
  assert(Output.getType() == types::TY_Object);

  CmdArgs.push_back("-no6thSlotCompression");
  CmdArgs.push_back("-cv:myriad2"); // Chip Version
  CmdArgs.push_back("-noSPrefixing");
  CmdArgs.push_back("-a"); // Mystery option.
  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
    A->claim();
    CmdArgs.push_back(
        Args.MakeArgString(std::string("-i:") + A->getValue(0)));
  }
  CmdArgs.push_back("-elf"); // Output format.
  CmdArgs.push_back(II.getFilename());
  CmdArgs.push_back(
      Args.MakeArgString(std::string("-o:") + Output.getFilename()));

  std::string Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                          CmdArgs, Inputs));
}

void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                         const InputInfo &Output,
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::MyriadToolChain &>(getToolChain());
  const llvm::Triple &T = TC.getTriple();
  ArgStringList CmdArgs;
  bool UseStartfiles =
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
  bool UseDefaultLibs =
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);

  if (T.getArch() == llvm::Triple::sparc)
    CmdArgs.push_back("-EB");
  else // SHAVE assumes little-endian, and sparcel is expressly so.
    CmdArgs.push_back("-EL");

  // The remaining logic is mostly like gnutools::Linker::ConstructJob,
  // but we never pass through a --sysroot option and various other bits.
  // For example, there are no sanitizers (yet) nor gold linker.

  // Eat some arguments that may be present but have no effect.
  Args.ClaimAllArgs(options::OPT_g_Group);
  Args.ClaimAllArgs(options::OPT_w);
  Args.ClaimAllArgs(options::OPT_static_libgcc);

  if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
    CmdArgs.push_back("-s");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (UseStartfiles) {
    // If you want startfiles, it means you want the builtin crti and crtbegin,
    // but not crt0. Myriad link commands provide their own crt0.o as needed.
    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
                            options::OPT_e, options::OPT_s, options::OPT_t,
                            options::OPT_Z_Flag, options::OPT_r});

  TC.AddFilePathLibArgs(Args, CmdArgs);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
d8374 1
a8374 321
  if (UseDefaultLibs) {
    if (C.getDriver().CCCIsCXX())
      CmdArgs.push_back("-lstdc++");
    if (T.getOS() == llvm::Triple::RTEMS) {
      CmdArgs.push_back("--start-group");
      CmdArgs.push_back("-lc");
      // You must provide your own "-L" option to enable finding these.
      CmdArgs.push_back("-lrtemscpu");
      CmdArgs.push_back("-lrtemsbsp");
      CmdArgs.push_back("--end-group");
    } else {
      CmdArgs.push_back("-lc");
    }
    CmdArgs.push_back("-lgcc");
  }
  if (UseStartfiles) {
    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
  }

  std::string Exec =
      Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
                                          CmdArgs, Inputs));
}

void PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  claimNoWarnArgs(Args);
  ArgStringList CmdArgs;

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("ps4-as"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
  if (SanArgs.needsUbsanRt()) {
    CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
  }
  if (SanArgs.needsAsanRt()) {
    CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
  }
}

static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
                                const JobAction &JA, const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) {
  const toolchains::FreeBSD &ToolChain =
      static_cast<const toolchains::FreeBSD &>(T.getToolChain());
  const Driver &D = ToolChain.getDriver();
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_pie))
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");
  if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("--oformat=so");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  AddPS4SanitizerArgs(ToolChain, CmdArgs);

  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_r);

  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (Args.hasArg(options::OPT_pthread)) {
    CmdArgs.push_back("-lpthread");
  }

  const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));

  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
}

static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
                                 const JobAction &JA, const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) {
  const toolchains::FreeBSD &ToolChain =
      static_cast<const toolchains::FreeBSD &>(T.getToolChain());
  const Driver &D = ToolChain.getDriver();
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_pie))
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld-elf.so.1");
    }
    CmdArgs.push_back("--enable-new-dtags");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  AddPS4SanitizerArgs(ToolChain, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    const char *crt1 = nullptr;
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        crt1 = "gcrt1.o";
      else if (Args.hasArg(options::OPT_pie))
        crt1 = "Scrt1.o";
      else
        crt1 = "crt1.o";
    }
    if (crt1)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

    const char *crtbegin = nullptr;
    if (Args.hasArg(options::OPT_static))
      crtbegin = "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      crtbegin = "crtbeginS.o";
    else
      crtbegin = "crtbegin.o";

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
  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_r);

  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    // For PS4, we always want to pass libm, libstdc++ and libkernel
    // libraries for both C and C++ compilations.
    CmdArgs.push_back("-lkernel");
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }
    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
    // the default system libraries. Just mimic this for now.
    if (Args.hasArg(options::OPT_pg))
      CmdArgs.push_back("-lgcc_p");
    else
      CmdArgs.push_back("-lcompiler_rt");
    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lstdc++");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lstdc++");
      CmdArgs.push_back("--no-as-needed");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (Args.hasArg(options::OPT_pg)) {
      if (Args.hasArg(options::OPT_shared))
        CmdArgs.push_back("-lc");
      else {
        if (Args.hasArg(options::OPT_static)) {
          CmdArgs.push_back("--start-group");
          CmdArgs.push_back("-lc_p");
          CmdArgs.push_back("-lpthread_p");
          CmdArgs.push_back("--end-group");
        } else {
          CmdArgs.push_back("-lc_p");
        }
      }
      CmdArgs.push_back("-lgcc_p");
    } else {
      if (Args.hasArg(options::OPT_static)) {
        CmdArgs.push_back("--start-group");
        CmdArgs.push_back("-lc");
        CmdArgs.push_back("-lpthread");
        CmdArgs.push_back("--end-group");
      } else {
        CmdArgs.push_back("-lc");
      }
      CmdArgs.push_back("-lcompiler_rt");
    }

    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lstdc++");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lstdc++");
      CmdArgs.push_back("--no-as-needed");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
  }

  const char *Exec =
#ifdef LLVM_ON_WIN32
      Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld.gold"));
#else
      Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));
#endif

  C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
}

void PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  const toolchains::FreeBSD &ToolChain =
      static_cast<const toolchains::FreeBSD &>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  bool PS4Linker;
  StringRef LinkerOptName;
  if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
    LinkerOptName = A->getValue();
    if (LinkerOptName != "ps4" && LinkerOptName != "gold")
      D.Diag(diag::err_drv_unsupported_linker) << LinkerOptName;
  }

  if (LinkerOptName == "gold")
    PS4Linker = false;
  else if (LinkerOptName == "ps4")
    PS4Linker = true;
  else
    PS4Linker = !Args.hasArg(options::OPT_shared);

  if (PS4Linker)
    ConstructPS4LinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
  else
    ConstructGoldLinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
@


1.1.1.11.2.1
log
@Sync with HEAD
@
text
@d43 1
a43 1
#include "llvm/Support/ScopedPrinter.h"
a44 1
#include "llvm/Support/YAMLParser.h"
d56 1
a56 1
                                      std::vector<StringRef> &Features,
a98 8
          .Case("leon2", "-Av8")
          .Case("at697e", "-Av8")
          .Case("at697f", "-Av8")
          .Case("leon3", "-Av8")
          .Case("ut699", "-Av8")
          .Case("gr712rc", "-Av8")
          .Case("leon4", "-Av8")
          .Case("gr740", "-Av8")
d103 2
d116 2
d228 1
a228 2
                            const ArgList &Args, ArgStringList &CmdArgs,
                            const JobAction &JA) {
a235 8
    // If the current tool chain refers to an OpenMP offloading host, we should
    // ignore inputs that refer to OpenMP offloading devices - they will be
    // embedded according to a proper linker script.
    if (auto *IA = II.getAction())
      if (JA.isHostOffloading(Action::OFK_OpenMP) &&
          IA->isDeviceOffloading(Action::OFK_OpenMP))
        continue;

a268 125
/// Add OpenMP linker script arguments at the end of the argument list so that
/// the fat binary is built by embedding each of the device images into the
/// host. The linker script also defines a few symbols required by the code
/// generation so that the images can be easily retrieved at runtime by the
/// offloading library. This should be used only in tool chains that support
/// linker scripts.
static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args, ArgStringList &CmdArgs,
                                  const JobAction &JA) {

  // If this is not an OpenMP host toolchain, we don't need to do anything.
  if (!JA.isHostOffloading(Action::OFK_OpenMP))
    return;

  // Create temporary linker script. Keep it if save-temps is enabled.
  const char *LKS;
  SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
  if (C.getDriver().isSaveTempsEnabled()) {
    llvm::sys::path::replace_extension(Name, "lk");
    LKS = C.getArgs().MakeArgString(Name.c_str());
  } else {
    llvm::sys::path::replace_extension(Name, "");
    Name = C.getDriver().GetTemporaryPath(Name, "lk");
    LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
  }

  // Add linker script option to the command.
  CmdArgs.push_back("-T");
  CmdArgs.push_back(LKS);

  // Create a buffer to write the contents of the linker script.
  std::string LksBuffer;
  llvm::raw_string_ostream LksStream(LksBuffer);

  // Get the OpenMP offload tool chains so that we can extract the triple
  // associated with each device input.
  auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
  assert(OpenMPToolChains.first != OpenMPToolChains.second &&
         "No OpenMP toolchains??");

  // Track the input file name and device triple in order to build the script,
  // inserting binaries in the designated sections.
  SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;

  // Add commands to embed target binaries. We ensure that each section and
  // image is 16-byte aligned. This is not mandatory, but increases the
  // likelihood of data to be aligned with a cache block in several main host
  // machines.
  LksStream << "/*\n";
  LksStream << "       OpenMP Offload Linker Script\n";
  LksStream << " *** Automatically generated by Clang ***\n";
  LksStream << "*/\n";
  LksStream << "TARGET(binary)\n";
  auto DTC = OpenMPToolChains.first;
  for (auto &II : Inputs) {
    const Action *A = II.getAction();
    // Is this a device linking action?
    if (A && isa<LinkJobAction>(A) &&
        A->isDeviceOffloading(Action::OFK_OpenMP)) {
      assert(DTC != OpenMPToolChains.second &&
             "More device inputs than device toolchains??");
      InputBinaryInfo.push_back(std::make_pair(
          DTC->second->getTriple().normalize(), II.getFilename()));
      ++DTC;
      LksStream << "INPUT(" << II.getFilename() << ")\n";
    }
  }

  assert(DTC == OpenMPToolChains.second &&
         "Less device inputs than device toolchains??");

  LksStream << "SECTIONS\n";
  LksStream << "{\n";
  LksStream << "  .omp_offloading :\n";
  LksStream << "  ALIGN(0x10)\n";
  LksStream << "  {\n";

  for (auto &BI : InputBinaryInfo) {
    LksStream << "    . = ALIGN(0x10);\n";
    LksStream << "    PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
              << " = .);\n";
    LksStream << "    " << BI.second << "\n";
    LksStream << "    PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
              << " = .);\n";
  }

  LksStream << "  }\n";
  // Add commands to define host entries begin and end. We use 1-byte subalign
  // so that the linker does not add any padding and the elements in this
  // section form an array.
  LksStream << "  .omp_offloading.entries :\n";
  LksStream << "  ALIGN(0x10)\n";
  LksStream << "  SUBALIGN(0x01)\n";
  LksStream << "  {\n";
  LksStream << "    PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
  LksStream << "    *(.omp_offloading.entries)\n";
  LksStream << "    PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
  LksStream << "  }\n";
  LksStream << "}\n";
  LksStream << "INSERT BEFORE .data\n";
  LksStream.flush();

  // Dump the contents of the linker script if the user requested that. We
  // support this option to enable testing of behavior with -###.
  if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
    llvm::errs() << LksBuffer;

  // If this is a dry run, do not create the linker script file.
  if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
    return;

  // Open script file and write the contents.
  std::error_code EC;
  llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);

  if (EC) {
    C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
    return;
  }

  Lksf << LksBuffer;
}

a290 21
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
                           const ToolChain &RegularToolChain,
                           llvm::function_ref<void(const ToolChain &)> Work) {
  // Apply Work on the current/regular tool chain.
  Work(RegularToolChain);

  // Apply Work on all the offloading tool chains associated with the current
  // action.
  if (JA.isHostOffloading(Action::OFK_Cuda))
    Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
  else if (JA.isDeviceOffloading(Action::OFK_Cuda))
    Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());

  //
  // TODO: Add support for other offloading programming models here.
  //
}

d295 2
a296 1
                                    const InputInfoList &Inputs) const {
a297 1
  const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
a383 7
  // Add offload include arguments specific for CUDA.  This must happen before
  // we -I or -include anything else, because we must pick up the CUDA headers
  // from the particular CUDA installation, rather than from e.g.
  // /usr/local/include.
  if (JA.isOffloading(Action::OFK_Cuda))
    getToolChain().AddCudaIncludeArgs(Args, CmdArgs);

a388 25
  int YcIndex = -1, YuIndex = -1;
  {
    int AI = -1;
    const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
    const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
    for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
      // Walk the whole i_Group and skip non "-include" flags so that the index
      // here matches the index in the next loop below.
      ++AI;
      if (!A->getOption().matches(options::OPT_include))
        continue;
      if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0)
        YcIndex = AI;
      if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0)
        YuIndex = AI;
    }
  }
  if (isa<PrecompileJobAction>(JA) && YcIndex != -1) {
    Driver::InputList Inputs;
    D.BuildInputs(getToolChain(), C.getArgs(), Inputs);
    assert(Inputs.size() == 1 && "Need one input when building pch");
    CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") +
                                         Inputs[0].second->getValue()));
  }

a389 1
  int AI = -1;
d391 1
a391 40
    ++AI;

    if (getToolChain().getDriver().IsCLMode() &&
        A->getOption().matches(options::OPT_include)) {
      // In clang-cl mode, /Ycfoo.h means that all code up to a foo.h
      // include is compiled into foo.h, and everything after goes into
      // the .obj file. /Yufoo.h means that all includes prior to and including
      // foo.h are completely skipped and replaced with a use of the pch file
      // for foo.h.  (Each flag can have at most one value, multiple /Yc flags
      // just mean that the last one wins.)  If /Yc and /Yu are both present
      // and refer to the same file, /Yc wins.
      // Note that OPT__SLASH_FI gets mapped to OPT_include.
      // FIXME: The code here assumes that /Yc and /Yu refer to the same file.
      // cl.exe seems to support both flags with different values, but that
      // seems strange (which flag does /Fp now refer to?), so don't implement
      // that until someone needs it.
      int PchIndex = YcIndex != -1 ? YcIndex : YuIndex;
      if (PchIndex != -1) {
        if (isa<PrecompileJobAction>(JA)) {
          // When building the pch, skip all includes after the pch.
          assert(YcIndex != -1 && PchIndex == YcIndex);
          if (AI >= YcIndex)
            continue;
        } else {
          // When using the pch, skip all includes prior to the pch.
          if (AI < PchIndex) {
            A->claim();
            continue;
          }
          if (AI == PchIndex) {
            A->claim();
            CmdArgs.push_back("-include-pch");
            CmdArgs.push_back(
                Args.MakeArgString(D.GetClPchPath(C, A->getValue())));
            continue;
          }
        }
      }
    } else if (A->getOption().matches(options::OPT_include)) {
      // Handling of gcc-style gch precompiled headers.
a438 7
    } else if (A->getOption().matches(options::OPT_isystem_after)) {
      // Handling of paths which must come late.  These entries are handled by
      // the toolchain itself after the resource dir is inserted in the right
      // search order.
      // Do not claim the argument so that the use of the argument does not
      // silently go unnoticed on toolchains which do not honour the option.
      continue;
d488 4
a491 3
  // While adding the include arguments, we also attempt to retrieve the
  // arguments of related offloading toolchains or arguments that are specific
  // of an offloading programming model.
d494 4
a497 15
  if (types::isCXX(Inputs[0].getType()))
    forAllAssociatedToolChains(C, JA, getToolChain(),
                               [&Args, &CmdArgs](const ToolChain &TC) {
                                 TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
                               });

  // Add system include arguments for all targets but IAMCU.
  if (!IsIAMCU)
    forAllAssociatedToolChains(C, JA, getToolChain(),
                               [&Args, &CmdArgs](const ToolChain &TC) {
                                 TC.AddClangSystemIncludeArgs(Args, CmdArgs);
                               });
  else {
    // For IAMCU add special include arguments.
    getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs);
d499 9
d591 1
a591 1
                                std::vector<StringRef> &Features) {
d600 1
a600 1
                              std::vector<StringRef> &Features) {
d608 1
a608 1
                              std::vector<StringRef> &Features) {
d613 2
a614 2
    StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature);
    if (!FeatureName.empty())
d627 1
a627 1
                             std::vector<StringRef> &Features,
d640 1
a640 1
                            std::vector<StringRef> &Features,
d661 1
a661 1
  const llvm::Triple &Triple = TC.getEffectiveTriple();
a700 1
      ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI;
a726 1
      case llvm::Triple::MuslEABIHF:
a730 1
      case llvm::Triple::MuslEABI:
d740 1
a740 6
        if (Triple.isOSBinFormatMachO() &&
            Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
          ABI = FloatABI::Hard;
        else
          ABI = FloatABI::Soft;

d756 1
a756 2
                                 ArgStringList &CmdArgs,
                                 std::vector<StringRef> &Features,
d882 4
a897 23
  // Generate execute-only output (no data access to code sections).
  // Supported only on ARMv6T2 and ARMv7 and above.
  // Cannot be combined with -mno-movt or -mlong-calls
  if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
    if (A->getOption().matches(options::OPT_mexecute_only)) {
      if (getARMSubArchVersionNumber(Triple) < 7 &&
          llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
            D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
      else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
        D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
      // Long calls create constant pool entries and have not yet been fixed up
      // to play nicely with execute-only. Hence, they cannot be used in
      // execute-only code for now
      else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
        if (B->getOption().matches(options::OPT_mlong_calls))
          D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
      }

      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-execute-only");
    }
  }

a906 4
      // v8M Baseline follows on from v6M, so doesn't support unaligned memory
      // access either.
      else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
        D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
d957 1
a957 1
    } else if (Triple.isWatchABI()) {
a970 2
    case llvm::Triple::MuslEABI:
    case llvm::Triple::MuslEABIHF:
d1024 3
a1026 3
/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
/// arguments if they are provided, or to nullptr otherwise.
static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
d1052 2
a1053 1
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
d1115 1
a1115 2
  if (Triple.isAndroid()) {
    DefMips32CPU = "mips32";
a1116 1
  }
a1150 24
  if (ABIName.empty() &&
      (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
       Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
    ABIName = llvm::StringSwitch<const char *>(CPUName)
                  .Case("mips1", "o32")
                  .Case("mips2", "o32")
                  .Case("mips3", "n64")
                  .Case("mips4", "n64")
                  .Case("mips5", "n64")
                  .Case("mips32", "o32")
                  .Case("mips32r2", "o32")
                  .Case("mips32r3", "o32")
                  .Case("mips32r5", "o32")
                  .Case("mips32r6", "o32")
                  .Case("mips64", "n64")
                  .Case("mips64r2", "n64")
                  .Case("mips64r3", "n64")
                  .Case("mips64r5", "n64")
                  .Case("mips64r6", "n64")
                  .Case("octeon", "n64")
                  .Case("p5600", "o32")
                  .Default("");
  }

d1163 1
a1163 1
                  .Case("o32", DefMips32CPU)
d1225 1
a1225 1
                             std::vector<StringRef> &Features,
d1238 1
a1238 1
                                  std::vector<StringRef> &Features) {
d1289 2
a1290 3
  // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
  // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
  // nooddspreg.
a1302 3
  } else if (mips::isFP64ADefault(Triple, CPUName)) {
    Features.push_back(Args.MakeArgString("+fp64"));
    Features.push_back(Args.MakeArgString("+nooddspreg"));
a1361 13

  if (Arg *A = Args.getLastArg(options::OPT_mcompact_branches_EQ)) {
    StringRef Val = StringRef(A->getValue());
    if (mips::hasCompactBranches(CPUName)) {
      if (Val == "never" || Val == "always" || Val == "optimal") {
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back(Args.MakeArgString("-mips-compact-branches=" + Val));
      } else
        D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Val;
    } else
      D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName;
  }
a1410 1
        .Case("power9", "pwr9")
a1418 1
        .Case("pwr9", "pwr9")
d1430 1
a1430 1
                                 std::vector<StringRef> &Features) {
d1434 9
a1442 2
  if (FloatABI == ppc::FloatABI::Soft)
    Features.push_back("-hard-float");
d1557 4
a1560 6
static std::string getLanaiTargetCPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    return A->getValue();
  }
  return "";
}
d1562 1
a1562 3
sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
                                        const ArgList &Args) {
  sparc::FloatABI ABI = sparc::FloatABI::Invalid;
d1564 1
a1564 2
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
                          options::OPT_mfloat_abi_EQ)) {
d1566 1
a1566 14
      ABI = sparc::FloatABI::Soft;
    else if (A->getOption().matches(options::OPT_mhard_float))
      ABI = sparc::FloatABI::Hard;
    else {
      ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue())
                .Case("soft", sparc::FloatABI::Soft)
                .Case("hard", sparc::FloatABI::Hard)
                .Default(sparc::FloatABI::Invalid);
      if (ABI == sparc::FloatABI::Invalid &&
          !StringRef(A->getValue()).empty()) {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        ABI = sparc::FloatABI::Hard;
      }
    }
a1568 1
  // If unspecified, choose the default based on the platform.
d1570 7
a1576 32
  // default. GCC also supports a nonstandard soft-float ABI mode, also
  // implemented in LLVM. However as this is not standard we set the default
  // to be hard-float.
  if (ABI == sparc::FloatABI::Invalid) {
    ABI = sparc::FloatABI::Hard;
  }

  return ABI;
}

static void getSparcTargetFeatures(const Driver &D, const ArgList &Args,
                                 std::vector<StringRef> &Features) {
  sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
  if (FloatABI == sparc::FloatABI::Soft)
    Features.push_back("+soft-float");
}

void Clang::AddSparcTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  sparc::FloatABI FloatABI =
      sparc::getSparcFloatABI(getToolChain().getDriver(), Args);

  if (FloatABI == sparc::FloatABI::Soft) {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == sparc::FloatABI::Hard && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
a1579 6
void Clang::AddSystemZTargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  if (Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false))
    CmdArgs.push_back("-mbackchain");
}

d1587 1
a1587 1
                                     std::vector<StringRef> &Features) {
a1657 5
    // macosx10.12 drops support for all pre-Penryn Macs.
    // Simulators can still run on 10.11 though, like Xcode.
    if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
      return "penryn";
    // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
a1708 2
  Arg *A;

d1715 1
a1715 1
    return getAArch64TargetCPU(Args, A);
a1773 3
  case llvm::Triple::lanai:
    return getLanaiTargetCPU(Args);

a1786 18
static unsigned getLTOParallelism(const ArgList &Args, const Driver &D) {
  unsigned Parallelism = 0;
  Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
  if (LtoJobsArg &&
      StringRef(LtoJobsArg->getValue()).getAsInteger(10, Parallelism))
    D.Diag(diag::err_drv_invalid_int_value) << LtoJobsArg->getAsString(Args)
                                            << LtoJobsArg->getValue();
  return Parallelism;
}

// CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
// default.
static bool isUseSeparateSections(const llvm::Triple &Triple) {
  return Triple.getOS() == llvm::Triple::CloudABI ||
         Triple.getArch() == llvm::Triple::wasm32 ||
         Triple.getArch() == llvm::Triple::wasm64;
}

d1788 1
a1788 2
                          ArgStringList &CmdArgs, bool IsThinLTO,
                          const Driver &D) {
a1819 37

  if (unsigned Parallelism = getLTOParallelism(Args, D))
    CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") +
                                         llvm::to_string(Parallelism)));

  // If an explicit debugger tuning argument appeared, pass it along.
  if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
                               options::OPT_ggdbN_Group)) {
    if (A->getOption().matches(options::OPT_glldb))
      CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb");
    else if (A->getOption().matches(options::OPT_gsce))
      CmdArgs.push_back("-plugin-opt=-debugger-tune=sce");
    else
      CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb");
  }

  bool UseSeparateSections =
      isUseSeparateSections(ToolChain.getEffectiveTriple());

  if (Args.hasFlag(options::OPT_ffunction_sections,
                   options::OPT_fno_function_sections, UseSeparateSections)) {
    CmdArgs.push_back("-plugin-opt=-function-sections");
  }

  if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
                   UseSeparateSections)) {
    CmdArgs.push_back("-plugin-opt=-data-sections");
  }

  if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
    StringRef FName = A->getValue();
    if (!llvm::sys::fs::exists(FName))
      D.Diag(diag::err_drv_no_such_file) << FName;
    else
      CmdArgs.push_back(
          Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
  }
d1955 1
a1955 1
                                 std::vector<StringRef> &Features) {
a2047 7

  // Set flags to support MCU ABI.
  if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
    CmdArgs.push_back("-mstack-alignment=4");
  }
a2071 23
void Clang::AddLanaiTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPUName = A->getValue();

    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPUName));
  }
  if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
    StringRef Value = A->getValue();
    // Only support mregparm=4 to support old usage. Report error for all other
    // cases.
    int Mregparm;
    if (Value.getAsInteger(10, Mregparm)) {
      if (Mregparm != 4) {
        getToolChain().getDriver().Diag(
            diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
      }
    }
  }
}

d2084 1
a2084 1
                                  std::vector<StringRef> &Features) {
d2089 16
a2104 3
    StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
    if (!FeatureName.empty())
      Features.push_back(FeatureName);
d2116 1
a2116 1
                              std::vector<StringRef> &Features) {
d2119 6
a2124 2

  if (CPU == "generic") {
d2127 2
a2128 8
    unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
    if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
      return false;

    unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
    if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
      return false;
   }
d2139 1
a2139 1
                                std::vector<StringRef> &Features) {
d2143 11
a2153 4
  unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
  if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
      !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
      (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
d2162 1
a2162 1
                               std::vector<StringRef> &Features) {
d2174 1
a2174 1
                                     std::vector<StringRef> &Features) {
d2189 1
a2189 1
                                    std::vector<StringRef> &Features) {
d2191 1
a2191 1
  std::vector<StringRef> DecodedFeature;
d2200 1
a2200 1
                                     std::vector<StringRef> &Features) {
d2210 2
a2211 2
    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
                                             Args, Features);
d2219 3
a2221 3
  else if (success && Args.hasArg(options::OPT_arch))
    success = getAArch64MicroArchFeaturesFromMcpu(
        D, getAArch64TargetCPU(Args, A), Args, Features);
d2250 2
a2251 3
                                     std::vector<StringRef> &Features) {
  handleTargetFeaturesGroup(Args, Features,
                            options::OPT_m_hexagon_Features_Group);
d2253 16
a2268 5
  bool UseLongCalls = false;
  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
                               options::OPT_mno_long_calls)) {
    if (A->getOption().matches(options::OPT_mlong_calls))
      UseLongCalls = true;
d2271 2
a2272 1
  Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
d2276 1
a2276 1
                                         std::vector<StringRef> &Features) {
a2279 17
static void getAMDGPUTargetFeatures(const Driver &D, const ArgList &Args,
                                    std::vector<StringRef> &Features) {
  if (const Arg *dAbi = Args.getLastArg(options::OPT_mamdgpu_debugger_abi)) {
    StringRef value = dAbi->getValue();
    if (value == "1.0") {
      Features.push_back("+amdgpu-debugger-insert-nops");
      Features.push_back("+amdgpu-debugger-reserve-regs");
      Features.push_back("+amdgpu-debugger-emit-prologue");
    } else {
      D.Diag(diag::err_drv_clang_unsupported) << dAbi->getAsString(Args);
    }
  }

  handleTargetFeaturesGroup(
    Args, Features, options::OPT_m_amdgpu_Features_Group);
}

d2284 1
a2284 1
  std::vector<StringRef> Features;
d2299 1
a2299 1
    getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
a2324 9
  case llvm::Triple::sparc:
  case llvm::Triple::sparcel:
  case llvm::Triple::sparcv9:
    getSparcTargetFeatures(D, Args, Features);
    break;
  case llvm::Triple::r600:
  case llvm::Triple::amdgcn:
    getAMDGPUTargetFeatures(D, Args, Features);
    break;
d2330 1
a2330 1
    StringRef Name = Features[I];
d2332 1
a2332 1
    LastOpt[Name.drop_front(1)] = I;
d2337 2
a2338 2
    StringRef Name = Features[I];
    llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
d2345 1
a2345 1
    CmdArgs.push_back(Name.data());
d2404 5
a2408 3
    // Disable C++ EH by default on XCore and PS4.
    bool CXXExceptionsEnabled =
        Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
d2467 2
a2468 2
  for (const auto &AI : A->inputs())
    if (ContainsCompileAction(AI))
d2498 1
a2498 1
static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
d2503 1
a2503 1
    return codegenoptions::NoDebugInfo;
d2506 2
a2507 2
    return codegenoptions::DebugLineTablesOnly;
  return codegenoptions::LimitedDebugInfo;
d2523 1
a2523 1
                                    codegenoptions::DebugInfoKind DebugInfoKind,
d2527 1
a2527 1
  case codegenoptions::DebugLineTablesOnly:
d2530 1
a2530 1
  case codegenoptions::LimitedDebugInfo:
d2533 1
a2533 1
  case codegenoptions::FullDebugInfo:
a2572 21
  switch (C.getDefaultToolChain().getArch()) {
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    if (Arg *A = Args.getLastArg(options::OPT_mimplicit_it_EQ)) {
      StringRef Value = A->getValue();
      if (Value == "always" || Value == "never" || Value == "arm" ||
          Value == "thumb") {
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
      }
    }
    break;
  default:
    break;
  }

a2582 3

  bool UseRelaxRelocations = ENABLE_X86_RELAX_RELOCATIONS;
  const char *MipsTargetFeature = nullptr;
a2593 4
      if (C.getDefaultToolChain().getTriple().isOSBinFormatCOFF() &&
          Value == "-mbig-obj")
        continue; // LLVM handles bigobj automatically

d2621 1
a2621 20

        MipsTargetFeature = llvm::StringSwitch<const char *>(Value)
                                .Case("-mips1", "+mips1")
                                .Case("-mips2", "+mips2")
                                .Case("-mips3", "+mips3")
                                .Case("-mips4", "+mips4")
                                .Case("-mips5", "+mips5")
                                .Case("-mips32", "+mips32")
                                .Case("-mips32r2", "+mips32r2")
                                .Case("-mips32r3", "+mips32r3")
                                .Case("-mips32r5", "+mips32r5")
                                .Case("-mips32r6", "+mips32r6")
                                .Case("-mips64", "+mips64")
                                .Case("-mips64r2", "+mips64r2")
                                .Case("-mips64r3", "+mips64r3")
                                .Case("-mips64r5", "+mips64r5")
                                .Case("-mips64r6", "+mips64r6")
                                .Default(nullptr);
        if (MipsTargetFeature)
          continue;
a2637 6
      } else if (Value == "-mrelax-relocations=yes" ||
                 Value == "--mrelax-relocations=yes") {
        UseRelaxRelocations = true;
      } else if (Value == "-mrelax-relocations=no" ||
                 Value == "--mrelax-relocations=no") {
        UseRelaxRelocations = false;
d2650 3
a2652 3
          RenderDebugEnablingArgs(Args, CmdArgs,
                                  codegenoptions::LimitedDebugInfo,
                                  DwarfVersion, llvm::DebuggerKind::Default);
a2656 21
      } else if (Value == "-defsym") {
          if (A->getNumValues() != 2) {
            D.Diag(diag::err_drv_defsym_invalid_format) << Value;
            break;
          }
          const char *S = A->getValue(1);
          auto Pair = StringRef(S).split('=');
          auto Sym = Pair.first;
          auto SVal = Pair.second;

          if (Sym.empty() || SVal.empty()) {
            D.Diag(diag::err_drv_defsym_invalid_format) << S;
            break;
          }
          int64_t IVal;
          if (SVal.getAsInteger(0, IVal)) {
            D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
            break;
          }
          CmdArgs.push_back(Value.data());
          TakeNextArg = true;
a2668 6
  if (UseRelaxRelocations)
    CmdArgs.push_back("--mrelax-relocations");
  if (MipsTargetFeature != nullptr) {
    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back(MipsTargetFeature);
  }
d2679 49
d2734 2
a2735 2
  switch (TC.getDriver().getOpenMPRuntime(Args)) {
  case Driver::OMPRT_OMP:
d2738 1
a2738 1
  case Driver::OMPRT_GOMP:
d2741 1
a2741 1
  case Driver::OMPRT_IOMP5:
d2744 1
a2744 1
  case Driver::OMPRT_Unknown:
d2752 2
a2753 2
                                bool IsShared, bool IsWhole) {
  // Wrap any static runtimes that must be forced into executable in
d2755 1
a2755 1
  if (IsWhole) CmdArgs.push_back("-whole-archive");
d2757 1
a2757 1
  if (IsWhole) CmdArgs.push_back("-no-whole-archive");
d2778 2
a2779 5
  // There's no libpthread or librt on RTEMS.
  if (TC.getTriple().getOS() != llvm::Triple::RTEMS) {
    CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lrt");
  }
d2781 2
a2782 3
  // There's no libdl on FreeBSD or RTEMS.
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
      TC.getTriple().getOS() != llvm::Triple::RTEMS)
d2790 1
a2790 3
                         SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
                         SmallVectorImpl<StringRef> &HelperStaticRuntimes,
                         SmallVectorImpl<StringRef> &RequiredSymbols) {
a2795 3
  // The stats_client library is also statically linked into DSOs.
  if (SanArgs.needsStatsRt())
    StaticRuntimes.push_back("stats_client");
d2834 1
a2834 1
  if (SanArgs.needsCfiDiagRt()) {
a2835 9
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("ubsan_standalone_cxx");
  }
  if (SanArgs.needsStatsRt()) {
    NonWholeStaticRuntimes.push_back("stats");
    RequiredSymbols.push_back("__sanitizer_stats_register");
  }
  if (SanArgs.needsEsanRt())
    StaticRuntimes.push_back("esan");
d2843 1
a2843 1
      NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
d2845 1
a2845 2
                           NonWholeStaticRuntimes, HelperStaticRuntimes,
                           RequiredSymbols);
d2847 1
a2847 1
    addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false);
d2849 1
a2849 1
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
d2852 1
a2852 5
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
    AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
  }
  for (auto RT : NonWholeStaticRuntimes) {
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false);
a2854 4
  for (auto S : RequiredSymbols) {
    CmdArgs.push_back("-u");
    CmdArgs.push_back(Args.MakeArgString(S));
  }
a2858 5

  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
  if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
    CmdArgs.push_back("-export-dynamic-symbol=__cfi_check");

a2861 27
static bool addXRayRuntime(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (Args.hasFlag(options::OPT_fxray_instrument,
                   options::OPT_fnoxray_instrument, false)) {
    CmdArgs.push_back("-whole-archive");
    CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false));
    CmdArgs.push_back("-no-whole-archive");
    return true;
  }
  return false;
}

static void linkXRayRuntimeDeps(const ToolChain &TC, const ArgList &Args,
                                ArgStringList &CmdArgs) {
  CmdArgs.push_back("--no-as-needed");
  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-lm");
  CmdArgs.push_back("-latomic");
  if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
    CmdArgs.push_back("-lc++");
  else
    CmdArgs.push_back("-lstdc++");
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
    CmdArgs.push_back("-ldl");
}

d2870 2
a2871 14
static bool mustUseFramePointerForTarget(const llvm::Triple &Triple) {
  switch (Triple.getArch()){
  default:
    return false;
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    // ARM Darwin targets require a frame pointer to be always present to aid
    // offline debugging via backtraces.
    return Triple.isOSDarwin();
  }
}

static bool useFramePointerForTargetByDefault(const ArgList &Args,
                                              const llvm::Triple &Triple) {
d2883 1
a2883 1
  if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
a2902 2
    case llvm::Triple::x86_64:
      return Triple.isOSBinFormatMachO();
d2921 1
a2921 3
    return A->getOption().matches(options::OPT_fno_omit_frame_pointer) ||
           mustUseFramePointerForTarget(Triple);

d2925 1
a2925 1
  return useFramePointerForTargetByDefault(Args, Triple);
d2932 1
a2932 3
    return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer) ||
           mustUseFramePointerForTarget(Triple);

d2939 1
a2939 1
  return useFramePointerForTargetByDefault(Args, Triple);
d3039 13
d3095 41
a3135 5
static Arg *getLastProfileUseArg(const ArgList &Args) {
  auto *ProfileUseArg = Args.getLastArg(
      options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
      options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
      options::OPT_fno_profile_instr_use);
d3137 3
a3139 5
  if (ProfileUseArg &&
      ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
    ProfileUseArg = nullptr;

  return ProfileUseArg;
a3144 8

  auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate,
                                         options::OPT_fprofile_generate_EQ,
                                         options::OPT_fno_profile_generate);
  if (PGOGenerateArg &&
      PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
    PGOGenerateArg = nullptr;

d3147 2
a3148 1
      options::OPT_fprofile_instr_generate_EQ,
d3155 7
a3161 9
  if (PGOGenerateArg && ProfileGenerateArg)
    D.Diag(diag::err_drv_argument_not_allowed_with)
        << PGOGenerateArg->getSpelling() << ProfileGenerateArg->getSpelling();

  auto *ProfileUseArg = getLastProfileUseArg(Args);

  if (PGOGenerateArg && ProfileUseArg)
    D.Diag(diag::err_drv_argument_not_allowed_with)
        << ProfileUseArg->getSpelling() << PGOGenerateArg->getSpelling();
d3170 5
a3174 12
      CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instrument-path=") +
                                           ProfileGenerateArg->getValue()));
    // The default is to use Clang Instrumentation.
    CmdArgs.push_back("-fprofile-instrument=clang");
  }

  if (PGOGenerateArg) {
    CmdArgs.push_back("-fprofile-instrument=llvm");
    if (PGOGenerateArg->getOption().matches(
            options::OPT_fprofile_generate_EQ)) {
      SmallString<128> Path(PGOGenerateArg->getValue());
      llvm::sys::path::append(Path, "default_%m.profraw");
d3176 3
a3178 2
          Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path));
    }
d3183 1
a3183 2
      CmdArgs.push_back(Args.MakeArgString(
          Twine("-fprofile-instrument-use-path=") + ProfileUseArg->getValue()));
d3193 1
a3193 1
          Args.MakeArgString(Twine("-fprofile-instrument-use-path=") + Path));
d3219 7
a3225 7
      CmdArgs.push_back("-coverage-notes-file");
      SmallString<128> OutputFilename;
      if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
        OutputFilename = FinalOutput->getValue();
      else
        OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
      SmallString<128> CoverageFilename = OutputFilename;
a3232 1
      llvm::sys::path::replace_extension(CoverageFilename, "gcno");
a3233 15

      // Leave -fprofile-dir= an unused argument unless .gcda emission is
      // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
      // the flag used. There is no -fno-profile-dir, so the user has no
      // targeted way to suppress the warning.
      if (Args.hasArg(options::OPT_fprofile_arcs) ||
          Args.hasArg(options::OPT_coverage)) {
        CmdArgs.push_back("-coverage-data-file");
        if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) {
          CoverageFilename = FProfileDir->getValue();
          llvm::sys::path::append(CoverageFilename, OutputFilename);
        }
        llvm::sys::path::replace_extension(CoverageFilename, "gcda");
        CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
      }
d3260 4
a3263 4
ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
  const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple();
  const llvm::Triple &Triple = ToolChain.getTriple();

d3267 2
a3268 1
  if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static))
d3276 2
a3277 2
  if (Triple.isAndroid()) {
    switch (Triple.getArch()) {
d3302 1
a3302 1
  if (Triple.getOS() == llvm::Triple::OpenBSD) {
a3330 11
  if (Triple.isOSWindows() && LastPICArg &&
      LastPICArg ==
          Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
                          options::OPT_fPIE, options::OPT_fpie)) {
    ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
        << LastPICArg->getSpelling() << Triple.str();
    if (Triple.getArch() == llvm::Triple::x86_64)
      return std::make_tuple(llvm::Reloc::PIC_, 2U, false);
    return std::make_tuple(llvm::Reloc::Static, 0U, false);
  }

d3345 1
a3345 1
        if (EffectiveTriple.isPS4CPU()) {
d3361 1
a3361 1
  if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU()))
d3366 2
a3367 3
  if (KernelOrKext &&
      ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
       !EffectiveTriple.isWatchOS()))
d3373 1
a3373 1
    if (!Triple.isOSDarwin())
d3375 1
a3375 1
          << A->getSpelling() << Triple.str();
d3384 1
a3384 1
    return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false);
a3386 33
  bool EmbeddedPISupported;
  switch (Triple.getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
      EmbeddedPISupported = true;
      break;
    default:
      EmbeddedPISupported = false;
      break;
  }

  bool ROPI = false, RWPI = false;
  Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi);
  if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) {
    if (!EmbeddedPISupported)
      ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
          << LastROPIArg->getSpelling() << Triple.str();
    ROPI = true;
  }
  Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi);
  if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) {
    if (!EmbeddedPISupported)
      ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
          << LastRWPIArg->getSpelling() << Triple.str();
    RWPI = true;
  }

  // ROPI and RWPI are not comaptible with PIC or PIE.
  if ((ROPI || RWPI) && (PIC || PIE))
    ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic);

d3388 1
a3388 9
    return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE);

  llvm::Reloc::Model RelocM = llvm::Reloc::Static;
  if (ROPI && RWPI)
    RelocM = llvm::Reloc::ROPI_RWPI;
  else if (ROPI)
    RelocM = llvm::Reloc::ROPI;
  else if (RWPI)
    RelocM = llvm::Reloc::RWPI;
d3390 1
a3390 1
  return std::make_tuple(RelocM, 0U, false);
d3395 2
a3402 6
  case llvm::Reloc::ROPI:
    return "ropi";
  case llvm::Reloc::RWPI:
    return "rwpi";
  case llvm::Reloc::ROPI_RWPI:
    return "ropi-rwpi";
d3412 2
a3413 1
  std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args);
a3418 59
void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
                                    StringRef Target, const InputInfo &Output,
                                    const InputInfo &Input, const ArgList &Args) const {
  // If this is a dry run, do not create the compilation database file.
  if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
    return;

  using llvm::yaml::escape;
  const Driver &D = getToolChain().getDriver();

  if (!CompilationDatabase) {
    std::error_code EC;
    auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text);
    if (EC) {
      D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
                                                       << EC.message();
      return;
    }
    CompilationDatabase = std::move(File);
  }
  auto &CDB = *CompilationDatabase;
  SmallString<128> Buf;
  if (llvm::sys::fs::current_path(Buf))
    Buf = ".";
  CDB << "{ \"directory\": \"" << escape(Buf) << "\"";
  CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\"";
  CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
  CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\"";
  Buf = "-x";
  Buf += types::getTypeName(Input.getType());
  CDB << ", \"" << escape(Buf) << "\"";
  if (!D.SysRoot.empty() && !Args.hasArg(options::OPT__sysroot_EQ)) {
    Buf = "--sysroot=";
    Buf += D.SysRoot;
    CDB << ", \"" << escape(Buf) << "\"";
  }
  CDB << ", \"" << escape(Input.getFilename()) << "\"";
  for (auto &A: Args) {
    auto &O = A->getOption();
    // Skip language selection, which is positional.
    if (O.getID() == options::OPT_x)
      continue;
    // Skip writing dependency output and the compilation database itself.
    if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group)
      continue;
    // Skip inputs.
    if (O.getKind() == Option::InputClass)
      continue;
    // All other arguments are quoted and appended.
    ArgStringList ASL;
    A->render(Args, ASL);
    for (auto &it: ASL)
      CDB << ", \"" << escape(it) << "\"";
  }
  Buf = "--target=";
  Buf += Target;
  CDB << ", \"" << escape(Buf) << "\"]},\n";
}

d3422 2
a3423 2
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
  const std::string &TripleStr = Triple.getTriple();
a3429 13
  // Check number of inputs for sanity. We need at least one input.
  assert(Inputs.size() >= 1 && "Must have at least one input.");
  const InputInfo &Input = Inputs[0];
  // CUDA compilation may have multiple inputs (source file + results of
  // device-side compilations). OpenMP device jobs also take the host IR as a
  // second input. All other jobs are expected to have exactly one
  // input.
  bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
  bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
  assert((IsCuda || (IsOpenMPDevice && Inputs.size() == 2) ||
          Inputs.size() == 1) &&
         "Unable to handle multiple inputs.");

a3434 1
  bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
d3436 8
a3443 13
  // Adjust IsWindowsXYZ for CUDA compilations.  Even when compiling in device
  // mode (i.e., getToolchain().getTriple() is NVPTX, not Windows), we need to
  // pass Windows-specific flags to cc1.
  if (IsCuda) {
    const llvm::Triple *AuxTriple = getToolChain().getAuxTriple();
    IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
    IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment();
    IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment();
  }

  // C++ is not supported for IAMCU.
  if (IsIAMCU && types::isCXX(Input.getType()))
    D.Diag(diag::err_drv_clang_unsupported) << "C++ for IAMCU";
d3454 1
a3454 5
  if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) {
    DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args);
    Args.ClaimAllArgs(options::OPT_MJ);
  }

d3456 11
a3466 12
    // We have to pass the triple of the host if compiling for a CUDA device and
    // vice-versa.
    std::string NormalizedTriple;
    if (JA.isDeviceOffloading(Action::OFK_Cuda))
      NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>()
                             ->getTriple()
                             .normalize();
    else
      NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Cuda>()
                             ->getTriple()
                             .normalize();

d3468 3
a3470 1
    CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
a3517 2
    else if (JA.getType() == types::TY_ModuleFile)
      CmdArgs.push_back("-emit-module-interface");
a3568 11
  // Embed-bitcode option.
  if (C.getDriver().embedBitcodeInObject() &&
      (isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
    // Add flags implied by -fembed-bitcode.
    Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
    // Disable all llvm IR level optimizations.
    CmdArgs.push_back("-disable-llvm-passes");
  }
  if (C.getDriver().embedBitcodeMarkerOnly())
    CmdArgs.push_back("-fembed-bitcode=marker");

a3577 2
  // Discard LLVM value names in -asserts builds.
  CmdArgs.push_back("-discard-value-names");
a3601 1
      CmdArgs.push_back("-analyzer-checker=apiModeling");
d3603 2
a3604 11
    if (!IsWindowsMSVC) {
      CmdArgs.push_back("-analyzer-checker=unix");
    } else {
      // Enable "unix" checkers that also work on Windows.
      CmdArgs.push_back("-analyzer-checker=unix.API");
      CmdArgs.push_back("-analyzer-checker=unix.Malloc");
      CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof");
      CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator");
      CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg");
      CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
    }
d3659 1
a3659 1
      ParsePICArgs(getToolChain(), Args);
a3661 7

  if ((RelocationModel == llvm::Reloc::ROPI ||
       RelocationModel == llvm::Reloc::ROPI_RWPI) &&
      types::isCXX(Input.getType()) &&
      !Args.hasArg(options::OPT_fallow_unsupported))
    D.Diag(diag::err_drv_ropi_incompatible_with_cxx);

d3669 4
a3672 2
    if (IsPIE)
      CmdArgs.push_back("-pic-is-pie");
d3698 3
a3700 8
      StringRef Map = A->getValue();
      if (!llvm::sys::fs::exists(Map)) {
        D.Diag(diag::err_drv_no_such_file) << Map;
      } else {
        CmdArgs.push_back("-frewrite-map-file");
        CmdArgs.push_back(A->getValue());
        A->claim();
      }
a3710 8
  if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
                    true))
    CmdArgs.push_back("-fno-jump-tables");

  if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
                    options::OPT_fno_preserve_as_comments, true))
    CmdArgs.push_back("-fno-preserve-as-comments");

d3730 1
a3730 1
    CmdArgs.push_back("-fdefault-calling-conv=stdcall");
a3754 3
  if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return,
                    true))
    CmdArgs.push_back("-fno-strict-return");
a3868 13
  if (!TrappingMath)
    CmdArgs.push_back("-fno-trapping-math");


  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fdenormal_fp_math_EQ))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations)
      Args.AddLastArg(CmdArgs, options::OPT_fdenormal_fp_math_EQ);

d3926 3
a3928 5
  // Enable -mconstructor-aliases except on darwin, where we have to work around
  // a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
  // aliases aren't supported.
  if (!getToolChain().getTriple().isOSDarwin() &&
      !getToolChain().getTriple().isNVPTX())
a3940 6
  if (Args.hasFlag(options::OPT_mpie_copy_relocations,
                   options::OPT_mno_pie_copy_relocations,
                   false)) {
    CmdArgs.push_back("-mpie-copy-relocations");
  }

a4020 4
  case llvm::Triple::systemz:
    AddSystemZTargetArgs(Args, CmdArgs);
    break;

a4025 4
  case llvm::Triple::lanai:
    AddLanaiTargetArgs(Args, CmdArgs);
    break;

d4048 2
a4049 1
  codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
a4052 1
  types::ID InputType = Input.getType();
d4054 1
a4054 1
    AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
d4067 1
a4094 4
  bool splitDwarfInlining =
      Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
                   options::OPT_fno_split_dwarf_inlining, true);

d4104 3
a4106 14
      // This gets a bit more complicated if you've disabled inline info in the
      // skeleton CUs (splitDwarfInlining) - then there's value in composing
      // split-dwarf and line-tables-only, so let those compose naturally in
      // that case.
      // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
      if (SplitDwarfArg) {
        if (A->getIndex() > SplitDwarfArg->getIndex()) {
          if (DebugInfoKind == codegenoptions::NoDebugInfo ||
              (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
               splitDwarfInlining))
            SplitDwarfArg = nullptr;
        } else if (splitDwarfInlining)
          DebugInfoKind = codegenoptions::NoDebugInfo;
      }
d4109 1
a4109 1
      DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4128 2
a4129 2
  // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
  // argument parsing.
d4134 1
a4134 1
             DebugInfoKind != codegenoptions::NoDebugInfo) {
d4141 1
a4141 5
  // Column info is included by default for everything except PS4 and CodeView.
  // Clang doesn't track end columns, just starting columns, which, in theory,
  // is fine for CodeView (and PDB).  In practice, however, the Microsoft
  // debuggers don't handle missing end columns well, so it's better not to
  // include any column info.
d4143 1
a4143 1
                   /*Default=*/ !IsPS4CPU && !(IsWindowsMSVC && EmitCodeView)))
d4147 2
a4148 4
  // If -gline-tables-only is the last option it wins.
  if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
      Args.hasArg(options::OPT_gmodules)) {
    DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4157 1
a4157 4
    if (!splitDwarfInlining)
      CmdArgs.push_back("-fno-split-dwarf-inlining");
    if (DebugInfoKind == codegenoptions::NoDebugInfo)
      DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4170 2
a4171 2
  if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
    DebugInfoKind = codegenoptions::FullDebugInfo;
d4195 5
a4199 1
  bool UseSeparateSections = isUseSeparateSections(Triple);
a4216 26
  if (Args.hasFlag(options::OPT_fxray_instrument,
                   options::OPT_fnoxray_instrument, false)) {
    const char *const XRayInstrumentOption = "-fxray-instrument";
    if (Triple.getOS() == llvm::Triple::Linux)
      switch (Triple.getArch()) {
      case llvm::Triple::x86_64:
      case llvm::Triple::arm:
      case llvm::Triple::aarch64:
        // Supported.
        break;
      default:
        D.Diag(diag::err_drv_clang_unsupported)
            << (std::string(XRayInstrumentOption) + " on " + Triple.str());
      }
    else
      D.Diag(diag::err_drv_clang_unsupported)
          << (std::string(XRayInstrumentOption) + " on non-Linux target OS");
    CmdArgs.push_back(XRayInstrumentOption);
    if (const Arg *A =
            Args.getLastArg(options::OPT_fxray_instruction_threshold_,
                            options::OPT_fxray_instruction_threshold_EQ)) {
      CmdArgs.push_back("-fxray-instruction-threshold");
      CmdArgs.push_back(A->getValue());
    }
  }

d4315 2
a4316 1
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);
a4343 1

a4547 1
  bool IsHosted = true;
d4549 1
a4549 1
      KernelOrKext) {
a4550 2
    IsHosted = false;
  }
d4558 1
a4558 1
  bool EmulatedTLSDefault = Triple.isAndroid() || Triple.isWindowsCygwinEnvironment();
d4570 1
a4570 2
  // Forward flags for OpenMP. We don't do this if the current action is an
  // device offloading action other than OpenMP.
d4572 4
a4575 6
                   options::OPT_fno_openmp, false) &&
      (JA.isDeviceOffloading(Action::OFK_None) ||
       JA.isDeviceOffloading(Action::OFK_OpenMP))) {
    switch (getToolChain().getDriver().getOpenMPRuntime(Args)) {
    case Driver::OMPRT_OMP:
    case Driver::OMPRT_IOMP5:
a4584 1
      Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
a4594 1
  }
d4663 9
a4671 4
  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                               options::OPT_fstack_protector_all,
                               options::OPT_fstack_protector_strong,
                               options::OPT_fstack_protector)) {
a4682 4
    // Only use a default stack protector on Darwin in case -ffreestanding
    // is not specified.
    if (Triple.isOSDarwin() && !IsHosted)
      StackProtectorLevel = 0;
a4751 40
  // Forward -cl options to -cc1
  if (Args.getLastArg(options::OPT_cl_opt_disable)) {
    CmdArgs.push_back("-cl-opt-disable");
  }
  if (Args.getLastArg(options::OPT_cl_strict_aliasing)) {
    CmdArgs.push_back("-cl-strict-aliasing");
  }
  if (Args.getLastArg(options::OPT_cl_single_precision_constant)) {
    CmdArgs.push_back("-cl-single-precision-constant");
  }
  if (Args.getLastArg(options::OPT_cl_finite_math_only)) {
    CmdArgs.push_back("-cl-finite-math-only");
  }
  if (Args.getLastArg(options::OPT_cl_kernel_arg_info)) {
    CmdArgs.push_back("-cl-kernel-arg-info");
  }
  if (Args.getLastArg(options::OPT_cl_unsafe_math_optimizations)) {
    CmdArgs.push_back("-cl-unsafe-math-optimizations");
  }
  if (Args.getLastArg(options::OPT_cl_fast_relaxed_math)) {
    CmdArgs.push_back("-cl-fast-relaxed-math");
  }
  if (Args.getLastArg(options::OPT_cl_mad_enable)) {
    CmdArgs.push_back("-cl-mad-enable");
  }
  if (Args.getLastArg(options::OPT_cl_no_signed_zeros)) {
    CmdArgs.push_back("-cl-no-signed-zeros");
  }
  if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
    std::string CLStdStr = "-cl-std=";
    CLStdStr += A->getValue();
    CmdArgs.push_back(Args.MakeArgString(CLStdStr));
  }
  if (Args.getLastArg(options::OPT_cl_denorms_are_zero)) {
    CmdArgs.push_back("-cl-denorms-are-zero");
  }
  if (Args.getLastArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt)) {
    CmdArgs.push_back("-cl-fp32-correctly-rounded-divide-sqrt");
  }

a4805 6
  if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
                   false) &&
      types::isCXX(InputType)) {
    CmdArgs.push_back("-fcoroutines-ts");
  }

d4809 1
a4809 1
  bool HaveClangModules = false;
d4815 1
a4815 1
      HaveClangModules = true;
a4818 6
  bool HaveAnyModules = HaveClangModules;
  if (Args.hasArg(options::OPT_fmodules_ts)) {
    CmdArgs.push_back("-fmodules-ts");
    HaveAnyModules = true;
  }

d4820 1
a4820 1
  // this is enabled if we are using Clang's flavor of precompiled modules.
d4822 1
a4822 1
                   options::OPT_fno_implicit_module_maps, HaveClangModules)) {
d4842 24
a4865 9
                    options::OPT_fno_implicit_modules, HaveClangModules)) {
    if (HaveAnyModules)
      CmdArgs.push_back("-fno-implicit-modules");
  } else if (HaveAnyModules) {
    // -fmodule-cache-path specifies where our implicitly-built module files
    // should be written.
    SmallString<128> Path;
    if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
      Path = A->getValue();
a4883 33
  if (HaveAnyModules) {
    // -fprebuilt-module-path specifies where to load the prebuilt module files.
    for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path))
      CmdArgs.push_back(Args.MakeArgString(
          std::string("-fprebuilt-module-path=") + A->getValue()));
  }
      
  // -fmodule-name specifies the module that is currently being built (or
  // used for header checking by -fmodule-maps).
  Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);

  // -fmodule-map-file can be used to specify files containing module
  // definitions.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);

  // -fbuiltin-module-map can be used to load the clang
  // builtin headers modulemap file.
  if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
    SmallString<128> BuiltinModuleMap(getToolChain().getDriver().ResourceDir);
    llvm::sys::path::append(BuiltinModuleMap, "include");
    llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
    if (llvm::sys::fs::exists(BuiltinModuleMap)) {
      CmdArgs.push_back(Args.MakeArgString("-fmodule-map-file=" +
                                           BuiltinModuleMap));
    }
  }

  // -fmodule-file can be used to specify files containing precompiled modules.
  if (HaveAnyModules)
    Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
  else
    Args.ClaimAllArgs(options::OPT_fmodule_file);

d4886 1
a4886 1
  if (HaveClangModules && C.isForDiagnostics()) {
d4897 1
a4897 1
  if (HaveClangModules)
d4915 3
a4917 5
    CmdArgs.push_back(
        Args.MakeArgString("-fbuild-session-timestamp=" +
                           Twine((uint64_t)Status.getLastModificationTime()
                                     .time_since_epoch()
                                     .count())));
a4929 1
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
d4996 3
a4998 2
  VersionTuple MSVT =
      getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args);
d5005 4
a5008 19
    StringRef LanguageStandard;
    if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
      LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
                             .Case("c++14", "-std=c++14")
                             .Case("c++latest", "-std=c++1z")
                             .Default("");
      if (LanguageStandard.empty())
        D.Diag(clang::diag::warn_drv_unused_argument)
            << StdArg->getAsString(Args);
    }

    if (LanguageStandard.empty()) {
      if (IsMSVC2015Compatible)
        LanguageStandard = "-std=c++14";
      else
        LanguageStandard = "-std=c++11";
    }

    CmdArgs.push_back(LanguageStandard.data());
d5049 2
a5050 7
  if (Arg* InlineArg = Args.getLastArg(options::OPT_finline_functions,
                                       options::OPT_finline_hint_functions,
                                       options::OPT_fno_inline_functions))
    InlineArg->render(Args, CmdArgs);

  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
                  options::OPT_fno_experimental_new_pass_manager);
d5055 1
a5055 1
  // legacy is the default. Except for deployment target of 10.5,
d5117 16
d5139 3
d5159 1
a5159 2
  if (Args.hasArg(options::OPT_fsjlj_exceptions) ||
      getToolChain().UseSjLjExceptions(Args))
a5166 7
  // -frelaxed-template-template-args is off by default, as it is a severe
  // breaking change until a corresponding change to template partial ordering
  // is provided.
  if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
                   options::OPT_fno_relaxed_template_template_args, false))
    CmdArgs.push_back("-frelaxed-template-template-args");

a5172 18
  // -faligned-allocation is on by default in C++17 onwards and otherwise off
  // by default.
  if (Arg *A = Args.getLastArg(options::OPT_faligned_allocation,
                               options::OPT_fno_aligned_allocation,
                               options::OPT_faligned_new_EQ)) {
    if (A->getOption().matches(options::OPT_fno_aligned_allocation))
      CmdArgs.push_back("-fno-aligned-allocation");
    else
      CmdArgs.push_back("-faligned-allocation");
  }

  // The default new alignment can be specified using a dedicated option or via
  // a GCC-compatible option that also turns on aligned allocation.
  if (Arg *A = Args.getLastArg(options::OPT_fnew_alignment_EQ,
                               options::OPT_faligned_new_EQ))
    CmdArgs.push_back(
        Args.MakeArgString(Twine("-fnew-alignment=") + A->getValue()));

d5240 1
a5240 1
    if (!value.equals_lower("utf-8"))
d5248 1
a5248 1
    if (!value.equals_lower("utf-8"))
a5273 4
  if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
                   options::OPT_fno_diagnostics_show_hotness, false))
    CmdArgs.push_back("-fdiagnostics-show-hotness");

d5289 7
a5295 6
  // Color diagnostics are parsed by the driver directly from argv
  // and later re-parsed to construct this job; claim any possible
  // color diagnostic here to avoid warn_drv_unused_argument and
  // diagnose bad OPT_fdiagnostics_color_EQ values.
  for (Arg *A : Args) {
    const Option &O = A->getOption();
d5302 18
a5319 3
    if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
      StringRef Value(A->getValue());
      if (Value != "always" && Value != "never" && Value != "auto")
d5321 1
a5321 1
              << ("-fdiagnostics-color=" + Value).str();
a5322 1
    A->claim();
d5324 2
a5325 1
  if (D.getDiags().getDiagnosticOptions().ShowColors)
a5334 3
  if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
    CmdArgs.push_back("-fdiagnostics-absolute-paths");

a5378 4
  if (Arg *A = Args.getLastArg(
          options::OPT_fsanitize_undefined_strip_path_components_EQ))
    A->render(Args, CmdArgs);

a5407 34
  if (Args.hasFlag(options::OPT_fsave_optimization_record,
                   options::OPT_fno_save_optimization_record, false)) {
    CmdArgs.push_back("-opt-record-file");

    const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
    if (A) {
      CmdArgs.push_back(A->getValue());
    } else {
      SmallString<128> F;
      if (Output.isFilename() && (Args.hasArg(options::OPT_c) ||
                                  Args.hasArg(options::OPT_S))) {
        F = Output.getFilename();
      } else {
        // Use the input filename.
        F = llvm::sys::path::stem(Input.getBaseInput());

        // If we're compiling for an offload architecture (i.e. a CUDA device),
        // we need to make the file name for the device compilation different
        // from the host compilation.
        if (!JA.isDeviceOffloading(Action::OFK_None) &&
            !JA.isDeviceOffloading(Action::OFK_Host)) {
          llvm::sys::path::replace_extension(F, "");
          F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
                                                   Triple.normalize());
          F += "-";
          F += JA.getOffloadingArch();
        }
      }

      llvm::sys::path::replace_extension(F, "opt.yaml");
      CmdArgs.push_back(Args.MakeArgString(F));
    }
  }

d5410 1
a5410 1
// FIXME: Now that PR4941 has been fixed this can be enabled.
d5428 1
a5428 1
      (C.isForDiagnostics() && !HaveAnyModules))
a5463 27
  // Setup statistics file output.
  if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) {
    StringRef SaveStats = A->getValue();

    SmallString<128> StatsFile;
    bool DoSaveStats = false;
    if (SaveStats == "obj") {
      if (Output.isFilename()) {
        StatsFile.assign(Output.getFilename());
        llvm::sys::path::remove_filename(StatsFile);
      }
      DoSaveStats = true;
    } else if (SaveStats == "cwd") {
      DoSaveStats = true;
    } else {
      D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
    }

    if (DoSaveStats) {
      StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
      llvm::sys::path::append(StatsFile, BaseName);
      llvm::sys::path::replace_extension(StatsFile, "stats");
      CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") +
                                           StatsFile));
    }
  }

d5471 1
a5471 2
    // it and developers have been trained to spell it with -mllvm. Both
    // spellings are now deprecated and should be removed.
d5474 1
a5474 1
    } else {
a5475 1
    }
d5481 1
a5481 7
  // When -fembed-bitcode is enabled, optimized bitcode is emitted because it
  // has slightly different breakdown between stages.
  // FIXME: -fembed-bitcode -save-temps will save optimized bitcode instead of
  // pristine IR generated by the frontend. Ideally, a new compile action should
  // be added so both IR can be captured.
  if (C.getDriver().isSaveTempsEnabled() &&
      !C.getDriver().embedBitcodeInObject() && isa<CompileJobAction>(JA))
a5542 41
  // OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
  // to specify the result of the compile phase on the host, so the meaningful
  // device declarations can be identified. Also, -fopenmp-is-device is passed
  // along to tell the frontend that it is generating code for a device, so that
  // only the relevant declarations are emitted.
  if (IsOpenMPDevice && Inputs.size() == 2) {
    CmdArgs.push_back("-fopenmp-is-device");
    CmdArgs.push_back("-fopenmp-host-ir-file-path");
    CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
  }

  // For all the host OpenMP offloading compile jobs we need to pass the targets
  // information using -fopenmp-targets= option.
  if (isa<CompileJobAction>(JA) && JA.isHostOffloading(Action::OFK_OpenMP)) {
    SmallString<128> TargetInfo("-fopenmp-targets=");

    Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
    assert(Tgts && Tgts->getNumValues() &&
           "OpenMP offloading has to have targets specified.");
    for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
      if (i)
        TargetInfo += ',';
      // We need to get the string from the triple because it may be not exactly
      // the same as the one we get directly from the arguments.
      llvm::Triple T(Tgts->getValue(i));
      TargetInfo += T.getTriple();
    }
    CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
  }

  bool WholeProgramVTables =
      Args.hasFlag(options::OPT_fwhole_program_vtables,
                   options::OPT_fno_whole_program_vtables, false);
  if (WholeProgramVTables) {
    if (!D.isUsingLTO())
      D.Diag(diag::err_drv_argument_only_allowed_with)
          << "-fwhole-program-vtables"
          << "-flto";
    CmdArgs.push_back("-fwhole-program-vtables");
  }

a5550 6
  } else if (Args.hasArg(options::OPT__SLASH_fallback) &&
             isa<PrecompileJobAction>(JA)) {
    // In /fallback builds, run the main compilation even if the pch generation
    // fails, so that the main compilation's fallback to cl.exe runs.
    C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec,
                                                        CmdArgs, Inputs));
d5558 1
a5558 1
  if (SplitDwarf && Output.getType() == types::TY_Object)
d5714 4
a5717 3
  bool Synch = false;
  bool Asynch = false;
  bool NoUnwindC = false;
d5726 2
a5727 1
/// - c: Assume that extern "C" functions are implicitly nounwind.
a5738 2
        if (EH.Asynch)
          EH.Synch = false;
d5741 1
a5741 1
        EH.NoUnwindC = maybeConsumeDash(EHVal, I);
a5744 2
        if (EH.Synch)
          EH.Asynch = false;
a5752 8
  // The /GX, /GX- flags are only processed if there are not /EH flags.
  // The default is that /GX is not specified.
  if (EHArgs.empty() &&
      Args.hasFlag(options::OPT__SLASH_GX, options::OPT__SLASH_GX_,
                   /*default=*/false)) {
    EH.Synch = true;
    EH.NoUnwindC = true;
  }
d5757 2
a5758 3
void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
                           ArgStringList &CmdArgs,
                           codegenoptions::DebugInfoKind *DebugInfoKind,
a5788 1
    CmdArgs.push_back("-flto-visibility-public-std");
a5793 1
    CmdArgs.push_back("-flto-visibility-public-std");
d5822 8
a5829 17
  // This controls whether or not we emit stack-protector instrumentation.
  // In MSVC, Buffer Security Check (/GS) is on by default.
  if (Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_,
                   /*default=*/true)) {
    CmdArgs.push_back("-stack-protector");
    CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong)));
  }

  // Emit CodeView if -Z7, -Zd, or -gline-tables-only are present.
  if (Arg *DebugInfoArg =
          Args.getLastArg(options::OPT__SLASH_Z7, options::OPT__SLASH_Zd,
                          options::OPT_gline_tables_only)) {
    *EmitCodeView = true;
    if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
      *DebugInfoKind = codegenoptions::LimitedDebugInfo;
    else
      *DebugInfoKind = codegenoptions::DebugLineTablesOnly;
a5830 3
  } else {
    *EmitCodeView = false;
  }
d5834 1
d5836 1
a5836 2
    if (types::isCXX(InputType))
      CmdArgs.push_back("-fcxx-exceptions");
a5838 2
  if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
    CmdArgs.push_back("-fexternc-nounwind");
a5884 9
  if (Args.getLastArg(options::OPT__SLASH_Gd))
     CmdArgs.push_back("-fdefault-calling-conv=cdecl");
  else if (Args.getLastArg(options::OPT__SLASH_Gr))
     CmdArgs.push_back("-fdefault-calling-conv=fastcall");
  else if (Args.getLastArg(options::OPT__SLASH_Gz))
     CmdArgs.push_back("-fdefault-calling-conv=stdcall");
  else if (Args.getLastArg(options::OPT__SLASH_Gv))
     CmdArgs.push_back("-fdefault-calling-conv=vectorcall");

a5913 14
void ClangAs::AddX86TargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  }
}

d5923 3
a5925 2
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
  const std::string &TripleStr = Triple.getTriple();
a5977 14
  bool WantDebug = false;
  unsigned DwarfVersion = 0;
  Args.ClaimAllArgs(options::OPT_g_Group);
  if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    WantDebug = !A->getOption().matches(options::OPT_g0) &&
                !A->getOption().matches(options::OPT_ggdb0);
    if (WantDebug)
      DwarfVersion = DwarfVersionNum(A->getSpelling());
  }
  if (DwarfVersion == 0)
    DwarfVersion = getToolChain().GetDefaultDwarfVersion();

  codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;

d5980 16
a5995 6
    // You might think that it would be ok to set DebugInfoKind outside of
    // the guard for source type, however there is a test which asserts
    // that some assembler invocation receives no -debug-info-kind,
    // and it's not clear whether that test is just overly restrictive.
    DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo
                               : codegenoptions::NoDebugInfo);
a6006 2
  RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
                          llvm::DebuggerKind::Default);
d6014 1
a6014 1
      ParsePICArgs(getToolChain(), Args);
a6054 5

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    AddX86TargetArgs(Args, CmdArgs);
    break;
a6087 128
void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const llvm::opt::ArgList &TCArgs,
                                  const char *LinkingOutput) const {
  // The version with only one output is expected to refer to a bundling job.
  assert(isa<OffloadBundlingJobAction>(JA) && "Expecting bundling job!");

  // The bundling command looks like this:
  // clang-offload-bundler -type=bc
  //   -targets=host-triple,openmp-triple1,openmp-triple2
  //   -outputs=input_file
  //   -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"

  ArgStringList CmdArgs;

  // Get the type.
  CmdArgs.push_back(TCArgs.MakeArgString(
      Twine("-type=") + types::getTypeTempSuffix(Output.getType())));

  assert(JA.getInputs().size() == Inputs.size() &&
         "Not have inputs for all dependence actions??");

  // Get the targets.
  SmallString<128> Triples;
  Triples += "-targets=";
  for (unsigned I = 0; I < Inputs.size(); ++I) {
    if (I)
      Triples += ',';

    Action::OffloadKind CurKind = Action::OFK_Host;
    const ToolChain *CurTC = &getToolChain();
    const Action *CurDep = JA.getInputs()[I];

    if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
      OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
        CurKind = A->getOffloadingDeviceKind();
        CurTC = TC;
      });
    }
    Triples += Action::GetOffloadKindName(CurKind);
    Triples += '-';
    Triples += CurTC->getTriple().normalize();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(Triples));

  // Get bundled file command.
  CmdArgs.push_back(
      TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));

  // Get unbundled files command.
  SmallString<128> UB;
  UB += "-inputs=";
  for (unsigned I = 0; I < Inputs.size(); ++I) {
    if (I)
      UB += ',';
    UB += Inputs[I].getFilename();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(UB));

  // All the inputs are encoded as commands.
  C.addCommand(llvm::make_unique<Command>(
      JA, *this,
      TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
      CmdArgs, None));
}

void OffloadBundler::ConstructJobMultipleOutputs(
    Compilation &C, const JobAction &JA, const InputInfoList &Outputs,
    const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs,
    const char *LinkingOutput) const {
  // The version with multiple outputs is expected to refer to a unbundling job.
  auto &UA = cast<OffloadUnbundlingJobAction>(JA);

  // The unbundling command looks like this:
  // clang-offload-bundler -type=bc
  //   -targets=host-triple,openmp-triple1,openmp-triple2
  //   -inputs=input_file
  //   -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
  //   -unbundle

  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Expecting to unbundle a single file!");
  InputInfo Input = Inputs.front();

  // Get the type.
  CmdArgs.push_back(TCArgs.MakeArgString(
      Twine("-type=") + types::getTypeTempSuffix(Input.getType())));

  // Get the targets.
  SmallString<128> Triples;
  Triples += "-targets=";
  auto DepInfo = UA.getDependentActionsInfo();
  for (unsigned I = 0; I < DepInfo.size(); ++I) {
    if (I)
      Triples += ',';

    auto &Dep = DepInfo[I];
    Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
    Triples += '-';
    Triples += Dep.DependentToolChain->getTriple().normalize();
  }

  CmdArgs.push_back(TCArgs.MakeArgString(Triples));

  // Get bundled file command.
  CmdArgs.push_back(
      TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));

  // Get unbundled files command.
  SmallString<128> UB;
  UB += "-outputs=";
  for (unsigned I = 0; I < Outputs.size(); ++I) {
    if (I)
      UB += ',';
    UB += Outputs[I].getFilename();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(UB));
  CmdArgs.push_back("-unbundle");

  // All the inputs are encoded as commands.
  C.addCommand(llvm::make_unique<Command>(
      JA, *this,
      TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
      CmdArgs, None));
}

d6200 1
a6200 1
  const std::string &customGCCName = D.getCCCGenericGCCName();
d6465 1
a6465 1
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
d6524 1
a6524 2
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  CmdArgs.push_back("-shared");
d6548 1
a6548 4

  const ToolChain &ToolChain = getToolChain();
  const Driver &D = ToolChain.getDriver();
  const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
d6553 6
a6558 45
  // Enable garbage collection of unused input sections by default, since code
  // size is of particular importance. This is significantly facilitated by
  // the enabling of -ffunction-sections and -fdata-sections in
  // Clang::ConstructJob.
  if (areOptimizationsEnabled(Args))
    CmdArgs.push_back("--gc-sections");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");
  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("--strip-all");
  if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("-shared");
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-Bstatic");

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("rcrt1.o")));
    else if (Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
  }

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX())
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");

    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lcompiler_rt");
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
d6560 1
a6562 1

a6680 8
bool mips::hasCompactBranches(StringRef &CPU) {
  // mips32r6 and mips64r6 have compact branches.
  return llvm::StringSwitch<bool>(CPU)
      .Case("mips32r6", true)
      .Case("mips64r6", true)
      .Default(false);
}

a6705 10
bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
  if (!Triple.isAndroid())
    return false;

  // Android MIPS32R6 defaults to FP64A.
  return llvm::StringSwitch<bool>(CPUName)
      .Case("mips32r6", true)
      .Default(false);
}

d6709 1
a6709 2
      Triple.getVendor() != llvm::Triple::MipsTechnologies &&
      !Triple.isAndroid())
a6777 1
  unsigned ArchKind = llvm::ARM::parseArch(Str);
d6782 1
a6782 3
  else if (ArchKind == llvm::ARM::AK_ARMV6M ||
           ArchKind == llvm::ARM::AK_ARMV7M ||
           ArchKind == llvm::ARM::AK_ARMV7EM) {
a6838 8
  CmdArgs.push_back("--no-dynamic-linker");

  // Provide PIE linker flags in case PIE is default for the architecture.
  if (ToolChain.isPIEDefault()) {
    CmdArgs.push_back("-pie");
    CmdArgs.push_back("-zrelro");
  }

d6861 1
a6861 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d6863 1
a6863 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a6972 23
/// \brief Pass -no_deduplicate to ld64 under certain conditions:
///
/// - Either -O0 or -O1 is explicitly specified
/// - No -O option is specified *and* this is a compile+link (implicit -O0)
///
/// Also do *not* add -no_deduplicate when no -O option is specified and this
/// is just a link (we can't imply -O0)
static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O0))
      return true;
    if (A->getOption().matches(options::OPT_O))
      return llvm::StringSwitch<bool>(A->getValue())
                    .Case("1", true)
                    .Default(false);
    return false; // OPT_Ofast & OPT_O4
  }

  if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
    return true;
  return false;
}

d6979 1
a6979 1
  unsigned Version[5] = {0, 0, 0, 0, 0};
d6981 4
a6984 1
    if (!Driver::GetReleaseVersion(A->getValue(), Version))
d7013 17
a7031 21
  // Use -lto_library option to specify the libLTO.dylib path. Try to find
  // it in clang installed libraries. ld64 will only look at this argument
  // when it actually uses LTO, so libLTO.dylib only needs to exist at link
  // time if ld64 decides that it needs to use LTO.
  // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
  // next to it. That's ok since ld64 using a libLTO.dylib not matching the
  // clang version won't work anyways.
  if (Version[0] >= 133) {
    // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
    StringRef P = llvm::sys::path::parent_path(D.Dir);
    SmallString<128> LibLTOPath(P);
    llvm::sys::path::append(LibLTOPath, "lib");
    llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
    CmdArgs.push_back("-lto_library");
    CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
  }

  // ld64 version 262 and above run the deduplicate pass by default.
  if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
    CmdArgs.push_back("-no_deduplicate");

a7118 9
  // for embed-bitcode, use -bitcode_bundle in linker command
  if (C.getDriver().embedBitcodeEnabled()) {
    // Check if the toolchain supports bitcode build flow.
    if (MachOTC.SupportsEmbeddedBitcode())
      CmdArgs.push_back("-bitcode_bundle");
    else
      D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
  }

a7203 18
  // For LTO, pass the name of the optimization record file.
  if (Args.hasFlag(options::OPT_fsave_optimization_record,
                   options::OPT_fno_save_optimization_record, false)) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-lto-pass-remarks-output");
    CmdArgs.push_back("-mllvm");

    SmallString<128> F;
    F = Output.getFilename();
    F += ".opt.yaml";
    CmdArgs.push_back(Args.MakeArgString(F));

    if (getLastProfileUseArg(Args)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-lto-pass-remarks-with-hotness");
    }
  }

d7233 1
a7233 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
a7275 7
  if (unsigned Parallelism =
          getLTOParallelism(Args, getToolChain().getDriver())) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(
        Args.MakeArgString(Twine("-threads=") + llvm::to_string(Parallelism)));
  }

d7451 1
a7451 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d7624 1
a7624 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d7743 1
a7743 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
a7918 1
  CmdArgs.push_back("--eh-frame-hdr");
d7924 1
d8006 1
a8006 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d8009 1
a8009 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d8215 3
a8217 1
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple());
d8305 1
a8305 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d8310 1
a8310 1
  if (Major >= 7 || Major == 0) {
a8312 1
    case llvm::Triple::aarch64_be:
d8381 3
d8390 1
a8390 1
      ParsePICArgs(getToolChain(), Args);
d8469 1
a8469 1
    // for now replace it with -mcpu=cortex-a15 to avoid a lower
d8473 2
a8474 2
        StringRef(A->getValue()).equals_lower("krait"))
      CmdArgs.push_back("-mcpu=cortex-a15");
a8595 1
  bool IsIAMCU = Triple.isOSIAMCU();
d8612 1
a8612 1
  if (StaticLibgcc && !isAndroid && !IsIAMCU)
d8626 66
a8703 1
    case llvm::Triple::Fuchsia:
d8709 1
a8709 10
    // Make sure libgcc is not used under MSVC environment by default
    if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
      // Issue error diagnostic if libgcc is explicitly specified
      // through command line as --rtlib option argument.
      if (Args.hasArg(options::OPT_rtlib_EQ)) {
        TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
            << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC";
      }
    } else
      AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
a8716 2
    if (T.isOSIAMCU())
      return "elf_iamcu";
d8727 1
a8727 1
    return "armelfb_linux_eabi";
d8758 1
a8758 1
    return nullptr;
d8771 2
a8772 1
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
a8775 1
  const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
a8815 8
  // Most Android ARM64 targets should enable the linker fix for erratum
  // 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
  if (Arch == llvm::Triple::aarch64 && isAndroid) {
    std::string CPU = getCPUName(Args, Triple);
    if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
      CmdArgs.push_back("--fix-cortex-a53-843419");
  }

d8823 2
a8824 7
  if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back(LDMOption);
  } else {
    D.Diag(diag::err_target_unknown_triple) << Triple.str();
    return;
  }
d8836 7
a8842 10
  if (!Args.hasArg(options::OPT_static)) {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");

    if (!Args.hasArg(options::OPT_shared)) {
      const std::string Loader =
          D.DyldPrefix + ToolChain.getDynamicLinker(Args);
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(Loader));
    }
d8849 1
a8849 1
    if (!isAndroid && !IsIAMCU) {
d8865 9
a8873 12
    if (IsIAMCU)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
    else {
      const char *crtbegin;
      if (Args.hasArg(options::OPT_static))
        crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
      else if (Args.hasArg(options::OPT_shared))
        crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
      else if (IsPIE)
        crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
      else
        crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
d8875 2
a8876 3
      if (HasCRTBeginEndFiles)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
    }
d8888 1
a8888 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d8894 1
a8894 2
  bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a8919 3
      if (NeedsXRayDeps)
        linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);

d8930 2
a8931 2
        switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
        case Driver::OMPRT_OMP:
d8934 1
a8934 1
        case Driver::OMPRT_GOMP:
d8941 1
a8941 1
        case Driver::OMPRT_IOMP5:
d8944 1
a8944 1
        case Driver::OMPRT_Unknown:
a8947 2
        if (JA.isHostOffloading(Action::OFK_OpenMP))
          CmdArgs.push_back("-lomptarget");
a8954 3
      if (Args.hasArg(options::OPT_fsplit_stack))
        CmdArgs.push_back("--wrap=pthread_create");

a8956 4
      // Add IAMCU specific libs, if needed.
      if (IsIAMCU)
        CmdArgs.push_back("-lgloss");

a8960 7

      // Add IAMCU specific libs (outside the group), if needed.
      if (IsIAMCU) {
        CmdArgs.push_back("--as-needed");
        CmdArgs.push_back("-lsoftfp");
        CmdArgs.push_back("--no-as-needed");
      }
d8963 1
a8963 1
    if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) {
a8978 3
  // Add OpenMP offloading linker script args if required.
  AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);

d9088 1
a9088 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a9153 106
void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  const toolchains::Fuchsia &ToolChain =
      static_cast<const toolchains::Fuchsia &>(getToolChain());
  const Driver &D = ToolChain.getDriver();

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  if (llvm::sys::path::stem(Exec).equals_lower("lld")) {
    CmdArgs.push_back("-flavor");
    CmdArgs.push_back("gnu");
  }

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  if (Args.hasArg(options::OPT_r))
    CmdArgs.push_back("-r");
  else
    CmdArgs.push_back("--build-id");

  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("--eh-frame-hdr");

  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-Bstatic");
  else if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("-shared");

  if (!Args.hasArg(options::OPT_static)) {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");

    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(D.DyldPrefix + "ld.so.1"));
    }
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_u);

  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (Args.hasArg(options::OPT_static))
      CmdArgs.push_back("-Bdynamic");

    if (D.CCCIsCXX()) {
      bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
                                 !Args.hasArg(options::OPT_static);
      if (OnlyLibstdcxxStatic)
        CmdArgs.push_back("-Bstatic");
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (OnlyLibstdcxxStatic)
        CmdArgs.push_back("-Bdynamic");
      CmdArgs.push_back("-lm");
    }

    AddRunTimeLibs(ToolChain, D, CmdArgs, Args);

    if (Args.hasArg(options::OPT_pthread) ||
        Args.hasArg(options::OPT_pthreads))
      CmdArgs.push_back("-lpthread");

    if (Args.hasArg(options::OPT_fsplit_stack))
      CmdArgs.push_back("--wrap=pthread_create");

    CmdArgs.push_back("-lc");
  }

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

d9200 1
a9200 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d9321 1
a9321 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d9444 1
a9444 1
                                               UniversalCRTLibPath));
d9450 2
a9451 2
      CmdArgs.push_back(
          Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
a9453 4
  if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
    for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));

d9456 1
a9456 2
  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
                  options::OPT__SLASH_Zd))
d9472 1
a9472 2
    if (TC.getSanitizerArgs().needsSharedAsanRt() ||
        Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
d9477 1
a9477 4
      CmdArgs.push_back(Args.MakeArgString(
          TC.getArch() == llvm::Triple::x86
              ? "-include:___asan_seh_interceptor"
              : "-include:__asan_seh_interceptor"));
d9494 2
a9495 2
    switch (TC.getDriver().getOpenMPRuntime(Args)) {
    case Driver::OMPRT_OMP:
d9498 1
a9498 1
    case Driver::OMPRT_IOMP5:
d9501 1
a9501 1
    case Driver::OMPRT_GOMP:
d9503 1
a9503 1
    case Driver::OMPRT_Unknown:
a9508 6
  // Add compiler-rt lib in case if it was explicitly
  // specified as an argument for --rtlib option.
  if (!Args.hasArg(options::OPT_nostdlib)) {
    AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
  }

a9616 5

  if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
                   /*default=*/false))
    CmdArgs.push_back("/GS-");

a9639 2
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
a9647 12
  // Use MSVC's default threadsafe statics behaviour unless there was a flag.
  if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
                               options::OPT_fno_threadsafe_statics)) {
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
                          ? "/Zc:threadSafeInit"
                          : "/Zc:threadSafeInit-");
  }

  // Pass through all unknown arguments so that the fallback command can see
  // them too.
  Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);

d9826 1
a9826 1
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
d9950 1
a9950 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d10104 1
a10104 1
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
d10132 6
a10137 6
      // Make sure the dynamic runtime thunk is not optimized out at link time
      // to ensure proper SEH handling.
      CmdArgs.push_back(Args.MakeArgString("--undefined"));
      CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
                                               ? "___asan_seh_interceptor"
                                               : "__asan_seh_interceptor"));
d10165 1
d10171 5
a10175 8
  Args.AddAllArgsExcept(
      CmdArgs,
      {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
       options::OPT_D, options::OPT_U, options::OPT_f_Group,
       options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
       options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ},
      {options::OPT_fno_split_dwarf_inlining});
  Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.
d10215 1
a10215 4
  const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
  if (CPUArg)
    CmdArgs.push_back(
        Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
a10247 2
  // Silence warning if the args contain both -nostdlib and -stdlib=.
  Args.getLastArg(options::OPT_stdlib_EQ);
d10282 1
a10282 2
  bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d10285 2
a10286 9
    if (NeedsSanitizerDeps)
      linkSanitizerRuntimeDeps(TC, CmdArgs);
    if (C.getDriver().CCCIsCXX()) {
      if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
        CmdArgs.push_back("-lc++");
        CmdArgs.push_back("-lc++abi");
      } else
        CmdArgs.push_back("-lstdc++");
    }
a10289 1
      CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
a10295 1
      CmdArgs.push_back("-lgcc");
d10297 1
d10329 1
a10329 1
      Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
d10391 1
a10391 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d10397 1
a10397 1
  const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
d10487 1
a10487 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d10570 1
a10570 1
      Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold"));
d10572 1
a10572 1
      Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
a10605 137

void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CudaToolChain &>(getToolChain());
  assert(TC.getTriple().isNVPTX() && "Wrong platform");

  // Obtain architecture from the action.
  CudaArch gpu_arch = StringToCudaArch(JA.getOffloadingArch());
  assert(gpu_arch != CudaArch::UNKNOWN &&
         "Device action expected to have an architecture.");

  // Check that our installation's ptxas supports gpu_arch.
  if (!Args.hasArg(options::OPT_no_cuda_version_check)) {
    TC.CudaInstallation.CheckCudaVersionSupportsArch(gpu_arch);
  }

  ArgStringList CmdArgs;
  CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
  if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
                   options::OPT_no_cuda_noopt_device_debug, false)) {
    // ptxas does not accept -g option if optimization is enabled, so
    // we ignore the compiler's -O* options if we want debug info.
    CmdArgs.push_back("-g");
    CmdArgs.push_back("--dont-merge-basicblocks");
    CmdArgs.push_back("--return-at-end");
  } else if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    // Map the -O we received to -O{0,1,2,3}.
    //
    // TODO: Perhaps we should map host -O2 to ptxas -O3. -O3 is ptxas's
    // default, so it may correspond more closely to the spirit of clang -O2.

    // -O3 seems like the least-bad option when -Osomething is specified to
    // clang but it isn't handled below.
    StringRef OOpt = "3";
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      OOpt = "3";
    else if (A->getOption().matches(options::OPT_O0))
      OOpt = "0";
    else if (A->getOption().matches(options::OPT_O)) {
      // -Os, -Oz, and -O(anything else) map to -O2, for lack of better options.
      OOpt = llvm::StringSwitch<const char *>(A->getValue())
                 .Case("1", "1")
                 .Case("2", "2")
                 .Case("3", "3")
                 .Case("s", "2")
                 .Case("z", "2")
                 .Default("2");
    }
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
  } else {
    // If no -O was passed, pass -O0 to ptxas -- no opt flag should correspond
    // to no optimizations, but ptxas's default is -O3.
    CmdArgs.push_back("-O0");
  }

  CmdArgs.push_back("--gpu-name");
  CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
  CmdArgs.push_back("--output-file");
  CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
  for (const auto& II : Inputs)
    CmdArgs.push_back(Args.MakeArgString(II.getFilename()));

  for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
    CmdArgs.push_back(Args.MakeArgString(A));

  const char *Exec;
  if (Arg *A = Args.getLastArg(options::OPT_ptxas_path_EQ))
    Exec = A->getValue();
  else
    Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

// All inputs to this linker must be from CudaDeviceActions, as we need to look
// at the Inputs' Actions in order to figure out which GPU architecture they
// correspond to.
void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CudaToolChain &>(getToolChain());
  assert(TC.getTriple().isNVPTX() && "Wrong platform");

  ArgStringList CmdArgs;
  CmdArgs.push_back("--cuda");
  CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32");
  CmdArgs.push_back(Args.MakeArgString("--create"));
  CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));

  for (const auto& II : Inputs) {
    auto *A = II.getAction();
    assert(A->getInputs().size() == 1 &&
           "Device offload action is expected to have a single input");
    const char *gpu_arch_str = A->getOffloadingArch();
    assert(gpu_arch_str &&
           "Device action expected to have associated a GPU architecture!");
    CudaArch gpu_arch = StringToCudaArch(gpu_arch_str);

    // We need to pass an Arch of the form "sm_XX" for cubin files and
    // "compute_XX" for ptx.
    const char *Arch =
        (II.getType() == types::TY_PP_Asm)
            ? CudaVirtualArchToString(VirtualArchForCudaArch(gpu_arch))
            : gpu_arch_str;
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") +
                                         Arch + ",file=" + II.getFilename()));
  }

  for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
    CmdArgs.push_back(Args.MakeArgString(A));

  const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &Args,
                               const char *LinkingOutput) const {

  std::string Linker = getToolChain().GetProgramPath(getShortName());
  ArgStringList CmdArgs;
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs, Inputs));
}
// AVR tools end.
@


1.1.1.12
log
@Import Clang 3.8.1+ r280599.
@
text
@a8183 1
      Args.AddAllArgs(CmdArgs, options::OPT_pie);
a8284 4
    }
    CmdArgs.push_back(
        Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
d8286 3
a8288 1
          Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
d8291 3
a8293 1
          Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
d8359 1
a8359 1
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
d8361 1
a8361 1
          Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
d8364 1
a8364 1
          Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
@


1.1.1.13
log
@Import Clang pre-4.0.0 r291444.
@
text
@d43 1
a43 1
#include "llvm/Support/ScopedPrinter.h"
a44 1
#include "llvm/Support/YAMLParser.h"
d56 1
a56 1
                                      std::vector<StringRef> &Features,
a98 8
          .Case("leon2", "-Av8")
          .Case("at697e", "-Av8")
          .Case("at697f", "-Av8")
          .Case("leon3", "-Av8")
          .Case("ut699", "-Av8")
          .Case("gr712rc", "-Av8")
          .Case("leon4", "-Av8")
          .Case("gr740", "-Av8")
d103 2
d116 2
d228 1
a228 2
                            const ArgList &Args, ArgStringList &CmdArgs,
                            const JobAction &JA) {
a235 8
    // If the current tool chain refers to an OpenMP offloading host, we should
    // ignore inputs that refer to OpenMP offloading devices - they will be
    // embedded according to a proper linker script.
    if (auto *IA = II.getAction())
      if (JA.isHostOffloading(Action::OFK_OpenMP) &&
          IA->isDeviceOffloading(Action::OFK_OpenMP))
        continue;

a268 125
/// Add OpenMP linker script arguments at the end of the argument list so that
/// the fat binary is built by embedding each of the device images into the
/// host. The linker script also defines a few symbols required by the code
/// generation so that the images can be easily retrieved at runtime by the
/// offloading library. This should be used only in tool chains that support
/// linker scripts.
static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args, ArgStringList &CmdArgs,
                                  const JobAction &JA) {

  // If this is not an OpenMP host toolchain, we don't need to do anything.
  if (!JA.isHostOffloading(Action::OFK_OpenMP))
    return;

  // Create temporary linker script. Keep it if save-temps is enabled.
  const char *LKS;
  SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
  if (C.getDriver().isSaveTempsEnabled()) {
    llvm::sys::path::replace_extension(Name, "lk");
    LKS = C.getArgs().MakeArgString(Name.c_str());
  } else {
    llvm::sys::path::replace_extension(Name, "");
    Name = C.getDriver().GetTemporaryPath(Name, "lk");
    LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
  }

  // Add linker script option to the command.
  CmdArgs.push_back("-T");
  CmdArgs.push_back(LKS);

  // Create a buffer to write the contents of the linker script.
  std::string LksBuffer;
  llvm::raw_string_ostream LksStream(LksBuffer);

  // Get the OpenMP offload tool chains so that we can extract the triple
  // associated with each device input.
  auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
  assert(OpenMPToolChains.first != OpenMPToolChains.second &&
         "No OpenMP toolchains??");

  // Track the input file name and device triple in order to build the script,
  // inserting binaries in the designated sections.
  SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;

  // Add commands to embed target binaries. We ensure that each section and
  // image is 16-byte aligned. This is not mandatory, but increases the
  // likelihood of data to be aligned with a cache block in several main host
  // machines.
  LksStream << "/*\n";
  LksStream << "       OpenMP Offload Linker Script\n";
  LksStream << " *** Automatically generated by Clang ***\n";
  LksStream << "*/\n";
  LksStream << "TARGET(binary)\n";
  auto DTC = OpenMPToolChains.first;
  for (auto &II : Inputs) {
    const Action *A = II.getAction();
    // Is this a device linking action?
    if (A && isa<LinkJobAction>(A) &&
        A->isDeviceOffloading(Action::OFK_OpenMP)) {
      assert(DTC != OpenMPToolChains.second &&
             "More device inputs than device toolchains??");
      InputBinaryInfo.push_back(std::make_pair(
          DTC->second->getTriple().normalize(), II.getFilename()));
      ++DTC;
      LksStream << "INPUT(" << II.getFilename() << ")\n";
    }
  }

  assert(DTC == OpenMPToolChains.second &&
         "Less device inputs than device toolchains??");

  LksStream << "SECTIONS\n";
  LksStream << "{\n";
  LksStream << "  .omp_offloading :\n";
  LksStream << "  ALIGN(0x10)\n";
  LksStream << "  {\n";

  for (auto &BI : InputBinaryInfo) {
    LksStream << "    . = ALIGN(0x10);\n";
    LksStream << "    PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
              << " = .);\n";
    LksStream << "    " << BI.second << "\n";
    LksStream << "    PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
              << " = .);\n";
  }

  LksStream << "  }\n";
  // Add commands to define host entries begin and end. We use 1-byte subalign
  // so that the linker does not add any padding and the elements in this
  // section form an array.
  LksStream << "  .omp_offloading.entries :\n";
  LksStream << "  ALIGN(0x10)\n";
  LksStream << "  SUBALIGN(0x01)\n";
  LksStream << "  {\n";
  LksStream << "    PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
  LksStream << "    *(.omp_offloading.entries)\n";
  LksStream << "    PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
  LksStream << "  }\n";
  LksStream << "}\n";
  LksStream << "INSERT BEFORE .data\n";
  LksStream.flush();

  // Dump the contents of the linker script if the user requested that. We
  // support this option to enable testing of behavior with -###.
  if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
    llvm::errs() << LksBuffer;

  // If this is a dry run, do not create the linker script file.
  if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
    return;

  // Open script file and write the contents.
  std::error_code EC;
  llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);

  if (EC) {
    C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
    return;
  }

  Lksf << LksBuffer;
}

a290 21
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
                           const ToolChain &RegularToolChain,
                           llvm::function_ref<void(const ToolChain &)> Work) {
  // Apply Work on the current/regular tool chain.
  Work(RegularToolChain);

  // Apply Work on all the offloading tool chains associated with the current
  // action.
  if (JA.isHostOffloading(Action::OFK_Cuda))
    Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
  else if (JA.isDeviceOffloading(Action::OFK_Cuda))
    Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());

  //
  // TODO: Add support for other offloading programming models here.
  //
}

d295 2
a296 1
                                    const InputInfoList &Inputs) const {
a297 1
  const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
a383 7
  // Add offload include arguments specific for CUDA.  This must happen before
  // we -I or -include anything else, because we must pick up the CUDA headers
  // from the particular CUDA installation, rather than from e.g.
  // /usr/local/include.
  if (JA.isOffloading(Action::OFK_Cuda))
    getToolChain().AddCudaIncludeArgs(Args, CmdArgs);

a388 25
  int YcIndex = -1, YuIndex = -1;
  {
    int AI = -1;
    const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
    const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
    for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
      // Walk the whole i_Group and skip non "-include" flags so that the index
      // here matches the index in the next loop below.
      ++AI;
      if (!A->getOption().matches(options::OPT_include))
        continue;
      if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0)
        YcIndex = AI;
      if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0)
        YuIndex = AI;
    }
  }
  if (isa<PrecompileJobAction>(JA) && YcIndex != -1) {
    Driver::InputList Inputs;
    D.BuildInputs(getToolChain(), C.getArgs(), Inputs);
    assert(Inputs.size() == 1 && "Need one input when building pch");
    CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") +
                                         Inputs[0].second->getValue()));
  }

a389 1
  int AI = -1;
d391 1
a391 40
    ++AI;

    if (getToolChain().getDriver().IsCLMode() &&
        A->getOption().matches(options::OPT_include)) {
      // In clang-cl mode, /Ycfoo.h means that all code up to a foo.h
      // include is compiled into foo.h, and everything after goes into
      // the .obj file. /Yufoo.h means that all includes prior to and including
      // foo.h are completely skipped and replaced with a use of the pch file
      // for foo.h.  (Each flag can have at most one value, multiple /Yc flags
      // just mean that the last one wins.)  If /Yc and /Yu are both present
      // and refer to the same file, /Yc wins.
      // Note that OPT__SLASH_FI gets mapped to OPT_include.
      // FIXME: The code here assumes that /Yc and /Yu refer to the same file.
      // cl.exe seems to support both flags with different values, but that
      // seems strange (which flag does /Fp now refer to?), so don't implement
      // that until someone needs it.
      int PchIndex = YcIndex != -1 ? YcIndex : YuIndex;
      if (PchIndex != -1) {
        if (isa<PrecompileJobAction>(JA)) {
          // When building the pch, skip all includes after the pch.
          assert(YcIndex != -1 && PchIndex == YcIndex);
          if (AI >= YcIndex)
            continue;
        } else {
          // When using the pch, skip all includes prior to the pch.
          if (AI < PchIndex) {
            A->claim();
            continue;
          }
          if (AI == PchIndex) {
            A->claim();
            CmdArgs.push_back("-include-pch");
            CmdArgs.push_back(
                Args.MakeArgString(D.GetClPchPath(C, A->getValue())));
            continue;
          }
        }
      }
    } else if (A->getOption().matches(options::OPT_include)) {
      // Handling of gcc-style gch precompiled headers.
a438 7
    } else if (A->getOption().matches(options::OPT_isystem_after)) {
      // Handling of paths which must come late.  These entries are handled by
      // the toolchain itself after the resource dir is inserted in the right
      // search order.
      // Do not claim the argument so that the use of the argument does not
      // silently go unnoticed on toolchains which do not honour the option.
      continue;
d488 4
a491 3
  // While adding the include arguments, we also attempt to retrieve the
  // arguments of related offloading toolchains or arguments that are specific
  // of an offloading programming model.
d494 4
a497 15
  if (types::isCXX(Inputs[0].getType()))
    forAllAssociatedToolChains(C, JA, getToolChain(),
                               [&Args, &CmdArgs](const ToolChain &TC) {
                                 TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
                               });

  // Add system include arguments for all targets but IAMCU.
  if (!IsIAMCU)
    forAllAssociatedToolChains(C, JA, getToolChain(),
                               [&Args, &CmdArgs](const ToolChain &TC) {
                                 TC.AddClangSystemIncludeArgs(Args, CmdArgs);
                               });
  else {
    // For IAMCU add special include arguments.
    getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs);
d499 9
d591 1
a591 1
                                std::vector<StringRef> &Features) {
d600 1
a600 1
                              std::vector<StringRef> &Features) {
d608 1
a608 1
                              std::vector<StringRef> &Features) {
d613 2
a614 2
    StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature);
    if (!FeatureName.empty())
d627 1
a627 1
                             std::vector<StringRef> &Features,
d640 1
a640 1
                            std::vector<StringRef> &Features,
d661 1
a661 1
  const llvm::Triple &Triple = TC.getEffectiveTriple();
a700 1
      ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI;
a726 1
      case llvm::Triple::MuslEABIHF:
a730 1
      case llvm::Triple::MuslEABI:
d740 1
a740 6
        if (Triple.isOSBinFormatMachO() &&
            Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
          ABI = FloatABI::Hard;
        else
          ABI = FloatABI::Soft;

d756 1
a756 2
                                 ArgStringList &CmdArgs,
                                 std::vector<StringRef> &Features,
d882 4
a897 23
  // Generate execute-only output (no data access to code sections).
  // Supported only on ARMv6T2 and ARMv7 and above.
  // Cannot be combined with -mno-movt or -mlong-calls
  if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
    if (A->getOption().matches(options::OPT_mexecute_only)) {
      if (getARMSubArchVersionNumber(Triple) < 7 &&
          llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
            D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
      else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
        D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
      // Long calls create constant pool entries and have not yet been fixed up
      // to play nicely with execute-only. Hence, they cannot be used in
      // execute-only code for now
      else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
        if (B->getOption().matches(options::OPT_mlong_calls))
          D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
      }

      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-execute-only");
    }
  }

a906 4
      // v8M Baseline follows on from v6M, so doesn't support unaligned memory
      // access either.
      else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
        D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
d957 1
a957 1
    } else if (Triple.isWatchABI()) {
a970 2
    case llvm::Triple::MuslEABI:
    case llvm::Triple::MuslEABIHF:
d1024 3
a1026 3
/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
/// arguments if they are provided, or to nullptr otherwise.
static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
d1052 2
a1053 1
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
d1115 1
a1115 2
  if (Triple.isAndroid()) {
    DefMips32CPU = "mips32";
a1116 1
  }
a1150 24
  if (ABIName.empty() &&
      (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
       Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
    ABIName = llvm::StringSwitch<const char *>(CPUName)
                  .Case("mips1", "o32")
                  .Case("mips2", "o32")
                  .Case("mips3", "n64")
                  .Case("mips4", "n64")
                  .Case("mips5", "n64")
                  .Case("mips32", "o32")
                  .Case("mips32r2", "o32")
                  .Case("mips32r3", "o32")
                  .Case("mips32r5", "o32")
                  .Case("mips32r6", "o32")
                  .Case("mips64", "n64")
                  .Case("mips64r2", "n64")
                  .Case("mips64r3", "n64")
                  .Case("mips64r5", "n64")
                  .Case("mips64r6", "n64")
                  .Case("octeon", "n64")
                  .Case("p5600", "o32")
                  .Default("");
  }

d1163 1
a1163 1
                  .Case("o32", DefMips32CPU)
d1225 1
a1225 1
                             std::vector<StringRef> &Features,
d1238 1
a1238 1
                                  std::vector<StringRef> &Features) {
d1289 2
a1290 3
  // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
  // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
  // nooddspreg.
a1302 3
  } else if (mips::isFP64ADefault(Triple, CPUName)) {
    Features.push_back(Args.MakeArgString("+fp64"));
    Features.push_back(Args.MakeArgString("+nooddspreg"));
a1361 13

  if (Arg *A = Args.getLastArg(options::OPT_mcompact_branches_EQ)) {
    StringRef Val = StringRef(A->getValue());
    if (mips::hasCompactBranches(CPUName)) {
      if (Val == "never" || Val == "always" || Val == "optimal") {
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back(Args.MakeArgString("-mips-compact-branches=" + Val));
      } else
        D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Val;
    } else
      D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName;
  }
a1410 1
        .Case("power9", "pwr9")
a1418 1
        .Case("pwr9", "pwr9")
d1430 1
a1430 1
                                 std::vector<StringRef> &Features) {
d1434 9
a1442 2
  if (FloatABI == ppc::FloatABI::Soft)
    Features.push_back("-hard-float");
d1557 4
a1560 6
static std::string getLanaiTargetCPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    return A->getValue();
  }
  return "";
}
d1562 1
a1562 3
sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
                                        const ArgList &Args) {
  sparc::FloatABI ABI = sparc::FloatABI::Invalid;
d1564 1
a1564 2
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
                          options::OPT_mfloat_abi_EQ)) {
d1566 1
a1566 14
      ABI = sparc::FloatABI::Soft;
    else if (A->getOption().matches(options::OPT_mhard_float))
      ABI = sparc::FloatABI::Hard;
    else {
      ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue())
                .Case("soft", sparc::FloatABI::Soft)
                .Case("hard", sparc::FloatABI::Hard)
                .Default(sparc::FloatABI::Invalid);
      if (ABI == sparc::FloatABI::Invalid &&
          !StringRef(A->getValue()).empty()) {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        ABI = sparc::FloatABI::Hard;
      }
    }
a1568 1
  // If unspecified, choose the default based on the platform.
d1570 7
a1576 5
  // default. GCC also supports a nonstandard soft-float ABI mode, also
  // implemented in LLVM. However as this is not standard we set the default
  // to be hard-float.
  if (ABI == sparc::FloatABI::Invalid) {
    ABI = sparc::FloatABI::Hard;
a1577 33

  return ABI;
}

static void getSparcTargetFeatures(const Driver &D, const ArgList &Args,
                                 std::vector<StringRef> &Features) {
  sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
  if (FloatABI == sparc::FloatABI::Soft)
    Features.push_back("+soft-float");
}

void Clang::AddSparcTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  sparc::FloatABI FloatABI =
      sparc::getSparcFloatABI(getToolChain().getDriver(), Args);

  if (FloatABI == sparc::FloatABI::Soft) {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == sparc::FloatABI::Hard && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }
}

void Clang::AddSystemZTargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  if (Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false))
    CmdArgs.push_back("-mbackchain");
d1587 1
a1587 1
                                     std::vector<StringRef> &Features) {
a1657 5
    // macosx10.12 drops support for all pre-Penryn Macs.
    // Simulators can still run on 10.11 though, like Xcode.
    if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
      return "penryn";
    // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
a1708 2
  Arg *A;

d1715 1
a1715 1
    return getAArch64TargetCPU(Args, A);
a1773 3
  case llvm::Triple::lanai:
    return getLanaiTargetCPU(Args);

a1786 18
static unsigned getLTOParallelism(const ArgList &Args, const Driver &D) {
  unsigned Parallelism = 0;
  Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
  if (LtoJobsArg &&
      StringRef(LtoJobsArg->getValue()).getAsInteger(10, Parallelism))
    D.Diag(diag::err_drv_invalid_int_value) << LtoJobsArg->getAsString(Args)
                                            << LtoJobsArg->getValue();
  return Parallelism;
}

// CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
// default.
static bool isUseSeparateSections(const llvm::Triple &Triple) {
  return Triple.getOS() == llvm::Triple::CloudABI ||
         Triple.getArch() == llvm::Triple::wasm32 ||
         Triple.getArch() == llvm::Triple::wasm64;
}

d1788 1
a1788 2
                          ArgStringList &CmdArgs, bool IsThinLTO,
                          const Driver &D) {
a1819 37

  if (unsigned Parallelism = getLTOParallelism(Args, D))
    CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") +
                                         llvm::to_string(Parallelism)));

  // If an explicit debugger tuning argument appeared, pass it along.
  if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
                               options::OPT_ggdbN_Group)) {
    if (A->getOption().matches(options::OPT_glldb))
      CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb");
    else if (A->getOption().matches(options::OPT_gsce))
      CmdArgs.push_back("-plugin-opt=-debugger-tune=sce");
    else
      CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb");
  }

  bool UseSeparateSections =
      isUseSeparateSections(ToolChain.getEffectiveTriple());

  if (Args.hasFlag(options::OPT_ffunction_sections,
                   options::OPT_fno_function_sections, UseSeparateSections)) {
    CmdArgs.push_back("-plugin-opt=-function-sections");
  }

  if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
                   UseSeparateSections)) {
    CmdArgs.push_back("-plugin-opt=-data-sections");
  }

  if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
    StringRef FName = A->getValue();
    if (!llvm::sys::fs::exists(FName))
      D.Diag(diag::err_drv_no_such_file) << FName;
    else
      CmdArgs.push_back(
          Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
  }
d1955 1
a1955 1
                                 std::vector<StringRef> &Features) {
a2047 7

  // Set flags to support MCU ABI.
  if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
    CmdArgs.push_back("-mstack-alignment=4");
  }
a2071 23
void Clang::AddLanaiTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPUName = A->getValue();

    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPUName));
  }
  if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
    StringRef Value = A->getValue();
    // Only support mregparm=4 to support old usage. Report error for all other
    // cases.
    int Mregparm;
    if (Value.getAsInteger(10, Mregparm)) {
      if (Mregparm != 4) {
        getToolChain().getDriver().Diag(
            diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
      }
    }
  }
}

d2084 1
a2084 1
                                  std::vector<StringRef> &Features) {
d2089 16
a2104 3
    StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
    if (!FeatureName.empty())
      Features.push_back(FeatureName);
d2116 1
a2116 1
                              std::vector<StringRef> &Features) {
d2119 6
a2124 2

  if (CPU == "generic") {
d2127 2
a2128 8
    unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
    if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
      return false;

    unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
    if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
      return false;
   }
d2139 1
a2139 1
                                std::vector<StringRef> &Features) {
d2143 11
a2153 4
  unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
  if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
      !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
      (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
d2162 1
a2162 1
                               std::vector<StringRef> &Features) {
d2174 1
a2174 1
                                     std::vector<StringRef> &Features) {
d2189 1
a2189 1
                                    std::vector<StringRef> &Features) {
d2191 1
a2191 1
  std::vector<StringRef> DecodedFeature;
d2200 1
a2200 1
                                     std::vector<StringRef> &Features) {
d2210 2
a2211 2
    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
                                             Args, Features);
d2219 3
a2221 3
  else if (success && Args.hasArg(options::OPT_arch))
    success = getAArch64MicroArchFeaturesFromMcpu(
        D, getAArch64TargetCPU(Args, A), Args, Features);
d2250 2
a2251 3
                                     std::vector<StringRef> &Features) {
  handleTargetFeaturesGroup(Args, Features,
                            options::OPT_m_hexagon_Features_Group);
d2253 16
a2268 5
  bool UseLongCalls = false;
  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
                               options::OPT_mno_long_calls)) {
    if (A->getOption().matches(options::OPT_mlong_calls))
      UseLongCalls = true;
d2271 2
a2272 1
  Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
d2276 1
a2276 1
                                         std::vector<StringRef> &Features) {
a2279 17
static void getAMDGPUTargetFeatures(const Driver &D, const ArgList &Args,
                                    std::vector<StringRef> &Features) {
  if (const Arg *dAbi = Args.getLastArg(options::OPT_mamdgpu_debugger_abi)) {
    StringRef value = dAbi->getValue();
    if (value == "1.0") {
      Features.push_back("+amdgpu-debugger-insert-nops");
      Features.push_back("+amdgpu-debugger-reserve-regs");
      Features.push_back("+amdgpu-debugger-emit-prologue");
    } else {
      D.Diag(diag::err_drv_clang_unsupported) << dAbi->getAsString(Args);
    }
  }

  handleTargetFeaturesGroup(
    Args, Features, options::OPT_m_amdgpu_Features_Group);
}

d2284 1
a2284 1
  std::vector<StringRef> Features;
d2299 1
a2299 1
    getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
a2324 9
  case llvm::Triple::sparc:
  case llvm::Triple::sparcel:
  case llvm::Triple::sparcv9:
    getSparcTargetFeatures(D, Args, Features);
    break;
  case llvm::Triple::r600:
  case llvm::Triple::amdgcn:
    getAMDGPUTargetFeatures(D, Args, Features);
    break;
d2330 1
a2330 1
    StringRef Name = Features[I];
d2332 1
a2332 1
    LastOpt[Name.drop_front(1)] = I;
d2337 2
a2338 2
    StringRef Name = Features[I];
    llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
d2345 1
a2345 1
    CmdArgs.push_back(Name.data());
d2404 5
a2408 3
    // Disable C++ EH by default on XCore and PS4.
    bool CXXExceptionsEnabled =
        Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
d2467 2
a2468 2
  for (const auto &AI : A->inputs())
    if (ContainsCompileAction(AI))
d2498 1
a2498 1
static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
d2503 1
a2503 1
    return codegenoptions::NoDebugInfo;
d2506 2
a2507 2
    return codegenoptions::DebugLineTablesOnly;
  return codegenoptions::LimitedDebugInfo;
d2523 1
a2523 1
                                    codegenoptions::DebugInfoKind DebugInfoKind,
d2527 1
a2527 1
  case codegenoptions::DebugLineTablesOnly:
d2530 1
a2530 1
  case codegenoptions::LimitedDebugInfo:
d2533 1
a2533 1
  case codegenoptions::FullDebugInfo:
a2572 21
  switch (C.getDefaultToolChain().getArch()) {
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    if (Arg *A = Args.getLastArg(options::OPT_mimplicit_it_EQ)) {
      StringRef Value = A->getValue();
      if (Value == "always" || Value == "never" || Value == "arm" ||
          Value == "thumb") {
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
      }
    }
    break;
  default:
    break;
  }

a2582 3

  bool UseRelaxRelocations = ENABLE_X86_RELAX_RELOCATIONS;
  const char *MipsTargetFeature = nullptr;
a2593 4
      if (C.getDefaultToolChain().getTriple().isOSBinFormatCOFF() &&
          Value == "-mbig-obj")
        continue; // LLVM handles bigobj automatically

d2621 1
a2621 20

        MipsTargetFeature = llvm::StringSwitch<const char *>(Value)
                                .Case("-mips1", "+mips1")
                                .Case("-mips2", "+mips2")
                                .Case("-mips3", "+mips3")
                                .Case("-mips4", "+mips4")
                                .Case("-mips5", "+mips5")
                                .Case("-mips32", "+mips32")
                                .Case("-mips32r2", "+mips32r2")
                                .Case("-mips32r3", "+mips32r3")
                                .Case("-mips32r5", "+mips32r5")
                                .Case("-mips32r6", "+mips32r6")
                                .Case("-mips64", "+mips64")
                                .Case("-mips64r2", "+mips64r2")
                                .Case("-mips64r3", "+mips64r3")
                                .Case("-mips64r5", "+mips64r5")
                                .Case("-mips64r6", "+mips64r6")
                                .Default(nullptr);
        if (MipsTargetFeature)
          continue;
a2637 6
      } else if (Value == "-mrelax-relocations=yes" ||
                 Value == "--mrelax-relocations=yes") {
        UseRelaxRelocations = true;
      } else if (Value == "-mrelax-relocations=no" ||
                 Value == "--mrelax-relocations=no") {
        UseRelaxRelocations = false;
d2650 3
a2652 3
          RenderDebugEnablingArgs(Args, CmdArgs,
                                  codegenoptions::LimitedDebugInfo,
                                  DwarfVersion, llvm::DebuggerKind::Default);
a2656 21
      } else if (Value == "-defsym") {
          if (A->getNumValues() != 2) {
            D.Diag(diag::err_drv_defsym_invalid_format) << Value;
            break;
          }
          const char *S = A->getValue(1);
          auto Pair = StringRef(S).split('=');
          auto Sym = Pair.first;
          auto SVal = Pair.second;

          if (Sym.empty() || SVal.empty()) {
            D.Diag(diag::err_drv_defsym_invalid_format) << S;
            break;
          }
          int64_t IVal;
          if (SVal.getAsInteger(0, IVal)) {
            D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
            break;
          }
          CmdArgs.push_back(Value.data());
          TakeNextArg = true;
a2668 6
  if (UseRelaxRelocations)
    CmdArgs.push_back("--mrelax-relocations");
  if (MipsTargetFeature != nullptr) {
    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back(MipsTargetFeature);
  }
d2679 49
d2734 2
a2735 2
  switch (TC.getDriver().getOpenMPRuntime(Args)) {
  case Driver::OMPRT_OMP:
d2738 1
a2738 1
  case Driver::OMPRT_GOMP:
d2741 1
a2741 1
  case Driver::OMPRT_IOMP5:
d2744 1
a2744 1
  case Driver::OMPRT_Unknown:
d2752 2
a2753 2
                                bool IsShared, bool IsWhole) {
  // Wrap any static runtimes that must be forced into executable in
d2755 1
a2755 1
  if (IsWhole) CmdArgs.push_back("-whole-archive");
d2757 1
a2757 1
  if (IsWhole) CmdArgs.push_back("-no-whole-archive");
d2778 2
a2779 5
  // There's no libpthread or librt on RTEMS.
  if (TC.getTriple().getOS() != llvm::Triple::RTEMS) {
    CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lrt");
  }
d2781 2
a2782 3
  // There's no libdl on FreeBSD or RTEMS.
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
      TC.getTriple().getOS() != llvm::Triple::RTEMS)
d2790 1
a2790 3
                         SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
                         SmallVectorImpl<StringRef> &HelperStaticRuntimes,
                         SmallVectorImpl<StringRef> &RequiredSymbols) {
a2795 3
  // The stats_client library is also statically linked into DSOs.
  if (SanArgs.needsStatsRt())
    StaticRuntimes.push_back("stats_client");
d2834 1
a2834 1
  if (SanArgs.needsCfiDiagRt()) {
a2835 9
    if (SanArgs.linkCXXRuntimes())
      StaticRuntimes.push_back("ubsan_standalone_cxx");
  }
  if (SanArgs.needsStatsRt()) {
    NonWholeStaticRuntimes.push_back("stats");
    RequiredSymbols.push_back("__sanitizer_stats_register");
  }
  if (SanArgs.needsEsanRt())
    StaticRuntimes.push_back("esan");
d2843 1
a2843 1
      NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
d2845 1
a2845 2
                           NonWholeStaticRuntimes, HelperStaticRuntimes,
                           RequiredSymbols);
d2847 1
a2847 1
    addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false);
d2849 1
a2849 1
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
d2852 1
a2852 1
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
a2854 8
  for (auto RT : NonWholeStaticRuntimes) {
    addSanitizerRuntime(TC, Args, CmdArgs, RT, false, false);
    AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
  }
  for (auto S : RequiredSymbols) {
    CmdArgs.push_back("-u");
    CmdArgs.push_back(Args.MakeArgString(S));
  }
a2858 5

  const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
  if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
    CmdArgs.push_back("-export-dynamic-symbol=__cfi_check");

a2861 27
static bool addXRayRuntime(const ToolChain &TC, const ArgList &Args,
                           ArgStringList &CmdArgs) {
  if (Args.hasFlag(options::OPT_fxray_instrument,
                   options::OPT_fnoxray_instrument, false)) {
    CmdArgs.push_back("-whole-archive");
    CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray", false));
    CmdArgs.push_back("-no-whole-archive");
    return true;
  }
  return false;
}

static void linkXRayRuntimeDeps(const ToolChain &TC, const ArgList &Args,
                                ArgStringList &CmdArgs) {
  CmdArgs.push_back("--no-as-needed");
  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-lm");
  CmdArgs.push_back("-latomic");
  if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
    CmdArgs.push_back("-lc++");
  else
    CmdArgs.push_back("-lstdc++");
  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
    CmdArgs.push_back("-ldl");
}

d2870 2
a2871 14
static bool mustUseFramePointerForTarget(const llvm::Triple &Triple) {
  switch (Triple.getArch()){
  default:
    return false;
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    // ARM Darwin targets require a frame pointer to be always present to aid
    // offline debugging via backtraces.
    return Triple.isOSDarwin();
  }
}

static bool useFramePointerForTargetByDefault(const ArgList &Args,
                                              const llvm::Triple &Triple) {
d2883 1
a2883 1
  if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
a2902 2
    case llvm::Triple::x86_64:
      return Triple.isOSBinFormatMachO();
d2921 1
a2921 3
    return A->getOption().matches(options::OPT_fno_omit_frame_pointer) ||
           mustUseFramePointerForTarget(Triple);

d2925 1
a2925 1
  return useFramePointerForTargetByDefault(Args, Triple);
d2932 1
a2932 3
    return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer) ||
           mustUseFramePointerForTarget(Triple);

d2939 1
a2939 1
  return useFramePointerForTargetByDefault(Args, Triple);
d3039 13
d3095 41
a3135 5
static Arg *getLastProfileUseArg(const ArgList &Args) {
  auto *ProfileUseArg = Args.getLastArg(
      options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
      options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
      options::OPT_fno_profile_instr_use);
d3137 3
a3139 5
  if (ProfileUseArg &&
      ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
    ProfileUseArg = nullptr;

  return ProfileUseArg;
a3144 8

  auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate,
                                         options::OPT_fprofile_generate_EQ,
                                         options::OPT_fno_profile_generate);
  if (PGOGenerateArg &&
      PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
    PGOGenerateArg = nullptr;

d3147 2
a3148 1
      options::OPT_fprofile_instr_generate_EQ,
d3155 7
a3161 9
  if (PGOGenerateArg && ProfileGenerateArg)
    D.Diag(diag::err_drv_argument_not_allowed_with)
        << PGOGenerateArg->getSpelling() << ProfileGenerateArg->getSpelling();

  auto *ProfileUseArg = getLastProfileUseArg(Args);

  if (PGOGenerateArg && ProfileUseArg)
    D.Diag(diag::err_drv_argument_not_allowed_with)
        << ProfileUseArg->getSpelling() << PGOGenerateArg->getSpelling();
d3170 5
a3174 12
      CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instrument-path=") +
                                           ProfileGenerateArg->getValue()));
    // The default is to use Clang Instrumentation.
    CmdArgs.push_back("-fprofile-instrument=clang");
  }

  if (PGOGenerateArg) {
    CmdArgs.push_back("-fprofile-instrument=llvm");
    if (PGOGenerateArg->getOption().matches(
            options::OPT_fprofile_generate_EQ)) {
      SmallString<128> Path(PGOGenerateArg->getValue());
      llvm::sys::path::append(Path, "default_%m.profraw");
d3176 3
a3178 2
          Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path));
    }
d3183 1
a3183 2
      CmdArgs.push_back(Args.MakeArgString(
          Twine("-fprofile-instrument-use-path=") + ProfileUseArg->getValue()));
d3193 1
a3193 1
          Args.MakeArgString(Twine("-fprofile-instrument-use-path=") + Path));
d3219 7
a3225 7
      CmdArgs.push_back("-coverage-notes-file");
      SmallString<128> OutputFilename;
      if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
        OutputFilename = FinalOutput->getValue();
      else
        OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
      SmallString<128> CoverageFilename = OutputFilename;
a3232 1
      llvm::sys::path::replace_extension(CoverageFilename, "gcno");
a3233 15

      // Leave -fprofile-dir= an unused argument unless .gcda emission is
      // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
      // the flag used. There is no -fno-profile-dir, so the user has no
      // targeted way to suppress the warning.
      if (Args.hasArg(options::OPT_fprofile_arcs) ||
          Args.hasArg(options::OPT_coverage)) {
        CmdArgs.push_back("-coverage-data-file");
        if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) {
          CoverageFilename = FProfileDir->getValue();
          llvm::sys::path::append(CoverageFilename, OutputFilename);
        }
        llvm::sys::path::replace_extension(CoverageFilename, "gcda");
        CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
      }
d3260 4
a3263 4
ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
  const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple();
  const llvm::Triple &Triple = ToolChain.getTriple();

d3267 2
a3268 1
  if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static))
d3276 2
a3277 2
  if (Triple.isAndroid()) {
    switch (Triple.getArch()) {
d3302 1
a3302 1
  if (Triple.getOS() == llvm::Triple::OpenBSD) {
a3330 11
  if (Triple.isOSWindows() && LastPICArg &&
      LastPICArg ==
          Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
                          options::OPT_fPIE, options::OPT_fpie)) {
    ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
        << LastPICArg->getSpelling() << Triple.str();
    if (Triple.getArch() == llvm::Triple::x86_64)
      return std::make_tuple(llvm::Reloc::PIC_, 2U, false);
    return std::make_tuple(llvm::Reloc::Static, 0U, false);
  }

d3345 1
a3345 1
        if (EffectiveTriple.isPS4CPU()) {
d3361 1
a3361 1
  if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU()))
d3366 2
a3367 3
  if (KernelOrKext &&
      ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
       !EffectiveTriple.isWatchOS()))
d3373 1
a3373 1
    if (!Triple.isOSDarwin())
d3375 1
a3375 1
          << A->getSpelling() << Triple.str();
d3384 1
a3384 23
    return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false);
  }

  bool EmbeddedPISupported;
  switch (Triple.getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
      EmbeddedPISupported = true;
      break;
    default:
      EmbeddedPISupported = false;
      break;
  }

  bool ROPI = false, RWPI = false;
  Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi);
  if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) {
    if (!EmbeddedPISupported)
      ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
          << LastROPIArg->getSpelling() << Triple.str();
    ROPI = true;
a3385 11
  Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi);
  if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) {
    if (!EmbeddedPISupported)
      ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
          << LastRWPIArg->getSpelling() << Triple.str();
    RWPI = true;
  }

  // ROPI and RWPI are not comaptible with PIC or PIE.
  if ((ROPI || RWPI) && (PIC || PIE))
    ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic);
d3388 1
a3388 1
    return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE);
d3390 1
a3390 9
  llvm::Reloc::Model RelocM = llvm::Reloc::Static;
  if (ROPI && RWPI)
    RelocM = llvm::Reloc::ROPI_RWPI;
  else if (ROPI)
    RelocM = llvm::Reloc::ROPI;
  else if (RWPI)
    RelocM = llvm::Reloc::RWPI;

  return std::make_tuple(RelocM, 0U, false);
d3395 2
a3402 6
  case llvm::Reloc::ROPI:
    return "ropi";
  case llvm::Reloc::RWPI:
    return "rwpi";
  case llvm::Reloc::ROPI_RWPI:
    return "ropi-rwpi";
d3412 2
a3413 1
  std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args);
a3418 59
void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
                                    StringRef Target, const InputInfo &Output,
                                    const InputInfo &Input, const ArgList &Args) const {
  // If this is a dry run, do not create the compilation database file.
  if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
    return;

  using llvm::yaml::escape;
  const Driver &D = getToolChain().getDriver();

  if (!CompilationDatabase) {
    std::error_code EC;
    auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text);
    if (EC) {
      D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
                                                       << EC.message();
      return;
    }
    CompilationDatabase = std::move(File);
  }
  auto &CDB = *CompilationDatabase;
  SmallString<128> Buf;
  if (llvm::sys::fs::current_path(Buf))
    Buf = ".";
  CDB << "{ \"directory\": \"" << escape(Buf) << "\"";
  CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\"";
  CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
  CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\"";
  Buf = "-x";
  Buf += types::getTypeName(Input.getType());
  CDB << ", \"" << escape(Buf) << "\"";
  if (!D.SysRoot.empty() && !Args.hasArg(options::OPT__sysroot_EQ)) {
    Buf = "--sysroot=";
    Buf += D.SysRoot;
    CDB << ", \"" << escape(Buf) << "\"";
  }
  CDB << ", \"" << escape(Input.getFilename()) << "\"";
  for (auto &A: Args) {
    auto &O = A->getOption();
    // Skip language selection, which is positional.
    if (O.getID() == options::OPT_x)
      continue;
    // Skip writing dependency output and the compilation database itself.
    if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group)
      continue;
    // Skip inputs.
    if (O.getKind() == Option::InputClass)
      continue;
    // All other arguments are quoted and appended.
    ArgStringList ASL;
    A->render(Args, ASL);
    for (auto &it: ASL)
      CDB << ", \"" << escape(it) << "\"";
  }
  Buf = "--target=";
  Buf += Target;
  CDB << ", \"" << escape(Buf) << "\"]},\n";
}

d3422 2
a3423 2
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
  const std::string &TripleStr = Triple.getTriple();
a3429 13
  // Check number of inputs for sanity. We need at least one input.
  assert(Inputs.size() >= 1 && "Must have at least one input.");
  const InputInfo &Input = Inputs[0];
  // CUDA compilation may have multiple inputs (source file + results of
  // device-side compilations). OpenMP device jobs also take the host IR as a
  // second input. All other jobs are expected to have exactly one
  // input.
  bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
  bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
  assert((IsCuda || (IsOpenMPDevice && Inputs.size() == 2) ||
          Inputs.size() == 1) &&
         "Unable to handle multiple inputs.");

a3434 1
  bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
d3436 8
a3443 13
  // Adjust IsWindowsXYZ for CUDA compilations.  Even when compiling in device
  // mode (i.e., getToolchain().getTriple() is NVPTX, not Windows), we need to
  // pass Windows-specific flags to cc1.
  if (IsCuda) {
    const llvm::Triple *AuxTriple = getToolChain().getAuxTriple();
    IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
    IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment();
    IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment();
  }

  // C++ is not supported for IAMCU.
  if (IsIAMCU && types::isCXX(Input.getType()))
    D.Diag(diag::err_drv_clang_unsupported) << "C++ for IAMCU";
d3454 1
a3454 5
  if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) {
    DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args);
    Args.ClaimAllArgs(options::OPT_MJ);
  }

d3456 11
a3466 12
    // We have to pass the triple of the host if compiling for a CUDA device and
    // vice-versa.
    std::string NormalizedTriple;
    if (JA.isDeviceOffloading(Action::OFK_Cuda))
      NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>()
                             ->getTriple()
                             .normalize();
    else
      NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Cuda>()
                             ->getTriple()
                             .normalize();

d3468 3
a3470 1
    CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
a3517 2
    else if (JA.getType() == types::TY_ModuleFile)
      CmdArgs.push_back("-emit-module-interface");
a3568 11
  // Embed-bitcode option.
  if (C.getDriver().embedBitcodeInObject() &&
      (isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
    // Add flags implied by -fembed-bitcode.
    Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
    // Disable all llvm IR level optimizations.
    CmdArgs.push_back("-disable-llvm-passes");
  }
  if (C.getDriver().embedBitcodeMarkerOnly())
    CmdArgs.push_back("-fembed-bitcode=marker");

a3577 2
  // Discard LLVM value names in -asserts builds.
  CmdArgs.push_back("-discard-value-names");
a3601 1
      CmdArgs.push_back("-analyzer-checker=apiModeling");
d3603 2
a3604 11
    if (!IsWindowsMSVC) {
      CmdArgs.push_back("-analyzer-checker=unix");
    } else {
      // Enable "unix" checkers that also work on Windows.
      CmdArgs.push_back("-analyzer-checker=unix.API");
      CmdArgs.push_back("-analyzer-checker=unix.Malloc");
      CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof");
      CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator");
      CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg");
      CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
    }
d3659 1
a3659 1
      ParsePICArgs(getToolChain(), Args);
a3661 7

  if ((RelocationModel == llvm::Reloc::ROPI ||
       RelocationModel == llvm::Reloc::ROPI_RWPI) &&
      types::isCXX(Input.getType()) &&
      !Args.hasArg(options::OPT_fallow_unsupported))
    D.Diag(diag::err_drv_ropi_incompatible_with_cxx);

d3669 4
a3672 2
    if (IsPIE)
      CmdArgs.push_back("-pic-is-pie");
d3698 3
a3700 8
      StringRef Map = A->getValue();
      if (!llvm::sys::fs::exists(Map)) {
        D.Diag(diag::err_drv_no_such_file) << Map;
      } else {
        CmdArgs.push_back("-frewrite-map-file");
        CmdArgs.push_back(A->getValue());
        A->claim();
      }
a3710 8
  if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
                    true))
    CmdArgs.push_back("-fno-jump-tables");

  if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
                    options::OPT_fno_preserve_as_comments, true))
    CmdArgs.push_back("-fno-preserve-as-comments");

d3730 1
a3730 1
    CmdArgs.push_back("-fdefault-calling-conv=stdcall");
a3754 3
  if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return,
                    true))
    CmdArgs.push_back("-fno-strict-return");
a3868 13
  if (!TrappingMath)
    CmdArgs.push_back("-fno-trapping-math");


  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fdenormal_fp_math_EQ))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations)
      Args.AddLastArg(CmdArgs, options::OPT_fdenormal_fp_math_EQ);

d3926 3
a3928 5
  // Enable -mconstructor-aliases except on darwin, where we have to work around
  // a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
  // aliases aren't supported.
  if (!getToolChain().getTriple().isOSDarwin() &&
      !getToolChain().getTriple().isNVPTX())
a3940 6
  if (Args.hasFlag(options::OPT_mpie_copy_relocations,
                   options::OPT_mno_pie_copy_relocations,
                   false)) {
    CmdArgs.push_back("-mpie-copy-relocations");
  }

a4020 4
  case llvm::Triple::systemz:
    AddSystemZTargetArgs(Args, CmdArgs);
    break;

a4025 4
  case llvm::Triple::lanai:
    AddLanaiTargetArgs(Args, CmdArgs);
    break;

d4048 2
a4049 1
  codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
a4052 1
  types::ID InputType = Input.getType();
d4054 1
a4054 1
    AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
d4067 1
a4094 4
  bool splitDwarfInlining =
      Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
                   options::OPT_fno_split_dwarf_inlining, true);

d4104 3
a4106 14
      // This gets a bit more complicated if you've disabled inline info in the
      // skeleton CUs (splitDwarfInlining) - then there's value in composing
      // split-dwarf and line-tables-only, so let those compose naturally in
      // that case.
      // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
      if (SplitDwarfArg) {
        if (A->getIndex() > SplitDwarfArg->getIndex()) {
          if (DebugInfoKind == codegenoptions::NoDebugInfo ||
              (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
               splitDwarfInlining))
            SplitDwarfArg = nullptr;
        } else if (splitDwarfInlining)
          DebugInfoKind = codegenoptions::NoDebugInfo;
      }
d4109 1
a4109 1
      DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4128 2
a4129 2
  // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
  // argument parsing.
d4134 1
a4134 1
             DebugInfoKind != codegenoptions::NoDebugInfo) {
d4141 1
a4141 5
  // Column info is included by default for everything except PS4 and CodeView.
  // Clang doesn't track end columns, just starting columns, which, in theory,
  // is fine for CodeView (and PDB).  In practice, however, the Microsoft
  // debuggers don't handle missing end columns well, so it's better not to
  // include any column info.
d4143 1
a4143 1
                   /*Default=*/ !IsPS4CPU && !(IsWindowsMSVC && EmitCodeView)))
d4147 2
a4148 4
  // If -gline-tables-only is the last option it wins.
  if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
      Args.hasArg(options::OPT_gmodules)) {
    DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4157 1
a4157 4
    if (!splitDwarfInlining)
      CmdArgs.push_back("-fno-split-dwarf-inlining");
    if (DebugInfoKind == codegenoptions::NoDebugInfo)
      DebugInfoKind = codegenoptions::LimitedDebugInfo;
d4170 2
a4171 2
  if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
    DebugInfoKind = codegenoptions::FullDebugInfo;
d4195 5
a4199 1
  bool UseSeparateSections = isUseSeparateSections(Triple);
a4216 26
  if (Args.hasFlag(options::OPT_fxray_instrument,
                   options::OPT_fnoxray_instrument, false)) {
    const char *const XRayInstrumentOption = "-fxray-instrument";
    if (Triple.getOS() == llvm::Triple::Linux)
      switch (Triple.getArch()) {
      case llvm::Triple::x86_64:
      case llvm::Triple::arm:
      case llvm::Triple::aarch64:
        // Supported.
        break;
      default:
        D.Diag(diag::err_drv_clang_unsupported)
            << (std::string(XRayInstrumentOption) + " on " + Triple.str());
      }
    else
      D.Diag(diag::err_drv_clang_unsupported)
          << (std::string(XRayInstrumentOption) + " on non-Linux target OS");
    CmdArgs.push_back(XRayInstrumentOption);
    if (const Arg *A =
            Args.getLastArg(options::OPT_fxray_instruction_threshold_,
                            options::OPT_fxray_instruction_threshold_EQ)) {
      CmdArgs.push_back("-fxray-instruction-threshold");
      CmdArgs.push_back(A->getValue());
    }
  }

d4315 2
a4316 1
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);
a4343 1

a4547 1
  bool IsHosted = true;
d4549 1
a4549 1
      KernelOrKext) {
a4550 2
    IsHosted = false;
  }
d4558 1
a4558 1
  bool EmulatedTLSDefault = Triple.isAndroid() || Triple.isWindowsCygwinEnvironment();
d4570 1
a4570 2
  // Forward flags for OpenMP. We don't do this if the current action is an
  // device offloading action other than OpenMP.
d4572 4
a4575 6
                   options::OPT_fno_openmp, false) &&
      (JA.isDeviceOffloading(Action::OFK_None) ||
       JA.isDeviceOffloading(Action::OFK_OpenMP))) {
    switch (getToolChain().getDriver().getOpenMPRuntime(Args)) {
    case Driver::OMPRT_OMP:
    case Driver::OMPRT_IOMP5:
a4584 1
      Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
a4594 1
  }
d4663 9
a4671 4
  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                               options::OPT_fstack_protector_all,
                               options::OPT_fstack_protector_strong,
                               options::OPT_fstack_protector)) {
a4682 4
    // Only use a default stack protector on Darwin in case -ffreestanding
    // is not specified.
    if (Triple.isOSDarwin() && !IsHosted)
      StackProtectorLevel = 0;
a4751 40
  // Forward -cl options to -cc1
  if (Args.getLastArg(options::OPT_cl_opt_disable)) {
    CmdArgs.push_back("-cl-opt-disable");
  }
  if (Args.getLastArg(options::OPT_cl_strict_aliasing)) {
    CmdArgs.push_back("-cl-strict-aliasing");
  }
  if (Args.getLastArg(options::OPT_cl_single_precision_constant)) {
    CmdArgs.push_back("-cl-single-precision-constant");
  }
  if (Args.getLastArg(options::OPT_cl_finite_math_only)) {
    CmdArgs.push_back("-cl-finite-math-only");
  }
  if (Args.getLastArg(options::OPT_cl_kernel_arg_info)) {
    CmdArgs.push_back("-cl-kernel-arg-info");
  }
  if (Args.getLastArg(options::OPT_cl_unsafe_math_optimizations)) {
    CmdArgs.push_back("-cl-unsafe-math-optimizations");
  }
  if (Args.getLastArg(options::OPT_cl_fast_relaxed_math)) {
    CmdArgs.push_back("-cl-fast-relaxed-math");
  }
  if (Args.getLastArg(options::OPT_cl_mad_enable)) {
    CmdArgs.push_back("-cl-mad-enable");
  }
  if (Args.getLastArg(options::OPT_cl_no_signed_zeros)) {
    CmdArgs.push_back("-cl-no-signed-zeros");
  }
  if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
    std::string CLStdStr = "-cl-std=";
    CLStdStr += A->getValue();
    CmdArgs.push_back(Args.MakeArgString(CLStdStr));
  }
  if (Args.getLastArg(options::OPT_cl_denorms_are_zero)) {
    CmdArgs.push_back("-cl-denorms-are-zero");
  }
  if (Args.getLastArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt)) {
    CmdArgs.push_back("-cl-fp32-correctly-rounded-divide-sqrt");
  }

a4805 6
  if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
                   false) &&
      types::isCXX(InputType)) {
    CmdArgs.push_back("-fcoroutines-ts");
  }

d4809 1
a4809 1
  bool HaveClangModules = false;
d4815 1
a4815 1
      HaveClangModules = true;
a4818 6
  bool HaveAnyModules = HaveClangModules;
  if (Args.hasArg(options::OPT_fmodules_ts)) {
    CmdArgs.push_back("-fmodules-ts");
    HaveAnyModules = true;
  }

d4820 1
a4820 1
  // this is enabled if we are using Clang's flavor of precompiled modules.
d4822 1
a4822 1
                   options::OPT_fno_implicit_module_maps, HaveClangModules)) {
d4842 24
a4865 9
                    options::OPT_fno_implicit_modules, HaveClangModules)) {
    if (HaveAnyModules)
      CmdArgs.push_back("-fno-implicit-modules");
  } else if (HaveAnyModules) {
    // -fmodule-cache-path specifies where our implicitly-built module files
    // should be written.
    SmallString<128> Path;
    if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
      Path = A->getValue();
a4883 33
  if (HaveAnyModules) {
    // -fprebuilt-module-path specifies where to load the prebuilt module files.
    for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path))
      CmdArgs.push_back(Args.MakeArgString(
          std::string("-fprebuilt-module-path=") + A->getValue()));
  }
      
  // -fmodule-name specifies the module that is currently being built (or
  // used for header checking by -fmodule-maps).
  Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);

  // -fmodule-map-file can be used to specify files containing module
  // definitions.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);

  // -fbuiltin-module-map can be used to load the clang
  // builtin headers modulemap file.
  if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
    SmallString<128> BuiltinModuleMap(getToolChain().getDriver().ResourceDir);
    llvm::sys::path::append(BuiltinModuleMap, "include");
    llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
    if (llvm::sys::fs::exists(BuiltinModuleMap)) {
      CmdArgs.push_back(Args.MakeArgString("-fmodule-map-file=" +
                                           BuiltinModuleMap));
    }
  }

  // -fmodule-file can be used to specify files containing precompiled modules.
  if (HaveAnyModules)
    Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
  else
    Args.ClaimAllArgs(options::OPT_fmodule_file);

d4886 1
a4886 1
  if (HaveClangModules && C.isForDiagnostics()) {
d4897 1
a4897 1
  if (HaveClangModules)
d4915 3
a4917 5
    CmdArgs.push_back(
        Args.MakeArgString("-fbuild-session-timestamp=" +
                           Twine((uint64_t)Status.getLastModificationTime()
                                     .time_since_epoch()
                                     .count())));
a4929 1
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
d4996 3
a4998 2
  VersionTuple MSVT =
      getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args);
d5005 4
a5008 19
    StringRef LanguageStandard;
    if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
      LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
                             .Case("c++14", "-std=c++14")
                             .Case("c++latest", "-std=c++1z")
                             .Default("");
      if (LanguageStandard.empty())
        D.Diag(clang::diag::warn_drv_unused_argument)
            << StdArg->getAsString(Args);
    }

    if (LanguageStandard.empty()) {
      if (IsMSVC2015Compatible)
        LanguageStandard = "-std=c++14";
      else
        LanguageStandard = "-std=c++11";
    }

    CmdArgs.push_back(LanguageStandard.data());
d5049 2
a5050 7
  if (Arg* InlineArg = Args.getLastArg(options::OPT_finline_functions,
                                       options::OPT_finline_hint_functions,
                                       options::OPT_fno_inline_functions))
    InlineArg->render(Args, CmdArgs);

  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
                  options::OPT_fno_experimental_new_pass_manager);
d5055 1
a5055 1
  // legacy is the default. Except for deployment target of 10.5,
d5117 16
d5139 3
d5159 1
a5159 2
  if (Args.hasArg(options::OPT_fsjlj_exceptions) ||
      getToolChain().UseSjLjExceptions(Args))
a5166 7
  // -frelaxed-template-template-args is off by default, as it is a severe
  // breaking change until a corresponding change to template partial ordering
  // is provided.
  if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
                   options::OPT_fno_relaxed_template_template_args, false))
    CmdArgs.push_back("-frelaxed-template-template-args");

a5172 18
  // -faligned-allocation is on by default in C++17 onwards and otherwise off
  // by default.
  if (Arg *A = Args.getLastArg(options::OPT_faligned_allocation,
                               options::OPT_fno_aligned_allocation,
                               options::OPT_faligned_new_EQ)) {
    if (A->getOption().matches(options::OPT_fno_aligned_allocation))
      CmdArgs.push_back("-fno-aligned-allocation");
    else
      CmdArgs.push_back("-faligned-allocation");
  }

  // The default new alignment can be specified using a dedicated option or via
  // a GCC-compatible option that also turns on aligned allocation.
  if (Arg *A = Args.getLastArg(options::OPT_fnew_alignment_EQ,
                               options::OPT_faligned_new_EQ))
    CmdArgs.push_back(
        Args.MakeArgString(Twine("-fnew-alignment=") + A->getValue()));

d5240 1
a5240 1
    if (!value.equals_lower("utf-8"))
d5248 1
a5248 1
    if (!value.equals_lower("utf-8"))
a5273 4
  if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
                   options::OPT_fno_diagnostics_show_hotness, false))
    CmdArgs.push_back("-fdiagnostics-show-hotness");

d5289 7
a5295 6
  // Color diagnostics are parsed by the driver directly from argv
  // and later re-parsed to construct this job; claim any possible
  // color diagnostic here to avoid warn_drv_unused_argument and
  // diagnose bad OPT_fdiagnostics_color_EQ values.
  for (Arg *A : Args) {
    const Option &O = A->getOption();
d5302 18
a5319 3
    if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
      StringRef Value(A->getValue());
      if (Value != "always" && Value != "never" && Value != "auto")
d5321 1
a5321 1
              << ("-fdiagnostics-color=" + Value).str();
a5322 1
    A->claim();
d5324 2
a5325 1
  if (D.getDiags().getDiagnosticOptions().ShowColors)
a5334 3
  if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
    CmdArgs.push_back("-fdiagnostics-absolute-paths");

a5378 4
  if (Arg *A = Args.getLastArg(
          options::OPT_fsanitize_undefined_strip_path_components_EQ))
    A->render(Args, CmdArgs);

a5407 34
  if (Args.hasFlag(options::OPT_fsave_optimization_record,
                   options::OPT_fno_save_optimization_record, false)) {
    CmdArgs.push_back("-opt-record-file");

    const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
    if (A) {
      CmdArgs.push_back(A->getValue());
    } else {
      SmallString<128> F;
      if (Output.isFilename() && (Args.hasArg(options::OPT_c) ||
                                  Args.hasArg(options::OPT_S))) {
        F = Output.getFilename();
      } else {
        // Use the input filename.
        F = llvm::sys::path::stem(Input.getBaseInput());

        // If we're compiling for an offload architecture (i.e. a CUDA device),
        // we need to make the file name for the device compilation different
        // from the host compilation.
        if (!JA.isDeviceOffloading(Action::OFK_None) &&
            !JA.isDeviceOffloading(Action::OFK_Host)) {
          llvm::sys::path::replace_extension(F, "");
          F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
                                                   Triple.normalize());
          F += "-";
          F += JA.getOffloadingArch();
        }
      }

      llvm::sys::path::replace_extension(F, "opt.yaml");
      CmdArgs.push_back(Args.MakeArgString(F));
    }
  }

d5410 1
a5410 1
// FIXME: Now that PR4941 has been fixed this can be enabled.
d5428 1
a5428 1
      (C.isForDiagnostics() && !HaveAnyModules))
a5463 27
  // Setup statistics file output.
  if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) {
    StringRef SaveStats = A->getValue();

    SmallString<128> StatsFile;
    bool DoSaveStats = false;
    if (SaveStats == "obj") {
      if (Output.isFilename()) {
        StatsFile.assign(Output.getFilename());
        llvm::sys::path::remove_filename(StatsFile);
      }
      DoSaveStats = true;
    } else if (SaveStats == "cwd") {
      DoSaveStats = true;
    } else {
      D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
    }

    if (DoSaveStats) {
      StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
      llvm::sys::path::append(StatsFile, BaseName);
      llvm::sys::path::replace_extension(StatsFile, "stats");
      CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") +
                                           StatsFile));
    }
  }

d5472 2
a5473 2
    if (StringRef(A->getValue(0)) == "-disable-llvm-passes") {
      CmdArgs.push_back("-disable-llvm-passes");
d5481 1
a5481 7
  // When -fembed-bitcode is enabled, optimized bitcode is emitted because it
  // has slightly different breakdown between stages.
  // FIXME: -fembed-bitcode -save-temps will save optimized bitcode instead of
  // pristine IR generated by the frontend. Ideally, a new compile action should
  // be added so both IR can be captured.
  if (C.getDriver().isSaveTempsEnabled() &&
      !C.getDriver().embedBitcodeInObject() && isa<CompileJobAction>(JA))
a5542 41
  // OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
  // to specify the result of the compile phase on the host, so the meaningful
  // device declarations can be identified. Also, -fopenmp-is-device is passed
  // along to tell the frontend that it is generating code for a device, so that
  // only the relevant declarations are emitted.
  if (IsOpenMPDevice && Inputs.size() == 2) {
    CmdArgs.push_back("-fopenmp-is-device");
    CmdArgs.push_back("-fopenmp-host-ir-file-path");
    CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
  }

  // For all the host OpenMP offloading compile jobs we need to pass the targets
  // information using -fopenmp-targets= option.
  if (isa<CompileJobAction>(JA) && JA.isHostOffloading(Action::OFK_OpenMP)) {
    SmallString<128> TargetInfo("-fopenmp-targets=");

    Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
    assert(Tgts && Tgts->getNumValues() &&
           "OpenMP offloading has to have targets specified.");
    for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
      if (i)
        TargetInfo += ',';
      // We need to get the string from the triple because it may be not exactly
      // the same as the one we get directly from the arguments.
      llvm::Triple T(Tgts->getValue(i));
      TargetInfo += T.getTriple();
    }
    CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
  }

  bool WholeProgramVTables =
      Args.hasFlag(options::OPT_fwhole_program_vtables,
                   options::OPT_fno_whole_program_vtables, false);
  if (WholeProgramVTables) {
    if (!D.isUsingLTO())
      D.Diag(diag::err_drv_argument_only_allowed_with)
          << "-fwhole-program-vtables"
          << "-flto";
    CmdArgs.push_back("-fwhole-program-vtables");
  }

a5550 6
  } else if (Args.hasArg(options::OPT__SLASH_fallback) &&
             isa<PrecompileJobAction>(JA)) {
    // In /fallback builds, run the main compilation even if the pch generation
    // fails, so that the main compilation's fallback to cl.exe runs.
    C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec,
                                                        CmdArgs, Inputs));
d5558 1
a5558 1
  if (SplitDwarf && Output.getType() == types::TY_Object)
d5714 4
a5717 3
  bool Synch = false;
  bool Asynch = false;
  bool NoUnwindC = false;
d5726 2
a5727 1
/// - c: Assume that extern "C" functions are implicitly nounwind.
a5738 2
        if (EH.Asynch)
          EH.Synch = false;
d5741 1
a5741 1
        EH.NoUnwindC = maybeConsumeDash(EHVal, I);
a5744 2
        if (EH.Synch)
          EH.Asynch = false;
a5752 8
  // The /GX, /GX- flags are only processed if there are not /EH flags.
  // The default is that /GX is not specified.
  if (EHArgs.empty() &&
      Args.hasFlag(options::OPT__SLASH_GX, options::OPT__SLASH_GX_,
                   /*default=*/false)) {
    EH.Synch = true;
    EH.NoUnwindC = true;
  }
d5757 2
a5758 3
void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
                           ArgStringList &CmdArgs,
                           codegenoptions::DebugInfoKind *DebugInfoKind,
a5788 1
    CmdArgs.push_back("-flto-visibility-public-std");
a5793 1
    CmdArgs.push_back("-flto-visibility-public-std");
d5822 8
a5829 17
  // This controls whether or not we emit stack-protector instrumentation.
  // In MSVC, Buffer Security Check (/GS) is on by default.
  if (Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_,
                   /*default=*/true)) {
    CmdArgs.push_back("-stack-protector");
    CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong)));
  }

  // Emit CodeView if -Z7, -Zd, or -gline-tables-only are present.
  if (Arg *DebugInfoArg =
          Args.getLastArg(options::OPT__SLASH_Z7, options::OPT__SLASH_Zd,
                          options::OPT_gline_tables_only)) {
    *EmitCodeView = true;
    if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
      *DebugInfoKind = codegenoptions::LimitedDebugInfo;
    else
      *DebugInfoKind = codegenoptions::DebugLineTablesOnly;
a5830 3
  } else {
    *EmitCodeView = false;
  }
d5834 1
d5836 1
a5836 2
    if (types::isCXX(InputType))
      CmdArgs.push_back("-fcxx-exceptions");
a5838 2
  if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
    CmdArgs.push_back("-fexternc-nounwind");
a5884 9
  if (Args.getLastArg(options::OPT__SLASH_Gd))
     CmdArgs.push_back("-fdefault-calling-conv=cdecl");
  else if (Args.getLastArg(options::OPT__SLASH_Gr))
     CmdArgs.push_back("-fdefault-calling-conv=fastcall");
  else if (Args.getLastArg(options::OPT__SLASH_Gz))
     CmdArgs.push_back("-fdefault-calling-conv=stdcall");
  else if (Args.getLastArg(options::OPT__SLASH_Gv))
     CmdArgs.push_back("-fdefault-calling-conv=vectorcall");

a5913 14
void ClangAs::AddX86TargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  }
}

d5923 3
a5925 2
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
  const std::string &TripleStr = Triple.getTriple();
a5977 14
  bool WantDebug = false;
  unsigned DwarfVersion = 0;
  Args.ClaimAllArgs(options::OPT_g_Group);
  if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    WantDebug = !A->getOption().matches(options::OPT_g0) &&
                !A->getOption().matches(options::OPT_ggdb0);
    if (WantDebug)
      DwarfVersion = DwarfVersionNum(A->getSpelling());
  }
  if (DwarfVersion == 0)
    DwarfVersion = getToolChain().GetDefaultDwarfVersion();

  codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;

d5980 16
a5995 6
    // You might think that it would be ok to set DebugInfoKind outside of
    // the guard for source type, however there is a test which asserts
    // that some assembler invocation receives no -debug-info-kind,
    // and it's not clear whether that test is just overly restrictive.
    DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo
                               : codegenoptions::NoDebugInfo);
a6006 2
  RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
                          llvm::DebuggerKind::Default);
d6014 1
a6014 1
      ParsePICArgs(getToolChain(), Args);
a6054 5

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    AddX86TargetArgs(Args, CmdArgs);
    break;
a6087 128
void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const llvm::opt::ArgList &TCArgs,
                                  const char *LinkingOutput) const {
  // The version with only one output is expected to refer to a bundling job.
  assert(isa<OffloadBundlingJobAction>(JA) && "Expecting bundling job!");

  // The bundling command looks like this:
  // clang-offload-bundler -type=bc
  //   -targets=host-triple,openmp-triple1,openmp-triple2
  //   -outputs=input_file
  //   -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"

  ArgStringList CmdArgs;

  // Get the type.
  CmdArgs.push_back(TCArgs.MakeArgString(
      Twine("-type=") + types::getTypeTempSuffix(Output.getType())));

  assert(JA.getInputs().size() == Inputs.size() &&
         "Not have inputs for all dependence actions??");

  // Get the targets.
  SmallString<128> Triples;
  Triples += "-targets=";
  for (unsigned I = 0; I < Inputs.size(); ++I) {
    if (I)
      Triples += ',';

    Action::OffloadKind CurKind = Action::OFK_Host;
    const ToolChain *CurTC = &getToolChain();
    const Action *CurDep = JA.getInputs()[I];

    if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
      OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
        CurKind = A->getOffloadingDeviceKind();
        CurTC = TC;
      });
    }
    Triples += Action::GetOffloadKindName(CurKind);
    Triples += '-';
    Triples += CurTC->getTriple().normalize();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(Triples));

  // Get bundled file command.
  CmdArgs.push_back(
      TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));

  // Get unbundled files command.
  SmallString<128> UB;
  UB += "-inputs=";
  for (unsigned I = 0; I < Inputs.size(); ++I) {
    if (I)
      UB += ',';
    UB += Inputs[I].getFilename();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(UB));

  // All the inputs are encoded as commands.
  C.addCommand(llvm::make_unique<Command>(
      JA, *this,
      TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
      CmdArgs, None));
}

void OffloadBundler::ConstructJobMultipleOutputs(
    Compilation &C, const JobAction &JA, const InputInfoList &Outputs,
    const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs,
    const char *LinkingOutput) const {
  // The version with multiple outputs is expected to refer to a unbundling job.
  auto &UA = cast<OffloadUnbundlingJobAction>(JA);

  // The unbundling command looks like this:
  // clang-offload-bundler -type=bc
  //   -targets=host-triple,openmp-triple1,openmp-triple2
  //   -inputs=input_file
  //   -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
  //   -unbundle

  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Expecting to unbundle a single file!");
  InputInfo Input = Inputs.front();

  // Get the type.
  CmdArgs.push_back(TCArgs.MakeArgString(
      Twine("-type=") + types::getTypeTempSuffix(Input.getType())));

  // Get the targets.
  SmallString<128> Triples;
  Triples += "-targets=";
  auto DepInfo = UA.getDependentActionsInfo();
  for (unsigned I = 0; I < DepInfo.size(); ++I) {
    if (I)
      Triples += ',';

    auto &Dep = DepInfo[I];
    Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
    Triples += '-';
    Triples += Dep.DependentToolChain->getTriple().normalize();
  }

  CmdArgs.push_back(TCArgs.MakeArgString(Triples));

  // Get bundled file command.
  CmdArgs.push_back(
      TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));

  // Get unbundled files command.
  SmallString<128> UB;
  UB += "-outputs=";
  for (unsigned I = 0; I < Outputs.size(); ++I) {
    if (I)
      UB += ',';
    UB += Outputs[I].getFilename();
  }
  CmdArgs.push_back(TCArgs.MakeArgString(UB));
  CmdArgs.push_back("-unbundle");

  // All the inputs are encoded as commands.
  C.addCommand(llvm::make_unique<Command>(
      JA, *this,
      TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
      CmdArgs, None));
}

d6200 1
a6200 1
  const std::string &customGCCName = D.getCCCGenericGCCName();
d6465 1
a6465 1
  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
d6524 1
a6524 2
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  CmdArgs.push_back("-shared");
d6548 1
a6548 4

  const ToolChain &ToolChain = getToolChain();
  const Driver &D = ToolChain.getDriver();
  const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
d6553 6
a6558 45
  // Enable garbage collection of unused input sections by default, since code
  // size is of particular importance. This is significantly facilitated by
  // the enabling of -ffunction-sections and -fdata-sections in
  // Clang::ConstructJob.
  if (areOptimizationsEnabled(Args))
    CmdArgs.push_back("--gc-sections");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");
  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("--strip-all");
  if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("-shared");
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-Bstatic");

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("rcrt1.o")));
    else if (Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
  }

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX())
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");

    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lcompiler_rt");
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
d6560 1
a6562 1

a6680 8
bool mips::hasCompactBranches(StringRef &CPU) {
  // mips32r6 and mips64r6 have compact branches.
  return llvm::StringSwitch<bool>(CPU)
      .Case("mips32r6", true)
      .Case("mips64r6", true)
      .Default(false);
}

a6705 10
bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
  if (!Triple.isAndroid())
    return false;

  // Android MIPS32R6 defaults to FP64A.
  return llvm::StringSwitch<bool>(CPUName)
      .Case("mips32r6", true)
      .Default(false);
}

d6709 1
a6709 2
      Triple.getVendor() != llvm::Triple::MipsTechnologies &&
      !Triple.isAndroid())
a6777 1
  unsigned ArchKind = llvm::ARM::parseArch(Str);
d6782 1
a6782 3
  else if (ArchKind == llvm::ARM::AK_ARMV6M ||
           ArchKind == llvm::ARM::AK_ARMV7M ||
           ArchKind == llvm::ARM::AK_ARMV7EM) {
a6838 8
  CmdArgs.push_back("--no-dynamic-linker");

  // Provide PIE linker flags in case PIE is default for the architecture.
  if (ToolChain.isPIEDefault()) {
    CmdArgs.push_back("-pie");
    CmdArgs.push_back("-zrelro");
  }

d6861 1
a6861 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d6863 1
a6863 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a6972 23
/// \brief Pass -no_deduplicate to ld64 under certain conditions:
///
/// - Either -O0 or -O1 is explicitly specified
/// - No -O option is specified *and* this is a compile+link (implicit -O0)
///
/// Also do *not* add -no_deduplicate when no -O option is specified and this
/// is just a link (we can't imply -O0)
static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O0))
      return true;
    if (A->getOption().matches(options::OPT_O))
      return llvm::StringSwitch<bool>(A->getValue())
                    .Case("1", true)
                    .Default(false);
    return false; // OPT_Ofast & OPT_O4
  }

  if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
    return true;
  return false;
}

d6979 1
a6979 1
  unsigned Version[5] = {0, 0, 0, 0, 0};
d6981 4
a6984 1
    if (!Driver::GetReleaseVersion(A->getValue(), Version))
d7013 17
a7031 21
  // Use -lto_library option to specify the libLTO.dylib path. Try to find
  // it in clang installed libraries. ld64 will only look at this argument
  // when it actually uses LTO, so libLTO.dylib only needs to exist at link
  // time if ld64 decides that it needs to use LTO.
  // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
  // next to it. That's ok since ld64 using a libLTO.dylib not matching the
  // clang version won't work anyways.
  if (Version[0] >= 133) {
    // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
    StringRef P = llvm::sys::path::parent_path(D.Dir);
    SmallString<128> LibLTOPath(P);
    llvm::sys::path::append(LibLTOPath, "lib");
    llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
    CmdArgs.push_back("-lto_library");
    CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
  }

  // ld64 version 262 and above run the deduplicate pass by default.
  if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
    CmdArgs.push_back("-no_deduplicate");

a7118 9
  // for embed-bitcode, use -bitcode_bundle in linker command
  if (C.getDriver().embedBitcodeEnabled()) {
    // Check if the toolchain supports bitcode build flow.
    if (MachOTC.SupportsEmbeddedBitcode())
      CmdArgs.push_back("-bitcode_bundle");
    else
      D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
  }

a7203 18
  // For LTO, pass the name of the optimization record file.
  if (Args.hasFlag(options::OPT_fsave_optimization_record,
                   options::OPT_fno_save_optimization_record, false)) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-lto-pass-remarks-output");
    CmdArgs.push_back("-mllvm");

    SmallString<128> F;
    F = Output.getFilename();
    F += ".opt.yaml";
    CmdArgs.push_back(Args.MakeArgString(F));

    if (getLastProfileUseArg(Args)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-lto-pass-remarks-with-hotness");
    }
  }

d7233 1
a7233 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
a7275 7
  if (unsigned Parallelism =
          getLTOParallelism(Args, getToolChain().getDriver())) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(
        Args.MakeArgString(Twine("-threads=") + llvm::to_string(Parallelism)));
  }

d7451 1
a7451 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d7624 1
a7624 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d7743 1
a7743 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
a7918 1
  CmdArgs.push_back("--eh-frame-hdr");
d7924 1
d8006 1
a8006 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d8009 1
a8009 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d8216 3
a8218 1
    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple());
d8306 1
a8306 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d8311 1
a8311 1
  if (Major >= 7 || Major == 0) {
a8313 1
    case llvm::Triple::aarch64_be:
d8382 3
d8391 1
a8391 1
      ParsePICArgs(getToolChain(), Args);
d8470 1
a8470 1
    // for now replace it with -mcpu=cortex-a15 to avoid a lower
d8474 2
a8475 2
        StringRef(A->getValue()).equals_lower("krait"))
      CmdArgs.push_back("-mcpu=cortex-a15");
a8596 1
  bool IsIAMCU = Triple.isOSIAMCU();
d8613 1
a8613 1
  if (StaticLibgcc && !isAndroid && !IsIAMCU)
d8627 66
a8704 1
    case llvm::Triple::Fuchsia:
d8710 1
a8710 10
    // Make sure libgcc is not used under MSVC environment by default
    if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
      // Issue error diagnostic if libgcc is explicitly specified
      // through command line as --rtlib option argument.
      if (Args.hasArg(options::OPT_rtlib_EQ)) {
        TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
            << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC";
      }
    } else
      AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
a8717 2
    if (T.isOSIAMCU())
      return "elf_iamcu";
d8728 1
a8728 1
    return "armelfb_linux_eabi";
d8759 1
a8759 1
    return nullptr;
d8772 2
a8773 1
  const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
a8776 1
  const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
a8816 8
  // Most Android ARM64 targets should enable the linker fix for erratum
  // 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
  if (Arch == llvm::Triple::aarch64 && isAndroid) {
    std::string CPU = getCPUName(Args, Triple);
    if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
      CmdArgs.push_back("--fix-cortex-a53-843419");
  }

d8824 2
a8825 7
  if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back(LDMOption);
  } else {
    D.Diag(diag::err_target_unknown_triple) << Triple.str();
    return;
  }
d8837 7
a8843 10
  if (!Args.hasArg(options::OPT_static)) {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");

    if (!Args.hasArg(options::OPT_shared)) {
      const std::string Loader =
          D.DyldPrefix + ToolChain.getDynamicLinker(Args);
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(Loader));
    }
d8850 1
a8850 1
    if (!isAndroid && !IsIAMCU) {
d8866 9
a8874 12
    if (IsIAMCU)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
    else {
      const char *crtbegin;
      if (Args.hasArg(options::OPT_static))
        crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
      else if (Args.hasArg(options::OPT_shared))
        crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
      else if (IsPIE)
        crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
      else
        crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
d8876 2
a8877 3
      if (HasCRTBeginEndFiles)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
    }
d8889 1
a8889 1
    AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
d8895 1
a8895 2
  bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a8920 3
      if (NeedsXRayDeps)
        linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);

d8931 2
a8932 2
        switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
        case Driver::OMPRT_OMP:
d8935 1
a8935 1
        case Driver::OMPRT_GOMP:
d8942 1
a8942 1
        case Driver::OMPRT_IOMP5:
d8945 1
a8945 1
        case Driver::OMPRT_Unknown:
a8948 2
        if (JA.isHostOffloading(Action::OFK_OpenMP))
          CmdArgs.push_back("-lomptarget");
a8955 3
      if (Args.hasArg(options::OPT_fsplit_stack))
        CmdArgs.push_back("--wrap=pthread_create");

a8957 4
      // Add IAMCU specific libs, if needed.
      if (IsIAMCU)
        CmdArgs.push_back("-lgloss");

a8961 7

      // Add IAMCU specific libs (outside the group), if needed.
      if (IsIAMCU) {
        CmdArgs.push_back("--as-needed");
        CmdArgs.push_back("-lsoftfp");
        CmdArgs.push_back("--no-as-needed");
      }
d8964 1
a8964 1
    if (!Args.hasArg(options::OPT_nostartfiles) && !IsIAMCU) {
a8979 3
  // Add OpenMP offloading linker script args if required.
  AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);

d9089 1
a9089 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
a9154 106
void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  const toolchains::Fuchsia &ToolChain =
      static_cast<const toolchains::Fuchsia &>(getToolChain());
  const Driver &D = ToolChain.getDriver();

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  if (llvm::sys::path::stem(Exec).equals_lower("lld")) {
    CmdArgs.push_back("-flavor");
    CmdArgs.push_back("gnu");
  }

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  if (Args.hasArg(options::OPT_r))
    CmdArgs.push_back("-r");
  else
    CmdArgs.push_back("--build-id");

  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("--eh-frame-hdr");

  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-Bstatic");
  else if (Args.hasArg(options::OPT_shared))
    CmdArgs.push_back("-shared");

  if (!Args.hasArg(options::OPT_static)) {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");

    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(D.DyldPrefix + "ld.so.1"));
    }
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_u);

  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (Args.hasArg(options::OPT_static))
      CmdArgs.push_back("-Bdynamic");

    if (D.CCCIsCXX()) {
      bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
                                 !Args.hasArg(options::OPT_static);
      if (OnlyLibstdcxxStatic)
        CmdArgs.push_back("-Bstatic");
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (OnlyLibstdcxxStatic)
        CmdArgs.push_back("-Bdynamic");
      CmdArgs.push_back("-lm");
    }

    AddRunTimeLibs(ToolChain, D, CmdArgs, Args);

    if (Args.hasArg(options::OPT_pthread) ||
        Args.hasArg(options::OPT_pthreads))
      CmdArgs.push_back("-lpthread");

    if (Args.hasArg(options::OPT_fsplit_stack))
      CmdArgs.push_back("--wrap=pthread_create");

    CmdArgs.push_back("-lc");
  }

  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

d9201 1
a9201 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d9322 1
a9322 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d9445 1
a9445 1
                                               UniversalCRTLibPath));
d9451 2
a9452 2
      CmdArgs.push_back(
          Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
a9454 4
  if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
    for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
      CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));

d9457 1
a9457 2
  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7,
                  options::OPT__SLASH_Zd))
d9473 1
a9473 2
    if (TC.getSanitizerArgs().needsSharedAsanRt() ||
        Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
d9478 1
a9478 4
      CmdArgs.push_back(Args.MakeArgString(
          TC.getArch() == llvm::Triple::x86
              ? "-include:___asan_seh_interceptor"
              : "-include:__asan_seh_interceptor"));
d9495 2
a9496 2
    switch (TC.getDriver().getOpenMPRuntime(Args)) {
    case Driver::OMPRT_OMP:
d9499 1
a9499 1
    case Driver::OMPRT_IOMP5:
d9502 1
a9502 1
    case Driver::OMPRT_GOMP:
d9504 1
a9504 1
    case Driver::OMPRT_Unknown:
a9509 6
  // Add compiler-rt lib in case if it was explicitly
  // specified as an argument for --rtlib option.
  if (!Args.hasArg(options::OPT_nostdlib)) {
    AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
  }

a9617 5

  if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
                   /*default=*/false))
    CmdArgs.push_back("/GS-");

a9640 2
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
a9648 12
  // Use MSVC's default threadsafe statics behaviour unless there was a flag.
  if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
                               options::OPT_fno_threadsafe_statics)) {
    CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
                          ? "/Zc:threadSafeInit"
                          : "/Zc:threadSafeInit-");
  }

  // Pass through all unknown arguments so that the fallback command can see
  // them too.
  Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);

d9827 1
a9827 1
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
d9951 1
a9951 1
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d10105 1
a10105 1
  AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
d10133 6
a10138 6
      // Make sure the dynamic runtime thunk is not optimized out at link time
      // to ensure proper SEH handling.
      CmdArgs.push_back(Args.MakeArgString("--undefined"));
      CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
                                               ? "___asan_seh_interceptor"
                                               : "__asan_seh_interceptor"));
d10166 1
d10172 5
a10176 8
  Args.AddAllArgsExcept(
      CmdArgs,
      {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
       options::OPT_D, options::OPT_U, options::OPT_f_Group,
       options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
       options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ},
      {options::OPT_fno_split_dwarf_inlining});
  Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.
d10216 1
a10216 4
  const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
  if (CPUArg)
    CmdArgs.push_back(
        Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
a10248 2
  // Silence warning if the args contain both -nostdlib and -stdlib=.
  Args.getLastArg(options::OPT_stdlib_EQ);
d10283 1
a10283 2
  bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
d10286 2
a10287 9
    if (NeedsSanitizerDeps)
      linkSanitizerRuntimeDeps(TC, CmdArgs);
    if (C.getDriver().CCCIsCXX()) {
      if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
        CmdArgs.push_back("-lc++");
        CmdArgs.push_back("-lc++abi");
      } else
        CmdArgs.push_back("-lstdc++");
    }
a10290 1
      CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
a10296 1
      CmdArgs.push_back("-lgcc");
d10298 1
d10330 1
a10330 1
      Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
d10392 1
a10392 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d10398 1
a10398 1
  const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
d10488 1
a10488 1
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
d10571 1
a10571 1
      Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold"));
d10573 1
a10573 1
      Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
a10606 137

void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CudaToolChain &>(getToolChain());
  assert(TC.getTriple().isNVPTX() && "Wrong platform");

  // Obtain architecture from the action.
  CudaArch gpu_arch = StringToCudaArch(JA.getOffloadingArch());
  assert(gpu_arch != CudaArch::UNKNOWN &&
         "Device action expected to have an architecture.");

  // Check that our installation's ptxas supports gpu_arch.
  if (!Args.hasArg(options::OPT_no_cuda_version_check)) {
    TC.CudaInstallation.CheckCudaVersionSupportsArch(gpu_arch);
  }

  ArgStringList CmdArgs;
  CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
  if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
                   options::OPT_no_cuda_noopt_device_debug, false)) {
    // ptxas does not accept -g option if optimization is enabled, so
    // we ignore the compiler's -O* options if we want debug info.
    CmdArgs.push_back("-g");
    CmdArgs.push_back("--dont-merge-basicblocks");
    CmdArgs.push_back("--return-at-end");
  } else if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    // Map the -O we received to -O{0,1,2,3}.
    //
    // TODO: Perhaps we should map host -O2 to ptxas -O3. -O3 is ptxas's
    // default, so it may correspond more closely to the spirit of clang -O2.

    // -O3 seems like the least-bad option when -Osomething is specified to
    // clang but it isn't handled below.
    StringRef OOpt = "3";
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      OOpt = "3";
    else if (A->getOption().matches(options::OPT_O0))
      OOpt = "0";
    else if (A->getOption().matches(options::OPT_O)) {
      // -Os, -Oz, and -O(anything else) map to -O2, for lack of better options.
      OOpt = llvm::StringSwitch<const char *>(A->getValue())
                 .Case("1", "1")
                 .Case("2", "2")
                 .Case("3", "3")
                 .Case("s", "2")
                 .Case("z", "2")
                 .Default("2");
    }
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
  } else {
    // If no -O was passed, pass -O0 to ptxas -- no opt flag should correspond
    // to no optimizations, but ptxas's default is -O3.
    CmdArgs.push_back("-O0");
  }

  CmdArgs.push_back("--gpu-name");
  CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
  CmdArgs.push_back("--output-file");
  CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
  for (const auto& II : Inputs)
    CmdArgs.push_back(Args.MakeArgString(II.getFilename()));

  for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
    CmdArgs.push_back(Args.MakeArgString(A));

  const char *Exec;
  if (Arg *A = Args.getLastArg(options::OPT_ptxas_path_EQ))
    Exec = A->getValue();
  else
    Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

// All inputs to this linker must be from CudaDeviceActions, as we need to look
// at the Inputs' Actions in order to figure out which GPU architecture they
// correspond to.
void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const auto &TC =
      static_cast<const toolchains::CudaToolChain &>(getToolChain());
  assert(TC.getTriple().isNVPTX() && "Wrong platform");

  ArgStringList CmdArgs;
  CmdArgs.push_back("--cuda");
  CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32");
  CmdArgs.push_back(Args.MakeArgString("--create"));
  CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));

  for (const auto& II : Inputs) {
    auto *A = II.getAction();
    assert(A->getInputs().size() == 1 &&
           "Device offload action is expected to have a single input");
    const char *gpu_arch_str = A->getOffloadingArch();
    assert(gpu_arch_str &&
           "Device action expected to have associated a GPU architecture!");
    CudaArch gpu_arch = StringToCudaArch(gpu_arch_str);

    // We need to pass an Arch of the form "sm_XX" for cubin files and
    // "compute_XX" for ptx.
    const char *Arch =
        (II.getType() == types::TY_PP_Asm)
            ? CudaVirtualArchToString(VirtualArchForCudaArch(gpu_arch))
            : gpu_arch_str;
    CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") +
                                         Arch + ",file=" + II.getFilename()));
  }

  for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
    CmdArgs.push_back(Args.MakeArgString(A));

  const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &Args,
                               const char *LinkingOutput) const {

  std::string Linker = getToolChain().GetProgramPath(getShortName());
  ArgStringList CmdArgs;
  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());
  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs, Inputs));
}
// AVR tools end.
@


1.1.1.13.2.1
log
@Sync with HEAD
@
text
@d6434 4
a6437 5
    // it and developers have been trained to spell it with -mllvm. Both
    // spellings are now deprecated and should be removed.
    if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
      CmdArgs.push_back("-disable-llvm-optzns");
    } else {
a6438 1
    }
@


1.1.1.14
log
@Import Clang 4.0RC1 r294123.
@
text
@d6434 4
a6437 5
    // it and developers have been trained to spell it with -mllvm. Both
    // spellings are now deprecated and should be removed.
    if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
      CmdArgs.push_back("-disable-llvm-optzns");
    } else {
a6438 1
    }
@


1.1.1.15
log
@Mark files not present in 309604 as dead.
@
text
@@


1.1.1.8.4.1
log
@file Tools.cpp was added on branch tls-maxphys on 2014-08-19 23:47:28 +0000
@
text
@d1 8081
@


1.1.1.8.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 8081
//===--- Tools.cpp - Tools Implementations --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                    options::OPT_fpic, options::OPT_fno_pic,
                                    options::OPT_fPIE, options::OPT_fno_PIE,
                                    options::OPT_fpie, options::OPT_fno_pie);
  if (!LastPICArg)
    return;
  if (LastPICArg->getOption().matches(options::OPT_fPIC) ||
      LastPICArg->getOption().matches(options::OPT_fpic) ||
      LastPICArg->getOption().matches(options::OPT_fPIE) ||
      LastPICArg->getOption().matches(options::OPT_fpie)) {
    CmdArgs.push_back("-KPIC");
  }
}

/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) {
    if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
        !Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
      D.Diag(diag::err_drv_argument_only_allowed_with)
          << A->getBaseArg().getAsString(Args)
          << (D.IsCLMode() ? "/E, /P or /EP" : "-E");
    }
  }
}

/// CheckCodeGenerationOptions - Perform some validation of code generation
/// arguments that is shared with gcc.
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
  // In gcc, only ARM checks this, but it seems reasonable to check universally.
  if (Args.hasArg(options::OPT_static))
    if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
                                       options::OPT_mdynamic_no_pic))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-static";
}

// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
static void QuoteTarget(StringRef Target,
                        SmallVectorImpl<char> &Res) {
  for (unsigned i = 0, e = Target.size(); i != e; ++i) {
    switch (Target[i]) {
    case ' ':
    case '\t':
      // Escape the preceding backslashes
      for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
        Res.push_back('\\');

      // Escape the space/tab
      Res.push_back('\\');
      break;
    case '$':
      Res.push_back('$');
      break;
    case '#':
      Res.push_back('\\');
      break;
    default:
      break;
    }

    Res.push_back(Target[i]);
  }
}

static void addDirectoryList(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             const char *ArgName,
                             const char *EnvVar) {
  const char *DirList = ::getenv(EnvVar);
  bool CombinedArg = false;

  if (!DirList)
    return; // Nothing to do.

  StringRef Name(ArgName);
  if (Name.equals("-I") || Name.equals("-L"))
    CombinedArg = true;

  StringRef Dirs(DirList);
  if (Dirs.empty()) // Empty string should not add '.'.
    return;

  StringRef::size_type Delim;
  while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
    if (Delim == 0) { // Leading colon.
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(".");
      }
    } else {
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
      }
    }
    Dirs = Dirs.substr(Delim + 1);
  }

  if (Dirs.empty()) { // Trailing colon.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(".");
    }
  } else { // Add the last path.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(Args.MakeArgString(Dirs));
    }
  }
}

static void AddLinkerInputs(const ToolChain &TC,
                            const InputInfoList &Inputs, const ArgList &Args,
                            ArgStringList &CmdArgs) {
  const Driver &D = TC.getDriver();

  // Add extra linker input arguments which are not treated as inputs
  // (constructed via -Xarch_).
  Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);

  for (const auto &II : Inputs) {
    if (!TC.HasNativeLLVMSupport()) {
      // Don't try to pass LLVM inputs unless we have native support.
      if (II.getType() == types::TY_LLVM_IR ||
          II.getType() == types::TY_LTO_IR ||
          II.getType() == types::TY_LLVM_BC ||
          II.getType() == types::TY_LTO_BC)
        D.Diag(diag::err_drv_no_linker_llvm_support)
          << TC.getTripleString();
    }

    // Add filenames immediately.
    if (II.isFilename()) {
      CmdArgs.push_back(II.getFilename());
      continue;
    }

    // Otherwise, this is a linker input argument.
    const Arg &A = II.getInputArg();

    // Handle reserved library options.
    if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
      TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
      TC.AddCCKextLibArgs(Args, CmdArgs);
    else if (A.getOption().matches(options::OPT_z)) {
      // Pass -z prefix for gcc linker compatibility.
      A.claim();
      A.render(Args, CmdArgs);
    } else {
       A.renderAsInput(Args, CmdArgs);
    }
  }

  // LIBRARY_PATH - included following the user specified library paths.
  //                and only supported on native toolchains.
  if (!TC.isCrossCompiling())
    addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
}

/// \brief Determine whether Objective-C automated reference counting is
/// enabled.
static bool isObjCAutoRefCount(const ArgList &Args) {
  return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
}

/// \brief Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
  if (isObjCAutoRefCount(Args)) {
    Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
    return true;
  }
  return Args.hasArg(options::OPT_fobjc_link_runtime);
}

static bool forwardToGCC(const Option &O) {
  // Don't forward inputs from the original command line.  They are added from
  // InputInfoList.
  return O.getKind() != Option::InputClass &&
         !O.hasFlag(options::DriverOption) &&
         !O.hasFlag(options::LinkerInput);
}

void Clang::AddPreprocessingOptions(Compilation &C,
                                    const JobAction &JA,
                                    const Driver &D,
                                    const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs) const {
  Arg *A;

  CheckPreprocessingOptions(D, Args);

  Args.AddLastArg(CmdArgs, options::OPT_C);
  Args.AddLastArg(CmdArgs, options::OPT_CC);

  // Handle dependency file generation.
  if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
      (A = Args.getLastArg(options::OPT_MD)) ||
      (A = Args.getLastArg(options::OPT_MMD))) {
    // Determine the output location.
    const char *DepFile;
    if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
      DepFile = MF->getValue();
      C.addFailureResultFile(DepFile, &JA);
    } else if (Output.getType() == types::TY_Dependencies) {
      DepFile = Output.getFilename();
    } else if (A->getOption().matches(options::OPT_M) ||
               A->getOption().matches(options::OPT_MM)) {
      DepFile = "-";
    } else {
      DepFile = getDependencyFileName(Args, Inputs);
      C.addFailureResultFile(DepFile, &JA);
    }
    CmdArgs.push_back("-dependency-file");
    CmdArgs.push_back(DepFile);

    // Add a default target if one wasn't specified.
    if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
      const char *DepTarget;

      // If user provided -o, that is the dependency target, except
      // when we are only generating a dependency file.
      Arg *OutputOpt = Args.getLastArg(options::OPT_o);
      if (OutputOpt && Output.getType() != types::TY_Dependencies) {
        DepTarget = OutputOpt->getValue();
      } else {
        // Otherwise derive from the base input.
        //
        // FIXME: This should use the computed output file location.
        SmallString<128> P(Inputs[0].getBaseInput());
        llvm::sys::path::replace_extension(P, "o");
        DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
      }

      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(DepTarget, Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));
    }

    if (A->getOption().matches(options::OPT_M) ||
        A->getOption().matches(options::OPT_MD))
      CmdArgs.push_back("-sys-header-deps");

    if (isa<PrecompileJobAction>(JA))
      CmdArgs.push_back("-module-file-deps");
  }

  if (Args.hasArg(options::OPT_MG)) {
    if (!A || A->getOption().matches(options::OPT_MD) ||
              A->getOption().matches(options::OPT_MMD))
      D.Diag(diag::err_drv_mg_requires_m_or_mm);
    CmdArgs.push_back("-MG");
  }

  Args.AddLastArg(CmdArgs, options::OPT_MP);

  // Convert all -MQ <target> args to -MT <quoted target>
  for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
                                             options::OPT_MQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = *it;
    A->claim();

    if (A->getOption().matches(options::OPT_MQ)) {
      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(A->getValue(), Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));

    // -MT flag - no change
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Add -i* options, and automatically translate to
  // -include-pch/-include-pth for transparent PCH support. It's
  // wonky, but we include looking for .gch so we can support seamless
  // replacement into a build system already set up to be generating
  // .gch files.
  bool RenderedImplicitInclude = false;
  for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = it;

    if (A->getOption().matches(options::OPT_include)) {
      bool IsFirstImplicitInclude = !RenderedImplicitInclude;
      RenderedImplicitInclude = true;

      // Use PCH if the user requested it.
      bool UsePCH = D.CCCUsePCH;

      bool FoundPTH = false;
      bool FoundPCH = false;
      SmallString<128> P(A->getValue());
      // We want the files to have a name like foo.h.pch. Add a dummy extension
      // so that replace_extension does the right thing.
      P += ".dummy";
      if (UsePCH) {
        llvm::sys::path::replace_extension(P, "pch");
        if (llvm::sys::fs::exists(P.str()))
          FoundPCH = true;
      }

      if (!FoundPCH) {
        llvm::sys::path::replace_extension(P, "pth");
        if (llvm::sys::fs::exists(P.str()))
          FoundPTH = true;
      }

      if (!FoundPCH && !FoundPTH) {
        llvm::sys::path::replace_extension(P, "gch");
        if (llvm::sys::fs::exists(P.str())) {
          FoundPCH = UsePCH;
          FoundPTH = !UsePCH;
        }
      }

      if (FoundPCH || FoundPTH) {
        if (IsFirstImplicitInclude) {
          A->claim();
          if (UsePCH)
            CmdArgs.push_back("-include-pch");
          else
            CmdArgs.push_back("-include-pth");
          CmdArgs.push_back(Args.MakeArgString(P.str()));
          continue;
        } else {
          // Ignore the PCH if not first on command line and emit warning.
          D.Diag(diag::warn_drv_pch_not_first_include)
              << P.str() << A->getAsString(Args);
        }
      }
    }

    // Not translated, render as usual.
    A->claim();
    A->render(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F,
                  options::OPT_index_header_map);

  // Add -Wp, and -Xassembler if using the preprocessor.

  // FIXME: There is a very unfortunate problem here, some troubled
  // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
  // really support that we would have to parse and then translate
  // those options. :(
  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
                       options::OPT_Xpreprocessor);

  // -I- is a deprecated GCC feature, reject it.
  if (Arg *A = Args.getLastArg(options::OPT_I_))
    D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args);

  // If we have a --sysroot, and don't have an explicit -isysroot flag, add an
  // -isysroot to the CC1 invocation.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    if (!Args.hasArg(options::OPT_isysroot)) {
      CmdArgs.push_back("-isysroot");
      CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
    }
  }

  // Parse additional include paths from environment variables.
  // FIXME: We should probably sink the logic for handling these from the
  // frontend into the driver. It will allow deleting 4 otherwise unused flags.
  // CPATH - included following the user specified includes (but prior to
  // builtin and standard includes).
  addDirectoryList(Args, CmdArgs, "-I", "CPATH");
  // C_INCLUDE_PATH - system includes enabled when compiling C.
  addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH");
  // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
  addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH");
  // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
  addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH");
  // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
  addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");

  // Add C++ include arguments, if needed.
  if (types::isCXX(Inputs[0].getType()))
    getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);

  // Add system include arguments.
  getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
}

// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return true;

  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
    if (Triple.isOSDarwin() || Triple.isOSWindows())
      return true;
    return false;

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
    if (Triple.isOSDarwin())
      return true;
    return false;

  case llvm::Triple::ppc64le:
  case llvm::Triple::systemz:
  case llvm::Triple::xcore:
    return false;
  }
}

static bool isNoCommonDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return false;

  case llvm::Triple::xcore:
    return true;
  }
}

// Handle -mhwdiv=.
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef HWDiv = A->getValue();
  if (HWDiv == "arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("-hwdiv");
  } else if (HWDiv == "thumb") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "none") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("-hwdiv");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
 
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
static void getARMFPUFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef FPU = A->getValue();

  // Set the target features based on the FPU.
  if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
    // Disable any default FPU support.
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-neon");
  } else if (FPU == "vfp") {
    Features.push_back("+vfp2");
    Features.push_back("-neon");
  } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
    Features.push_back("+vfp3");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp3" || FPU == "vfpv3") {
    Features.push_back("+vfp3");
    Features.push_back("-neon");
  } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp4" || FPU == "vfpv4") {
    Features.push_back("+vfp4");
    Features.push_back("-neon");
  } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("+fp-only-sp");
    Features.push_back("-neon");
  } else if (FPU == "fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("-neon");
    Features.push_back("-crypto");
  } else if (FPU == "neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("-crypto");
  } else if (FPU == "crypto-neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("+crypto");
  } else if (FPU == "neon") {
    Features.push_back("+neon");
  } else if (FPU == "none") {
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-vfp4");
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
                                     const llvm::Triple &Triple) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi)
          << A->getAsString(Args);
        FloatABI = "soft";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    switch (Triple.getOS()) {
    case llvm::Triple::Darwin:
    case llvm::Triple::MacOSX:
    case llvm::Triple::IOS: {
      // Darwin defaults to "softfp" for v6 and v7.
      //
      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
      std::string ArchName =
        arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
      if (StringRef(ArchName).startswith("v6") ||
          StringRef(ArchName).startswith("v7"))
        FloatABI = "softfp";
      else
        FloatABI = "soft";
      break;
    }

    // FIXME: this is invalid for WindowsCE
    case llvm::Triple::Win32:
      FloatABI = "hard";
      break;

    case llvm::Triple::FreeBSD:
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      default:
        // FreeBSD defaults to soft float
        FloatABI = "soft";
        break;
      }
      break;

    default:
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      case llvm::Triple::GNUEABI:
        FloatABI = "softfp";
        break;
      case llvm::Triple::EABIHF:
        FloatABI = "hard";
        break;
      case llvm::Triple::EABI:
        // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
        FloatABI = "softfp";
        break;
      case llvm::Triple::Android: {
        std::string ArchName =
          arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
        if (StringRef(ArchName).startswith("v7"))
          FloatABI = "softfp";
        else
          FloatABI = "soft";
        break;
      }
      default:
        // Assume "soft", but warn the user we are guessing.
        FloatABI = "soft";
        if (Triple.getOS() != llvm::Triple::UnknownOS ||
            !Triple.isOSBinFormatMachO())
          D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
        break;
      }
    }
  }

  return FloatABI;
}

static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features,
                                 bool ForAS) {
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
  if (!ForAS) {
    // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
    // yet (it uses the -mfloat-abi and -msoft-float options), and it is
    // stripped out by the ARM target. We should probably pass this a new
    // -target-option, which is handled by the -cc1/-cc1as invocation.
    //
    // FIXME2:  For consistency, it would be ideal if we set up the target
    // machine state the same when using the frontend or the assembler. We don't
    // currently do that for the assembler, we pass the options directly to the
    // backend and never even instantiate the frontend TargetInfo. If we did,
    // and used its handleTargetFeatures hook, then we could ensure the
    // assembler and the frontend behave the same.

    // Use software floating point operations?
    if (FloatABI == "soft")
      Features.push_back("+soft-float");

    // Use software floating point argument passing?
    if (FloatABI != "hard")
      Features.push_back("+soft-float-abi");
  }

  // Honor -mfpu=.
  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
    getARMFPUFeatures(D, A, Args, Features);
  if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
    getARMHWDivFeatures(D, A, Args, Features);

  // Setting -msoft-float effectively disables NEON because of the GCC
  // implementation, although the same isn't true of VFP or VFP3.
  if (FloatABI == "soft") {
    Features.push_back("-neon");
    // Also need to explicitly disable features which imply NEON.
    Features.push_back("-crypto");
  }

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
}

void Clang::AddARMTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             bool KernelOrKext) const {
  const Driver &D = getToolChain().getDriver();
  // Get the effective triple, which takes into account the deployment target.
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);
  std::string CPUName = arm::getARMTargetCPU(Args, Triple);

  // Select the ABI to use.
  //
  // FIXME: Support -meabi.
  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
  } else if (Triple.isOSBinFormatMachO()) {
    // The backend is hardwired to assume AAPCS for M-class processors, ensure
    // the frontend matches that.
    if (Triple.getEnvironment() == llvm::Triple::EABI ||
        (Triple.getOS() == llvm::Triple::UnknownOS &&
         Triple.getObjectFormat() == llvm::Triple::MachO) ||
        StringRef(CPUName).startswith("cortex-m")) {
      ABIName = "aapcs";
    } else {
      ABIName = "apcs-gnu";
    }
  } else if (Triple.isOSWindows()) {
    // FIXME: this is invalid for WindowsCE
    ABIName = "aapcs";
  } else {
    // Select the default based on the platform.
    switch(Triple.getEnvironment()) {
    case llvm::Triple::Android:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::GNUEABIHF:
      ABIName = "aapcs-linux";
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::EABI:
      ABIName = "aapcs";
      break;
    default:
      ABIName = "apcs-gnu";
    }
  }
  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  // Determine floating point ABI from the options & target defaults.
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else if (FloatABI == "softfp") {
    // Floating point operations are hard, but argument passing is soft.
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  // Kernel code has more strict alignment requirements.
  if (KernelOrKext) {
    if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-long-calls");
    }

    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-strict-align");

    // The kext linker doesn't know how to deal with movw/movt.
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-use-movt=0");
  }

  // -mkernel implies -mstrict-align; don't add the redundant option.
  if (!KernelOrKext) {
    if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                                 options::OPT_munaligned_access)) {
      CmdArgs.push_back("-backend-option");
      if (A->getOption().matches(options::OPT_mno_unaligned_access))
        CmdArgs.push_back("-arm-strict-align");
      else
        CmdArgs.push_back("-arm-no-strict-align");
    }
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting 
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float,
                    true))
    CmdArgs.push_back("-no-implicit-float");

  // llvm does not support reserving registers in general. There is support
  // for reserving r9 on ARM though (defined as a platform-specific register
  // in ARM EABI).
  if (Args.hasArg(options::OPT_ffixed_r9)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-reserve-r9");
  }
}

/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
/// targeting.
static std::string getAArch64TargetCPU(const ArgList &Args) {
  Arg *A;
  std::string CPU;
  // If we have -mtune or -mcpu, use that.
  if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
    CPU = A->getValue();
  } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
    StringRef Mcpu = A->getValue();
    CPU = Mcpu.split("+").first;
  }

  // Handle CPU name is 'native'.
  if (CPU == "native")
    return llvm::sys::getHostCPUName();
  else if (CPU.size())
    return CPU;

  // Make sure we pick "cyclone" if -arch is used.
  // FIXME: Should this be picked by checking the target triple instead?
  if (Args.getLastArg(options::OPT_arch))
    return "cyclone";

  return "generic";
}

void Clang::AddAArch64TargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);

  if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float, true))
    CmdArgs.push_back("-no-implicit-float");

  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
    ABIName = A->getValue();
  else if (Triple.isOSDarwin())
    ABIName = "darwinpcs";
  else
    ABIName = "aapcs";

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                               options::OPT_munaligned_access)) {
    CmdArgs.push_back("-backend-option");
    if (A->getOption().matches(options::OPT_mno_unaligned_access))
      CmdArgs.push_back("-aarch64-strict-align");
    else
      CmdArgs.push_back("-aarch64-no-strict-align");
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }
}

// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
void mips::getMipsCPUAndABI(const ArgList &Args,
                            const llvm::Triple &Triple,
                            StringRef &CPUName,
                            StringRef &ABIName) {
  const char *DefMips32CPU = "mips32r2";
  const char *DefMips64CPU = "mips64r2";

  // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
  // default for mips64(el)?-img-linux-gnu.
  if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
      Triple.getEnvironment() == llvm::Triple::GNU) {
    DefMips32CPU = "mips32r6";
    DefMips64CPU = "mips64r6";
  }

  if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
                               options::OPT_mcpu_EQ))
    CPUName = A->getValue();

  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
    // Convert a GNU style Mips ABI name to the name
    // accepted by LLVM Mips backend.
    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
      .Case("32", "o32")
      .Case("64", "n64")
      .Default(ABIName);
  }

  // Setup default CPU and ABI names.
  if (CPUName.empty() && ABIName.empty()) {
    switch (Triple.getArch()) {
    default:
      llvm_unreachable("Unexpected triple arch name");
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
      CPUName = DefMips32CPU;
      break;
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      CPUName = DefMips64CPU;
      break;
    }
  }

  if (ABIName.empty()) {
    // Deduce ABI name from the target triple.
    if (Triple.getArch() == llvm::Triple::mips ||
        Triple.getArch() == llvm::Triple::mipsel)
      ABIName = "o32";
    else
      ABIName = "n64";
  }

  if (CPUName.empty()) {
    // Deduce CPU name from ABI name.
    CPUName = llvm::StringSwitch<const char *>(ABIName)
      .Cases("o32", "eabi", DefMips32CPU)
      .Cases("n32", "n64", DefMips64CPU)
      .Default("");
  }

  // FIXME: Warn on inconsistent use of -march and -mabi.
}

// Convert ABI name to the GNU tools acceptable variant.
static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
  return llvm::StringSwitch<llvm::StringRef>(ABI)
    .Case("o32", "32")
    .Case("n64", "64")
    .Default(ABI);
}

// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        FloatABI = "hard";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "hard", because it's a default value used by gcc.
    // When we start to recognize specific target MIPS processors,
    // we will be able to select the default more correctly.
    FloatABI = "hard";
  }

  return FloatABI;
}

static void AddTargetFeature(const ArgList &Args,
                             std::vector<const char *> &Features,
                             OptSpecifier OnOpt, OptSpecifier OffOpt,
                             StringRef FeatureName) {
  if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
    if (A->getOption().matches(OnOpt))
      Features.push_back(Args.MakeArgString("+" + FeatureName));
    else
      Features.push_back(Args.MakeArgString("-" + FeatureName));
  }
}

static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
  StringRef CPUName;
  StringRef ABIName;
  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
  ABIName = getGnuCompatibleMipsABIName(ABIName);

  // Always override the backend's default ABI.
  std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
                               .Case("32", "+o32")
                               .Case("n32", "+n32")
                               .Case("64", "+n64")
                               .Case("eabi", "+eabi")
                               .Default(("+" + ABIName).str());
  Features.push_back("-o32");
  Features.push_back("-n64");
  Features.push_back(Args.MakeArgString(ABIFeature));

  AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
                   options::OPT_mabicalls, "noabicalls");

  StringRef FloatABI = getMipsFloatABI(D, Args);
  if (FloatABI == "soft") {
    // FIXME: Note, this is a hack. We need to pass the selected float
    // mode to the MipsTargetInfoBase to define appropriate macros there.
    // Now it is the only method.
    Features.push_back("+soft-float");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
    StringRef Val = StringRef(A->getValue());
    if (Val == "2008")
      Features.push_back("+nan2008");
    else if (Val == "legacy")
      Features.push_back("-nan2008");
    else
      D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
  }

  AddTargetFeature(Args, Features, options::OPT_msingle_float,
                   options::OPT_mdouble_float, "single-float");
  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
                   "mips16");
  AddTargetFeature(Args, Features, options::OPT_mmicromips,
                   options::OPT_mno_micromips, "micromips");
  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
                   "dsp");
  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
                   "dspr2");
  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
                   "msa");

  // Add the last -mfp32/-mfpxx/-mfp64 or if none are given and the ABI is O32
  // pass -mfpxx
  if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
                               options::OPT_mfp64)) {
    if (A->getOption().matches(options::OPT_mfp32))
      Features.push_back(Args.MakeArgString("-fp64"));
    else if (A->getOption().matches(options::OPT_mfpxx)) {
      Features.push_back(Args.MakeArgString("+fpxx"));
      Features.push_back(Args.MakeArgString("+nooddspreg"));
    } else
      Features.push_back(Args.MakeArgString("+fp64"));
  } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
    Features.push_back(Args.MakeArgString("+fpxx"));
    Features.push_back(Args.MakeArgString("+nooddspreg"));
  }

  AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
                   options::OPT_modd_spreg, "nooddspreg");
}

void Clang::AddMIPSTargetArgs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();
  StringRef CPUName;
  StringRef ABIName;
  const llvm::Triple &Triple = getToolChain().getTriple();
  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName.data());

  StringRef FloatABI = getMipsFloatABI(D, Args);

  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  }
  else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
    if (A->getOption().matches(options::OPT_mxgot)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mxgot");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
                               options::OPT_mno_ldc1_sdc1)) {
    if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-ldc1-sdc1");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
                               options::OPT_mno_check_zero_division)) {
    if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-check-zero-division");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_G)) {
    StringRef v = A->getValue();
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v));
    A->claim();
  }
}

/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
static std::string getPPCTargetCPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPUName = A->getValue();

    if (CPUName == "native") {
      std::string CPU = llvm::sys::getHostCPUName();
      if (!CPU.empty() && CPU != "generic")
        return CPU;
      else
        return "";
    }

    return llvm::StringSwitch<const char *>(CPUName)
      .Case("common", "generic")
      .Case("440", "440")
      .Case("440fp", "440")
      .Case("450", "450")
      .Case("601", "601")
      .Case("602", "602")
      .Case("603", "603")
      .Case("603e", "603e")
      .Case("603ev", "603ev")
      .Case("604", "604")
      .Case("604e", "604e")
      .Case("620", "620")
      .Case("630", "pwr3")
      .Case("G3", "g3")
      .Case("7400", "7400")
      .Case("G4", "g4")
      .Case("7450", "7450")
      .Case("G4+", "g4+")
      .Case("750", "750")
      .Case("970", "970")
      .Case("G5", "g5")
      .Case("a2", "a2")
      .Case("a2q", "a2q")
      .Case("e500mc", "e500mc")
      .Case("e5500", "e5500")
      .Case("power3", "pwr3")
      .Case("power4", "pwr4")
      .Case("power5", "pwr5")
      .Case("power5x", "pwr5x")
      .Case("power6", "pwr6")
      .Case("power6x", "pwr6x")
      .Case("power7", "pwr7")
      .Case("power8", "pwr8")
      .Case("pwr3", "pwr3")
      .Case("pwr4", "pwr4")
      .Case("pwr5", "pwr5")
      .Case("pwr5x", "pwr5x")
      .Case("pwr6", "pwr6")
      .Case("pwr6x", "pwr6x")
      .Case("pwr7", "pwr7")
      .Case("pwr8", "pwr8")
      .Case("powerpc", "ppc")
      .Case("powerpc64", "ppc64")
      .Case("powerpc64le", "ppc64le")
      .Default("");
  }

  return "";
}

static void getPPCTargetFeatures(const ArgList &Args,
                                 std::vector<const char *> &Features) {
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
    // pass the correct option to the backend while calling the frontend
    // option the same.
    // TODO: Change the LLVM backend option maybe?
    if (Name == "mfcrf")
      Name = "mfocrf";

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }

  // Altivec is a bit weird, allow overriding of the Altivec feature here.
  AddTargetFeature(Args, Features, options::OPT_faltivec,
                   options::OPT_fno_altivec, "altivec");
}

void Clang::AddPPCTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  // Select the ABI to use.
  const char *ABIName = nullptr;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
  } else if (getToolChain().getTriple().isOSLinux())
    switch(getToolChain().getArch()) {
    case llvm::Triple::ppc64:
      ABIName = "elfv1";
      break;
    case llvm::Triple::ppc64le:
      ABIName = "elfv2";
      break;
    default:
      break;
  }

  if (ABIName) {
    CmdArgs.push_back("-target-abi");
    CmdArgs.push_back(ABIName);
  }
}

bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

/// Get the (LLVM) name of the R600 gpu we are targeting.
static std::string getR600TargetGPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    const char *GPUName = A->getValue();
    return llvm::StringSwitch<const char *>(GPUName)
      .Cases("rv630", "rv635", "r600")
      .Cases("rv610", "rv620", "rs780", "rs880")
      .Case("rv740", "rv770")
      .Case("palm", "cedar")
      .Cases("sumo", "sumo2", "sumo")
      .Case("hemlock", "cypress")
      .Case("aruba", "cayman")
      .Default(GPUName);
  }
  return "";
}

static void getSparcTargetFeatures(const ArgList &Args,
                                   std::vector<const char *> Features) {
  bool SoftFloatABI = true;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_mhard_float))
      SoftFloatABI = false;
  }
  if (SoftFloatABI)
    Features.push_back("+soft-float");
}

void Clang::AddSparcTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // Select the float ABI as determined by -msoft-float and -mhard-float.
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "soft", but warn the user we are guessing.
    FloatABI = "soft";
    D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
  }

  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
  } else {
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mhard-float");
  }
}

static const char *getSystemZTargetCPU(const ArgList &Args) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
    return A->getValue();
  return "z10";
}

static const char *getX86TargetCPU(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    if (StringRef(A->getValue()) != "native") {
      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
        return "core-avx2";

      return A->getValue();
    }

    // FIXME: Reject attempts to use -march=native unless the target matches
    // the host.
    //
    // FIXME: We should also incorporate the detected target features for use
    // with -native.
    std::string CPU = llvm::sys::getHostCPUName();
    if (!CPU.empty() && CPU != "generic")
      return Args.MakeArgString(CPU);
  }

  // Select the default CPU if none was given (or detection failed).

  if (Triple.getArch() != llvm::Triple::x86_64 &&
      Triple.getArch() != llvm::Triple::x86)
    return nullptr; // This routine is only handling x86 targets.

  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;

  // FIXME: Need target hooks.
  if (Triple.isOSDarwin()) {
    if (Triple.getArchName() == "x86_64h")
      return "core-avx2";
    return Is64Bit ? "core2" : "yonah";
  }

  // On Android use targets compatible with gcc
  if (Triple.getEnvironment() == llvm::Triple::Android)
    return Is64Bit ? "x86-64" : "i686";

  // Everything else goes to x86-64 in 64-bit mode.
  if (Is64Bit)
    return "x86-64";

  switch (Triple.getOS()) {
  case llvm::Triple::FreeBSD:
  case llvm::Triple::NetBSD:
  case llvm::Triple::OpenBSD:
    return "i486";
  case llvm::Triple::Haiku:
    return "i586";
  case llvm::Triple::Bitrig:
    return "i686";
  default:
    // Fallback to p4.
    return "pentium4";
  }
}

static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
  switch(T.getArch()) {
  default:
    return "";

  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
    return getAArch64TargetCPU(Args);

  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    return arm::getARMTargetCPU(Args, T);

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
    return CPUName;
  }

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le: {
    std::string TargetCPUName = getPPCTargetCPU(Args);
    // LLVM may default to generating code for the native CPU,
    // but, like gcc, we default to a more generic option for
    // each architecture. (except on Darwin)
    if (TargetCPUName.empty() && !T.isOSDarwin()) {
      if (T.getArch() == llvm::Triple::ppc64)
        TargetCPUName = "ppc64";
      else if (T.getArch() == llvm::Triple::ppc64le)
        TargetCPUName = "ppc64le";
      else
        TargetCPUName = "ppc";
    }
    return TargetCPUName;
  }

  case llvm::Triple::sparc:
  case llvm::Triple::sparcv9:
    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
      return A->getValue();
    return "";

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    return getX86TargetCPU(Args, T);

  case llvm::Triple::hexagon:
    return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();

  case llvm::Triple::systemz:
    return getSystemZTargetCPU(Args);

  case llvm::Triple::r600:
    return getR600TargetGPU(Args);
  }
}

static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
                          ArgStringList &CmdArgs) {
  // Tell the linker to load the plugin. This has to come before AddLinkerInputs
  // as gold requires -plugin to come before any -plugin-opt that -Wl might
  // forward.
  CmdArgs.push_back("-plugin");
  std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
  CmdArgs.push_back(Args.MakeArgString(Plugin));

  // Try to pass driver level flags relevant to LTO code generation down to
  // the plugin.

  // Handle flags for selecting CPU variants.
  std::string CPU = getCPUName(Args, ToolChain.getTriple());
  if (!CPU.empty())
    CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
}

static void getX86TargetFeatures(const Driver & D,
                                 const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features) {
  if (Triple.getArchName() == "x86_64h") {
    // x86_64h implies quite a few of the more modern subtarget features
    // for Haswell class CPUs, but not all of them. Opt-out of a few.
    Features.push_back("-rdrnd");
    Features.push_back("-aes");
    Features.push_back("-pclmul");
    Features.push_back("-rtm");
    Features.push_back("-hle");
    Features.push_back("-fsgsbase");
  }

  // Add features to comply with gcc on Android
  if (Triple.getEnvironment() == llvm::Triple::Android) {
    if (Triple.getArch() == llvm::Triple::x86_64) {
      Features.push_back("+sse4.2");
      Features.push_back("+popcnt");
    } else
      Features.push_back("+ssse3");
  }

  // Set features according to the -arch flag on MSVC
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
    StringRef Arch = A->getValue();
    bool ArchUsed = false;
    // First, look for flags that are shared in x86 and x86-64.
    if (Triple.getArch() == llvm::Triple::x86_64 ||
        Triple.getArch() == llvm::Triple::x86) {
      if (Arch == "AVX" || Arch == "AVX2") {
        ArchUsed = true;
        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
      }
    }
    // Then, look for x86-specific flags.
    if (Triple.getArch() == llvm::Triple::x86) {
      if (Arch == "IA32") {
        ArchUsed = true;
      } else if (Arch == "SSE" || Arch == "SSE2") {
        ArchUsed = true;
        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
      }
    }
    if (!ArchUsed)
      D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
  }

  // Now add any that the user explicitly requested on the command line,
  // which may override the defaults.
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }
}

void Clang::AddX86TargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  if (!Args.hasFlag(options::OPT_mred_zone,
                    options::OPT_mno_red_zone,
                    true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  // Default to avoid implicit floating-point for kernel/kext code, but allow
  // that to be overridden with -mno-soft-float.
  bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
                          Args.hasArg(options::OPT_fapple_kext));
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mno_soft_float,
                               options::OPT_mimplicit_float,
                               options::OPT_mno_implicit_float)) {
    const Option &O = A->getOption();
    NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
                       O.matches(options::OPT_msoft_float));
  }
  if (NoImplicitFloat)
    CmdArgs.push_back("-no-implicit-float");

  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  }
}

static inline bool HasPICArg(const ArgList &Args) {
  return Args.hasArg(options::OPT_fPIC)
    || Args.hasArg(options::OPT_fpic);
}

static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) {
  return Args.getLastArg(options::OPT_G,
                         options::OPT_G_EQ,
                         options::OPT_msmall_data_threshold_EQ);
}

static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
  std::string value;
  if (HasPICArg(Args))
    value = "0";
  else if (Arg *A = GetLastSmallDataThresholdArg(Args)) {
    value = A->getValue();
    A->claim();
  }
  return value;
}

void Clang::AddHexagonTargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-fno-signed-char");
  CmdArgs.push_back("-mqdsp6-compat");
  CmdArgs.push_back("-Wreturn-type");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back(Args.MakeArgString(
                        "-hexagon-small-data-threshold=" + SmallDataThreshold));
  }

  if (!Args.hasArg(options::OPT_fno_short_enums))
    CmdArgs.push_back("-fshort-enums");
  if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
  }
  CmdArgs.push_back ("-mllvm");
  CmdArgs.push_back ("-machine-sink-split=0");
}

// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, const StringRef &text,
                                  std::vector<const char *> &Features) {
  SmallVector<StringRef, 8> Split;
  text.split(Split, StringRef("+"), -1, false);

  for (unsigned I = 0, E = Split.size(); I != E; ++I) {
    const char *result = llvm::StringSwitch<const char *>(Split[I])
                             .Case("fp", "+fp-armv8")
                             .Case("simd", "+neon")
                             .Case("crc", "+crc")
                             .Case("crypto", "+crypto")
                             .Case("nofp", "-fp-armv8")
                             .Case("nosimd", "-neon")
                             .Case("nocrc", "-crc")
                             .Case("nocrypto", "-crypto")
                             .Default(nullptr);
    if (result)
      Features.push_back(result);
    else if (Split[I] == "neon" || Split[I] == "noneon")
      D.Diag(diag::err_drv_no_neon_modifier);
    else
      return false;
  }
  return true;
}

// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
// decode CPU and feature.
static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
                              std::vector<const char *> &Features) {
  std::pair<StringRef, StringRef> Split = Mcpu.split("+");
  CPU = Split.first;
  if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
    Features.push_back("+neon");
    Features.push_back("+crc");
    Features.push_back("+crypto");
  } else if (CPU == "generic") {
    Features.push_back("+neon");
  } else {
    return false;
  }

  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
    return false;

  return true;
}

static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
                                const ArgList &Args,
                                std::vector<const char *> &Features) {
  std::pair<StringRef, StringRef> Split = March.split("+");
  if (Split.first != "armv8-a")
    return false;

  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
    return false;

  return true;
}

static bool
getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
                               const ArgList &Args,
                               std::vector<const char *> &Features) {
  StringRef CPU;
  if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
    return false;

  return true;
}

static bool
getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
                                     const ArgList &Args,
                                     std::vector<const char *> &Features) {
  // Handle CPU name is 'native'.
  if (Mtune == "native")
    Mtune = llvm::sys::getHostCPUName();
  if (Mtune == "cyclone") {
    Features.push_back("+zcm");
    Features.push_back("+zcz");
  }
  return true;
}

static bool
getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
                                    const ArgList &Args,
                                    std::vector<const char *> &Features) {
  StringRef CPU;
  std::vector<const char *> DecodedFeature;
  if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
    return false;

  return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
}

static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
                                     std::vector<const char *> &Features) {
  Arg *A;
  bool success = true;
  // Enable NEON by default.
  Features.push_back("+neon");
  if ((A = Args.getLastArg(options::OPT_march_EQ)))
    success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
  else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);

  if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
    success =
        getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
  else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
    success =
        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);

  if (!success)
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);

  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  }

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
}

static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args, ArgStringList &CmdArgs,
                              bool ForAS) {
  std::vector<const char *> Features;
  switch (Triple.getArch()) {
  default:
    break;
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    getMIPSTargetFeatures(D, Triple, Args, Features);
    break;

  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    getARMTargetFeatures(D, Triple, Args, Features, ForAS);
    break;

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    getPPCTargetFeatures(Args, Features);
    break;
  case llvm::Triple::sparc:
    getSparcTargetFeatures(Args, Features);
    break;
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
    getAArch64TargetFeatures(D, Args, Features);
    break;
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    getX86TargetFeatures(D, Triple, Args, Features);
    break;
  }

  // Find the last of each feature.
  llvm::StringMap<unsigned> LastOpt;
  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    const char *Name = Features[I];
    assert(Name[0] == '-' || Name[0] == '+');
    LastOpt[Name + 1] = I;
  }

  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    // If this feature was overridden, ignore it.
    const char *Name = Features[I];
    llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
    assert(LastI != LastOpt.end());
    unsigned Last = LastI->second;
    if (Last != I)
      continue;

    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back(Name);
  }
}

static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
                                          const llvm::Triple &Triple) {
  // We use the zero-cost exception tables for Objective-C if the non-fragile
  // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
  // later.
  if (runtime.isNonFragile())
    return true;

  if (!Triple.isMacOSX())
    return false;

  return (!Triple.isMacOSXVersionLT(10,5) &&
          (Triple.getArch() == llvm::Triple::x86_64 ||
           Triple.getArch() == llvm::Triple::arm));
}

namespace {
  struct ExceptionSettings {
    bool ExceptionsEnabled;
    bool ShouldUseExceptionTables;
    ExceptionSettings() : ExceptionsEnabled(false),
                          ShouldUseExceptionTables(false) {}
  };
} // end anonymous namespace.

// exceptionSettings() exists to share the logic between -cc1 and linker
// invocations.
static ExceptionSettings exceptionSettings(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  ExceptionSettings ES;

  // Are exceptions enabled by default?
  ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);

  // This keeps track of whether exceptions were explicitly turned on or off.
  bool DidHaveExplicitExceptionFlag = false;

  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
                               options::OPT_fno_exceptions)) {
    if (A->getOption().matches(options::OPT_fexceptions))
      ES.ExceptionsEnabled = true;
    else
      ES.ExceptionsEnabled = false;

    DidHaveExplicitExceptionFlag = true;
  }

  // Exception tables and cleanups can be enabled with -fexceptions even if the
  // language itself doesn't support exceptions.
  if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
    ES.ShouldUseExceptionTables = true;

  return ES;
}

/// addExceptionArgs - Adds exception related arguments to the driver command
/// arguments. There's a master flag, -fexceptions and also language specific
/// flags to enable/disable C++ and Objective-C exceptions.
/// This makes it possible to for example disable C++ exceptions but enable
/// Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
                             const llvm::Triple &Triple,
                             bool KernelOrKext,
                             const ObjCRuntime &objcRuntime,
                             ArgStringList &CmdArgs) {
  if (KernelOrKext) {
    // -mkernel and -fapple-kext imply no exceptions, so claim exception related
    // arguments now to avoid warnings about unused arguments.
    Args.ClaimAllArgs(options::OPT_fexceptions);
    Args.ClaimAllArgs(options::OPT_fno_exceptions);
    Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
    Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
    return;
  }

   // Gather the exception settings from the command line arguments.
   ExceptionSettings ES = exceptionSettings(Args, Triple);

  // Obj-C exceptions are enabled by default, regardless of -fexceptions. This
  // is not necessarily sensible, but follows GCC.
  if (types::isObjC(InputType) &&
      Args.hasFlag(options::OPT_fobjc_exceptions,
                   options::OPT_fno_objc_exceptions,
                   true)) {
    CmdArgs.push_back("-fobjc-exceptions");

    ES.ShouldUseExceptionTables |=
      shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
  }

  if (types::isCXX(InputType)) {
    bool CXXExceptionsEnabled = ES.ExceptionsEnabled;

    if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
                                 options::OPT_fno_cxx_exceptions,
                                 options::OPT_fexceptions,
                                 options::OPT_fno_exceptions)) {
      if (A->getOption().matches(options::OPT_fcxx_exceptions))
        CXXExceptionsEnabled = true;
      else if (A->getOption().matches(options::OPT_fno_cxx_exceptions))
        CXXExceptionsEnabled = false;
    }

    if (CXXExceptionsEnabled) {
      CmdArgs.push_back("-fcxx-exceptions");

      ES.ShouldUseExceptionTables = true;
    }
  }

  if (ES.ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");
}

static bool ShouldDisableAutolink(const ArgList &Args,
                             const ToolChain &TC) {
  bool Default = true;
  if (TC.getTriple().isOSDarwin()) {
    // The native darwin assembler doesn't support the linker_option directives,
    // so we disable them if we think the .s file will be passed to it.
    Default = TC.useIntegratedAs();
  }
  return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
                       Default);
}

static bool ShouldDisableDwarfDirectory(const ArgList &Args,
                                        const ToolChain &TC) {
  bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
                                        options::OPT_fno_dwarf_directory_asm,
                                        TC.useIntegratedAs());
  return !UseDwarfDirectory;
}

/// \brief Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
  if (isa<CompileJobAction>(A))
    return true;

  for (const auto &Act : *A)
    if (ContainsCompileAction(Act))
      return true;

  return false;
}

/// \brief Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
  bool RelaxDefault = true;

  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    RelaxDefault = A->getOption().matches(options::OPT_O0);

  if (RelaxDefault) {
    RelaxDefault = false;
    for (const auto &Act : C.getActions()) {
      if (ContainsCompileAction(Act)) {
        RelaxDefault = true;
        break;
      }
    }
  }

  return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
    RelaxDefault);
}

static void CollectArgsForIntegratedAssembler(Compilation &C,
                                              const ArgList &Args,
                                              ArgStringList &CmdArgs,
                                              const Driver &D) {
    if (UseRelaxAll(C, Args))
      CmdArgs.push_back("-mrelax-all");

    // When passing -I arguments to the assembler we sometimes need to
    // unconditionally take the next argument.  For example, when parsing
    // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
    // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
    // arg after parsing the '-I' arg.
    bool TakeNextArg = false;

    // When using an integrated assembler, translate -Wa, and -Xassembler
    // options.
    bool CompressDebugSections = false;
    for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
                                               options::OPT_Xassembler),
           ie = Args.filtered_end(); it != ie; ++it) {
      const Arg *A = *it;
      A->claim();

      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
        StringRef Value = A->getValue(i);
        if (TakeNextArg) {
          CmdArgs.push_back(Value.data());
          TakeNextArg = false;
          continue;
        }

        if (Value == "-force_cpusubtype_ALL") {
          // Do nothing, this is the default and we don't support anything else.
        } else if (Value == "-L") {
          CmdArgs.push_back("-msave-temp-labels");
        } else if (Value == "--fatal-warnings") {
          CmdArgs.push_back("-mllvm");
          CmdArgs.push_back("-fatal-assembler-warnings");
        } else if (Value == "--noexecstack") {
          CmdArgs.push_back("-mnoexecstack");
        } else if (Value == "-compress-debug-sections" ||
                   Value == "--compress-debug-sections") {
          CompressDebugSections = true;
        } else if (Value == "-nocompress-debug-sections" ||
                   Value == "--nocompress-debug-sections") {
          CompressDebugSections = false;
        } else if (Value.startswith("-I")) {
          CmdArgs.push_back(Value.data());
          // We need to consume the next argument if the current arg is a plain
          // -I. The next arg will be the include directory.
          if (Value == "-I")
            TakeNextArg = true;
        } else if (Value.startswith("-gdwarf-")) {
          CmdArgs.push_back(Value.data());
        } else {
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
        }
      }
    }
    if (CompressDebugSections) {
      if (llvm::zlib::isAvailable())
        CmdArgs.push_back("-compress-debug-sections");
      else
        D.Diag(diag::warn_debug_compression_unavailable);
    }
}

// Until ARM libraries are build separately, we have them all in one library
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
  if (TC.getArch() == llvm::Triple::arm ||
      TC.getArch() == llvm::Triple::armeb)
    return "arm";
  else
    return TC.getArchName();
}

static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
  // The runtimes are located in the OS-specific resource directory.
  SmallString<128> Res(TC.getDriver().ResourceDir);
  const llvm::Triple &Triple = TC.getTriple();
  // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
  StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
    "freebsd" : TC.getOS();
  llvm::sys::path::append(Res, "lib", OSLibName);
  return Res;
}

// This adds the static libclang_rt.builtins-arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
static void addClangRTLinux(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
                                          getArchNameForCompilerRTLib(TC) +
                                          ".a");

  CmdArgs.push_back(Args.MakeArgString(LibClangRT));
  CmdArgs.push_back("-lgcc_s");
  if (TC.getDriver().CCCIsCXX())
    CmdArgs.push_back("-lgcc_eh");
}

static void addProfileRT(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                     false) ||
        Args.hasArg(options::OPT_fprofile_generate) ||
        Args.hasArg(options::OPT_fprofile_instr_generate) ||
        Args.hasArg(options::OPT_fcreate_profile) ||
        Args.hasArg(options::OPT_coverage)))
    return;

  // -fprofile-instr-generate requires position-independent code to build with
  // shared objects.  Link against the right archive.
  const char *Lib = "libclang_rt.profile-";
  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      Args.hasArg(options::OPT_shared))
    Lib = "libclang_rt.profile-pic-";

  SmallString<128> LibProfile = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibProfile,
      Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");

  CmdArgs.push_back(Args.MakeArgString(LibProfile));
}

static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
                                              const StringRef Sanitizer,
                                              bool Shared) {
  // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
  // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
  const char *EnvSuffix =
    TC.getTriple().getEnvironment() == llvm::Triple::Android ?  "-android" : "";
  SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibSanitizer,
                          Twine("libclang_rt.") + Sanitizer + "-" +
                              getArchNameForCompilerRTLib(TC) + EnvSuffix +
                              (Shared ? ".so" : ".a"));
  return LibSanitizer;
}

static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const StringRef Sanitizer,
                                    bool BeforeLibStdCXX,
                                    bool ExportSymbols = true,
                                    bool LinkDeps = true) {
  SmallString<128> LibSanitizer =
      getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);

  // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
  // etc.) so that the linker picks custom versions of the global 'operator
  // new' and 'operator delete' symbols. We take the extreme (but simple)
  // strategy of inserting it at the front of the link command. It also
  // needs to be forced to end up in the executable, so wrap it in
  // whole-archive.
  SmallVector<const char *, 3> LibSanitizerArgs;
  LibSanitizerArgs.push_back("-whole-archive");
  LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
  LibSanitizerArgs.push_back("-no-whole-archive");

  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());

  if (LinkDeps) {
    // Link sanitizer dependencies explicitly
    CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lrt");
    CmdArgs.push_back("-lm");
    // There's no libdl on FreeBSD.
    if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
      CmdArgs.push_back("-ldl");
  }

  // If possible, use a dynamic symbols file to export the symbols from the
  // runtime library. If we can't do so, use -export-dynamic instead to export
  // all symbols from the binary.
  if (ExportSymbols) {
    if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
      CmdArgs.push_back(
          Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
    else
      CmdArgs.push_back("-export-dynamic");
  }
}

/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
  if (Shared) {
    // Link dynamic runtime if necessary.
    SmallString<128> LibSanitizer =
        getSanitizerRTLibName(TC, "asan", Shared);
    CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
  }

  // Do not link static runtime to DSOs or if compiling for Android.
  if (Args.hasArg(options::OPT_shared) ||
      (TC.getTriple().getEnvironment() == llvm::Triple::Android))
    return;

  if (Shared) {
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
                            /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
                            /*LinkDeps*/ false);
  } else {
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
    if (IsCXX)
      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
  }
}

/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addTsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true);
}

/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addMsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true);
}

/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addLsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
}

/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs, bool IsCXX,
                       bool HasOtherSanitizerRt) {
  // Do not link runtime into shared libraries.
  if (Args.hasArg(options::OPT_shared))
    return;

  // Need a copy of sanitizer_common. This could come from another sanitizer
  // runtime; if we're not including one, include our own copy.
  if (!HasOtherSanitizerRt)
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);

  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true);

  // Only include the bits of the runtime which need a C++ ABI library if
  // we're linking in C++ mode.
  if (IsCXX)
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true);
}

static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
}

// Should be called before we add C++ ABI library.
static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
                                 ArgStringList &CmdArgs) {
  const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
  if (Sanitize.needsUbsanRt())
    addUbsanRT(TC, Args, CmdArgs, Sanitize.linkCXXRuntimes(),
               Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                   Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
  if (Sanitize.needsAsanRt())
    addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(),
              Sanitize.linkCXXRuntimes());
  if (Sanitize.needsTsanRt())
    addTsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsMsanRt())
    addMsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsLsanRt())
    addLsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsDfsanRt())
    addDfsanRT(TC, Args, CmdArgs);
}

static bool shouldUseFramePointerForTarget(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  // Don't use a frame pointer on linux if optimizing for certain targets.
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::systemz:
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    if (Triple.isOSLinux())
      if (Arg *A = Args.getLastArg(options::OPT_O_Group))
        if (!A->getOption().matches(options::OPT_O0))
          return false;
    return true;
  case llvm::Triple::xcore:
    return false;
  default:
    return true;
  }
}

static bool shouldUseFramePointer(const ArgList &Args,
                                  const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
                               options::OPT_fomit_frame_pointer))
    return A->getOption().matches(options::OPT_fno_omit_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

static bool shouldUseLeafFramePointer(const ArgList &Args,
                                      const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
                               options::OPT_momit_leaf_frame_pointer))
    return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> cwd;
  if (!llvm::sys::fs::current_path(cwd)) {
    CmdArgs.push_back("-fdebug-compilation-dir");
    CmdArgs.push_back(Args.MakeArgString(cwd));
  }
}

static const char *SplitDebugName(const ArgList &Args,
                                  const InputInfoList &Inputs) {
  Arg *FinalOutput = Args.getLastArg(options::OPT_o);
  if (FinalOutput && Args.hasArg(options::OPT_c)) {
    SmallString<128> T(FinalOutput->getValue());
    llvm::sys::path::replace_extension(T, "dwo");
    return Args.MakeArgString(T);
  } else {
    // Use the compilation dir.
    SmallString<128> T(
        Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
    SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
    llvm::sys::path::replace_extension(F, "dwo");
    T += F;
    return Args.MakeArgString(F);
  }
}

static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
                           const Tool &T, const JobAction &JA,
                           const ArgList &Args, const InputInfo &Output,
                           const char *OutFile) {
  ArgStringList ExtractArgs;
  ExtractArgs.push_back("--extract-dwo");

  ArgStringList StripArgs;
  StripArgs.push_back("--strip-dwo");

  // Grabbing the output of the earlier compile step.
  StripArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(OutFile);

  const char *Exec =
    Args.MakeArgString(TC.GetProgramPath("objcopy"));

  // First extract the dwo sections.
  C.addCommand(new Command(JA, T, Exec, ExtractArgs));

  // Then remove them from the original .o file.
  C.addCommand(new Command(JA, T, Exec, StripArgs));
}

/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      return true;

    if (A->getOption().matches(options::OPT_O0))
      return false;

    assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");

    // Vectorize -Os.
    StringRef S(A->getValue());
    if (S == "s")
      return true;

    // Don't vectorize -Oz, unless it's the slp vectorizer.
    if (S == "z")
      return isSlpVec;

    unsigned OptLevel = 0;
    if (S.getAsInteger(10, OptLevel))
      return false;

    return OptLevel > 1;
  }

  return false;
}

/// Add -x lang to \p CmdArgs for \p Input.
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
                             ArgStringList &CmdArgs) {
  // When using -verify-pch, we don't want to provide the type
  // 'precompiled-header' if it was inferred from the file extension
  if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
    return;

  CmdArgs.push_back("-x");
  if (Args.hasArg(options::OPT_rewrite_objc))
    CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
  else
    CmdArgs.push_back(types::getTypeName(Input.getType()));
}

static std::string getMSCompatibilityVersion(const char *VersionStr) {
  unsigned Version;
  if (StringRef(VersionStr).getAsInteger(10, Version))
    return "0";

  if (Version < 100)
    return llvm::utostr_32(Version) + ".0";

  if (Version < 10000)
    return llvm::utostr_32(Version / 100) + "." +
        llvm::utostr_32(Version % 100);

  unsigned Build = 0, Factor = 1;
  for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
    Build = Build + (Version % 10) * Factor;
  return llvm::utostr_32(Version / 100) + "." +
      llvm::utostr_32(Version % 100) + "." +
      llvm::utostr_32(Build);
}

void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                         const InputInfo &Output,
                         const InputInfoList &Inputs,
                         const ArgList &Args,
                         const char *LinkingOutput) const {
  bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
                                  options::OPT_fapple_kext);
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
  bool IsWindowsCygnus =
      getToolChain().getTriple().isWindowsCygwinEnvironment();
  bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");

  // Invoke ourselves in -cc1 mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  const llvm::Triple TT(TripleStr);
  if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                           TT.getArch() == llvm::Triple::thumb)) {
    unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
    unsigned Version;
    TT.getArchName().substr(Offset).getAsInteger(10, Version);
    if (Version < 7)
      D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
                                                << TripleStr;
  }

  // Push all default warning arguments that are specific to
  // the given target.  These come before user provided warning options
  // are provided.
  getToolChain().addClangWarningOptions(CmdArgs);

  // Select the appropriate action.
  RewriteKind rewriteKind = RK_None;
  
  if (isa<AnalyzeJobAction>(JA)) {
    assert(JA.getType() == types::TY_Plist && "Invalid output type.");
    CmdArgs.push_back("-analyze");
  } else if (isa<MigrateJobAction>(JA)) {
    CmdArgs.push_back("-migrate");
  } else if (isa<PreprocessJobAction>(JA)) {
    if (Output.getType() == types::TY_Dependencies)
      CmdArgs.push_back("-Eonly");
    else {
      CmdArgs.push_back("-E");
      if (Args.hasArg(options::OPT_rewrite_objc) &&
          !Args.hasArg(options::OPT_g_Group))
        CmdArgs.push_back("-P");
    }
  } else if (isa<AssembleJobAction>(JA)) {
    CmdArgs.push_back("-emit-obj");

    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);

    // Also ignore explicit -force_cpusubtype_ALL option.
    (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
  } else if (isa<PrecompileJobAction>(JA)) {
    // Use PCH if the user requested it.
    bool UsePCH = D.CCCUsePCH;

    if (JA.getType() == types::TY_Nothing)
      CmdArgs.push_back("-fsyntax-only");
    else if (UsePCH)
      CmdArgs.push_back("-emit-pch");
    else
      CmdArgs.push_back("-emit-pth");
  } else if (isa<VerifyPCHJobAction>(JA)) {
    CmdArgs.push_back("-verify-pch");
  } else {
    assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");

    if (JA.getType() == types::TY_Nothing) {
      CmdArgs.push_back("-fsyntax-only");
    } else if (JA.getType() == types::TY_LLVM_IR ||
               JA.getType() == types::TY_LTO_IR) {
      CmdArgs.push_back("-emit-llvm");
    } else if (JA.getType() == types::TY_LLVM_BC ||
               JA.getType() == types::TY_LTO_BC) {
      CmdArgs.push_back("-emit-llvm-bc");
    } else if (JA.getType() == types::TY_PP_Asm) {
      CmdArgs.push_back("-S");
    } else if (JA.getType() == types::TY_AST) {
      CmdArgs.push_back("-emit-pch");
    } else if (JA.getType() == types::TY_ModuleFile) {
      CmdArgs.push_back("-module-file-info");
    } else if (JA.getType() == types::TY_RewrittenObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_NonFragile;
    } else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_Fragile;
    } else {
      assert(JA.getType() == types::TY_PP_Asm &&
             "Unexpected output type!");
    }
  }

  // We normally speed up the clang process a bit by skipping destructors at
  // exit, but when we're generating diagnostics we can rely on some of the
  // cleanup.
  if (!C.isForDiagnostics())
    CmdArgs.push_back("-disable-free");

  // Disable the verification pass in -asserts builds.
#ifdef NDEBUG
  CmdArgs.push_back("-disable-llvm-verifier");
#endif

  // Set the main file name, so that debug info works even with
  // -save-temps.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(getBaseInputName(Args, Inputs));

  // Some flags which affect the language (via preprocessor
  // defines).
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-static-define");

  if (isa<AnalyzeJobAction>(JA)) {
    // Enable region store model by default.
    CmdArgs.push_back("-analyzer-store=region");

    // Treat blocks as analysis entry points.
    CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");

    CmdArgs.push_back("-analyzer-eagerly-assume");

    // Add default argument set.
    if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
      CmdArgs.push_back("-analyzer-checker=core");

      if (!IsWindowsMSVC)
        CmdArgs.push_back("-analyzer-checker=unix");

      if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
        CmdArgs.push_back("-analyzer-checker=osx");
      
      CmdArgs.push_back("-analyzer-checker=deadcode");
      
      if (types::isCXX(Inputs[0].getType()))
        CmdArgs.push_back("-analyzer-checker=cplusplus");

      // Enable the following experimental checkers for testing.
      CmdArgs.push_back(
          "-analyzer-checker=security.insecureAPI.UncheckedReturn");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");      
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
    }

    // Set the output format. The default is plist, for (lame) historical
    // reasons.
    CmdArgs.push_back("-analyzer-output");
    if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
      CmdArgs.push_back(A->getValue());
    else
      CmdArgs.push_back("plist");

    // Disable the presentation of standard compiler warnings when
    // using --analyze.  We only want to show static analyzer diagnostics
    // or frontend errors.
    CmdArgs.push_back("-w");

    // Add -Xanalyzer arguments when running as analyzer.
    Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
  }

  CheckCodeGenerationOptions(D, Args);

  bool PIE = getToolChain().isPIEDefault();
  bool PIC = PIE || getToolChain().isPICDefault();
  bool IsPICLevelTwo = PIC;

  // Android-specific defaults for PIC/PIE
  if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
    case llvm::Triple::aarch64:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      PIC = true; // "-fpic"
      break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      PIC = true; // "-fPIC"
      IsPICLevelTwo = true;
      break;

    default:
      break;
    }
  }

  // OpenBSD-specific defaults for PIE
  if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
    case llvm::Triple::sparc:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      IsPICLevelTwo = false; // "-fpie"
      break;

    case llvm::Triple::ppc:
    case llvm::Triple::sparcv9:
      IsPICLevelTwo = true; // "-fPIE"
      break;

    default:
      break;
    }
  }

  // For the PIC and PIE flag options, this logic is different from the
  // legacy logic in very old versions of GCC, as that logic was just
  // a bug no one had ever fixed. This logic is both more rational and
  // consistent with GCC's new logic now that the bugs are fixed. The last
  // argument relating to either PIC or PIE wins, and no other argument is
  // used. If the last argument is any flavor of the '-fno-...' arguments,
  // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
  // at the same level.
  Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                 options::OPT_fpic, options::OPT_fno_pic,
                                 options::OPT_fPIE, options::OPT_fno_PIE,
                                 options::OPT_fpie, options::OPT_fno_pie);
  // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
  // is forced, then neither PIC nor PIE flags will have no effect.
  if (!getToolChain().isPICDefaultForced()) {
    if (LastPICArg) {
      Option O = LastPICArg->getOption();
      if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
          O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
        PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
        PIC = PIE || O.matches(options::OPT_fPIC) ||
              O.matches(options::OPT_fpic);
        IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
                        O.matches(options::OPT_fPIC);
      } else {
        PIE = PIC = false;
      }
    }
  }

  // Introduce a Darwin-specific hack. If the default is PIC but the flags
  // specified while enabling PIC enabled level 1 PIC, just force it back to
  // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
  // informal testing).
  if (PIC && getToolChain().getTriple().isOSDarwin())
    IsPICLevelTwo |= getToolChain().isPICDefault();

  // Note that these flags are trump-cards. Regardless of the order w.r.t. the
  // PIC or PIE options above, if these show up, PIC is disabled.
  llvm::Triple Triple(TripleStr);
  if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
                       Triple.getArch() == llvm::Triple::aarch64))
    PIC = PIE = false;
  if (Args.hasArg(options::OPT_static))
    PIC = PIE = false;

  if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
    // This is a very special mode. It trumps the other modes, almost no one
    // uses it, and it isn't even valid on any OS but Darwin.
    if (!getToolChain().getTriple().isOSDarwin())
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();

    // FIXME: Warn when this flag trumps some other PIC or PIE flag.

    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back("dynamic-no-pic");

    // Only a forced PIC mode can cause the actual compile to have PIC defines
    // etc., no flags are sufficient. This behavior was selected to closely
    // match that of llvm-gcc and Apple GCC before that.
    if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back("2");
    }
  } else {
    // Currently, LLVM only knows about PIC vs. static; the PIE differences are
    // handled in Clang's IRGen by the -pie-level flag.
    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back(PIC ? "pic" : "static");

    if (PIC) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      if (PIE) {
        CmdArgs.push_back("-pie-level");
        CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      }
    }
  }

  if (!Args.hasFlag(options::OPT_fmerge_all_constants,
                    options::OPT_fno_merge_all_constants))
    CmdArgs.push_back("-fno-merge-all-constants");

  // LLVM Code Generator Options.

  if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
    StringRef v = A->getValue();
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
    A->claim();
  }

  if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
    CmdArgs.push_back("-mregparm");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
                               options::OPT_freg_struct_return)) {
    if (getToolChain().getArch() != llvm::Triple::x86) {
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();
    } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
      CmdArgs.push_back("-fpcc-struct-return");
    } else {
      assert(A->getOption().matches(options::OPT_freg_struct_return));
      CmdArgs.push_back("-freg-struct-return");
    }
  }

  if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
    CmdArgs.push_back("-mrtd");

  if (shouldUseFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-mdisable-fp-elim");
  if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
                    options::OPT_fno_zero_initialized_in_bss))
    CmdArgs.push_back("-mno-zero-initialized-in-bss");

  bool OFastEnabled = isOptimizationLevelFast(Args);
  // If -Ofast is the optimization level, then -fstrict-aliasing should be
  // enabled.  This alias option is being used to simplify the hasFlag logic.
  OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_fstrict_aliasing;
  // We turn strict aliasing off by default if we're in CL mode, since MSVC
  // doesn't do any TBAA.
  bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
  if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
                    options::OPT_fno_strict_aliasing, TBAAOnByDefault))
    CmdArgs.push_back("-relaxed-aliasing");
  if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
                    options::OPT_fno_struct_path_tbaa))
    CmdArgs.push_back("-no-struct-path-tbaa");
  if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
                   false))
    CmdArgs.push_back("-fstrict-enums");
  if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
                    options::OPT_fno_optimize_sibling_calls))
    CmdArgs.push_back("-mdisable-tail-calls");

  // Handle segmented stacks.
  if (Args.hasArg(options::OPT_fsplit_stack))
    CmdArgs.push_back("-split-stacks");

  // If -Ofast is the optimization level, then -ffast-math should be enabled.
  // This alias option is being used to simplify the getLastArg logic.
  OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_ffast_math;
  
  // Handle various floating point optimization flags, mapping them to the
  // appropriate LLVM code generation flags. The pattern for all of these is to
  // default off the codegen optimizations, and if any flag enables them and no
  // flag disables them after the flag enabling them, enable the codegen
  // optimization. This is complicated by several "umbrella" flags.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_infinities,
                               options::OPT_fno_honor_infinities))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_infinities)
      CmdArgs.push_back("-menable-no-infs");
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_nans,
                               options::OPT_fno_honor_nans))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_nans)
      CmdArgs.push_back("-menable-no-nans");

  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
  bool MathErrno = getToolChain().IsMathErrnoDefault();
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_fmath_errno,
                               options::OPT_fno_math_errno)) {
    // Turning on -ffast_math (with either flag) removes the need for MathErrno.
    // However, turning *off* -ffast_math merely restores the toolchain default
    // (which may be false).
    if (A->getOption().getID() == options::OPT_fno_math_errno ||
        A->getOption().getID() == options::OPT_ffast_math ||
        A->getOption().getID() == options::OPT_Ofast)
      MathErrno = false;
    else if (A->getOption().getID() == options::OPT_fmath_errno)
      MathErrno = true;
  }
  if (MathErrno)
    CmdArgs.push_back("-fmath-errno");

  // There are several flags which require disabling very specific
  // optimizations. Any of these being disabled forces us to turn off the
  // entire set of LLVM optimizations, so collect them through all the flag
  // madness.
  bool AssociativeMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fassociative_math,
                               options::OPT_fno_associative_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_associative_math)
      AssociativeMath = true;
  bool ReciprocalMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_freciprocal_math,
                               options::OPT_fno_reciprocal_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_reciprocal_math)
      ReciprocalMath = true;
  bool SignedZeros = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fsigned_zeros,
                               options::OPT_fno_signed_zeros))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fsigned_zeros)
      SignedZeros = false;
  bool TrappingMath = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_ftrapping_math,
                               options::OPT_fno_trapping_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_ftrapping_math)
      TrappingMath = false;
  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
      !TrappingMath)
    CmdArgs.push_back("-menable-unsafe-fp-math");


  // Validate and pass through -fp-contract option. 
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffp_contract)) {
    if (A->getOption().getID() == options::OPT_ffp_contract) {
      StringRef Val = A->getValue();
      if (Val == "fast" || Val == "on" || Val == "off") {
        CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
      }
    } else if (A->getOption().matches(options::OPT_ffast_math) ||
               (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
      // If fast-math is set then set the fp-contract mode to fast.
      CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
    }
  }

  // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
  // and if we find them, tell the frontend to provide the appropriate
  // preprocessor macros. This is distinct from enabling any optimizations as
  // these options induce language changes which must survive serialization
  // and deserialization, etc.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math))
      if (!A->getOption().matches(options::OPT_fno_fast_math))
        CmdArgs.push_back("-ffast-math");
  if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
                               options::OPT_fno_fast_math))
    if (A->getOption().matches(options::OPT_ffinite_math_only))
      CmdArgs.push_back("-ffinite-math-only");

  // Decide whether to use verbose asm. Verbose assembly is the default on
  // toolchains which have the integrated assembler on by default.
  bool IsIntegratedAssemblerDefault =
      getToolChain().IsIntegratedAssemblerDefault();
  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   IsIntegratedAssemblerDefault) ||
      Args.hasArg(options::OPT_dA))
    CmdArgs.push_back("-masm-verbose");

  if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
                    IsIntegratedAssemblerDefault))
    CmdArgs.push_back("-no-integrated-as");

  if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Structure");
  }
  if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Arguments");
  }

  // Enable -mconstructor-aliases except on darwin, where we have to
  // work around a linker bug;  see <rdar://problem/7651567>.
  if (!getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-mconstructor-aliases");

  // Darwin's kernel doesn't support guard variables; just die if we
  // try to use them.
  if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-fforbid-guard-variables");

  if (Args.hasArg(options::OPT_mms_bitfields)) {
    CmdArgs.push_back("-mms-bitfields");
  }

  // This is a coarse approximation of what llvm-gcc actually does, both
  // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
  // complicated ways.
  bool AsynchronousUnwindTables =
      Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
                   options::OPT_fno_asynchronous_unwind_tables,
                   (getToolChain().IsUnwindTablesDefault() ||
                    getToolChain().getSanitizerArgs().needsUnwindTables()) &&
                       !KernelOrKext);
  if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
                   AsynchronousUnwindTables))
    CmdArgs.push_back("-munwind-tables");

  getToolChain().addClangTargetOptions(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
    CmdArgs.push_back("-mlimit-float-precision");
    CmdArgs.push_back(A->getValue());
  }

  // FIXME: Handle -mtune=.
  (void) Args.hasArg(options::OPT_mtune_EQ);

  if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
    CmdArgs.push_back("-mcode-model");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target cpu
  std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple ETriple(ETripleStr);
  std::string CPU = getCPUName(Args, ETriple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
    CmdArgs.push_back("-mfpmath");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target features
  getTargetFeatures(D, ETriple, Args, CmdArgs, false);

  // Add target specific flags.
  switch(getToolChain().getArch()) {
  default:
    break;

  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
    break;

  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
    AddAArch64TargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    AddMIPSTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    AddPPCTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::sparc:
  case llvm::Triple::sparcv9:
    AddSparcTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    AddX86TargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::hexagon:
    AddHexagonTargetArgs(Args, CmdArgs);
    break;
  }

  // Add clang-cl arguments.
  if (getToolChain().getDriver().IsCLMode())
    AddClangCLArgs(Args, CmdArgs);

  // 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());
  }

  if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-momit-leaf-frame-pointer");

  // Explicitly error on some things we know we don't support and can't just
  // ignore.
  types::ID InputType = Inputs[0].getType();
  if (!Args.hasArg(options::OPT_fallow_unsupported)) {
    Arg *Unsupported;
    if (types::isCXX(InputType) &&
        getToolChain().getTriple().isOSDarwin() &&
        getToolChain().getArch() == llvm::Triple::x86) {
      if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
          (Unsupported = Args.getLastArg(options::OPT_mkernel)))
        D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
          << Unsupported->getOption().getName();
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_v);
  Args.AddLastArg(CmdArgs, options::OPT_H);
  if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-header-include-file");
    CmdArgs.push_back(D.CCPrintHeadersFilename ?
                      D.CCPrintHeadersFilename : "-");
  }
  Args.AddLastArg(CmdArgs, options::OPT_P);
  Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);

  if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-diagnostic-log-file");
    CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
                      D.CCLogDiagnosticsFilename : "-");
  }

  // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
  // are preserved, all other debug options are substituted with "-g".
  Args.ClaimAllArgs(options::OPT_g_Group);
  if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    if (A->getOption().matches(options::OPT_gline_tables_only)) {
      // FIXME: we should support specifying dwarf version with
      // -gline-tables-only.
      CmdArgs.push_back("-gline-tables-only");
      // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
      const llvm::Triple &Triple = getToolChain().getTriple();
      if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
          Triple.getOS() == llvm::Triple::FreeBSD)
        CmdArgs.push_back("-gdwarf-2");
    } else if (A->getOption().matches(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    else if (A->getOption().matches(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    else if (A->getOption().matches(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");
    else if (!A->getOption().matches(options::OPT_g0) &&
             !A->getOption().matches(options::OPT_ggdb0)) {
      // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
      const llvm::Triple &Triple = getToolChain().getTriple();
      if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
          Triple.getOS() == llvm::Triple::FreeBSD)
        CmdArgs.push_back("-gdwarf-2");
      else
        CmdArgs.push_back("-g");
    }
  }

  // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
  Args.ClaimAllArgs(options::OPT_g_flags_Group);
  if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
                   /*Default*/ true))
    CmdArgs.push_back("-dwarf-column-info");

  // FIXME: Move backend command line options to the module.
  // -gsplit-dwarf should turn on -g and enable the backend dwarf
  // splitting and extraction.
  // FIXME: Currently only works on Linux.
  if (getToolChain().getTriple().isOSLinux() &&
      Args.hasArg(options::OPT_gsplit_dwarf)) {
    CmdArgs.push_back("-g");
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-split-dwarf=Enable");
  }

  // -ggnu-pubnames turns on gnu style pubnames in the backend.
  if (Args.hasArg(options::OPT_ggnu_pubnames)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
  }

  // -gdwarf-aranges turns on the emission of the aranges section in the
  // backend.
  if (Args.hasArg(options::OPT_gdwarf_aranges)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-arange-section");
  }

  if (Args.hasFlag(options::OPT_fdebug_types_section,
                   options::OPT_fno_debug_types_section, false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-type-units");
  }

  if (Args.hasFlag(options::OPT_ffunction_sections,
                   options::OPT_fno_function_sections, false)) {
    CmdArgs.push_back("-ffunction-sections");
  }

  if (Args.hasFlag(options::OPT_fdata_sections,
                   options::OPT_fno_data_sections, false)) {
    CmdArgs.push_back("-fdata-sections");
  }

  Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);

  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      (Args.hasArg(options::OPT_fprofile_instr_use) ||
       Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
    D.Diag(diag::err_drv_argument_not_allowed_with)
      << "-fprofile-instr-generate" << "-fprofile-instr-use";

  Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);

  if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
    A->render(Args, CmdArgs);
  else if (Args.hasArg(options::OPT_fprofile_instr_use))
    CmdArgs.push_back("-fprofile-instr-use=pgo-data");

  if (Args.hasArg(options::OPT_ftest_coverage) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-notes");
  if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
                   false) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-data");

  if (Args.hasArg(options::OPT_fcoverage_mapping) &&
      !Args.hasArg(options::OPT_fprofile_instr_generate))
    D.Diag(diag::err_drv_argument_only_allowed_with)
      << "-fcoverage-mapping" << "-fprofile-instr-generate";

  if (Args.hasArg(options::OPT_fcoverage_mapping))
    CmdArgs.push_back("-fcoverage-mapping");

  if (C.getArgs().hasArg(options::OPT_c) ||
      C.getArgs().hasArg(options::OPT_S)) {
    if (Output.isFilename()) {
      CmdArgs.push_back("-coverage-file");
      SmallString<128> CoverageFilename(Output.getFilename());
      if (llvm::sys::path::is_relative(CoverageFilename.str())) {
        SmallString<128> Pwd;
        if (!llvm::sys::fs::current_path(Pwd)) {
          llvm::sys::path::append(Pwd, CoverageFilename.str());
          CoverageFilename.swap(Pwd);
        }
      }
      CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
    }
  }

  // Pass options for controlling the default header search paths.
  if (Args.hasArg(options::OPT_nostdinc)) {
    CmdArgs.push_back("-nostdsysteminc");
    CmdArgs.push_back("-nobuiltininc");
  } else {
    if (Args.hasArg(options::OPT_nostdlibinc))
        CmdArgs.push_back("-nostdsysteminc");
    Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
    Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
  }

  // Pass the path to compiler resource files.
  CmdArgs.push_back("-resource-dir");
  CmdArgs.push_back(D.ResourceDir.c_str());

  Args.AddLastArg(CmdArgs, options::OPT_working_directory);

  bool ARCMTEnabled = false;
  if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
    if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
                                       options::OPT_ccc_arcmt_modify,
                                       options::OPT_ccc_arcmt_migrate)) {
      ARCMTEnabled = true;
      switch (A->getOption().getID()) {
      default:
        llvm_unreachable("missed a case");
      case options::OPT_ccc_arcmt_check:
        CmdArgs.push_back("-arcmt-check");
        break;
      case options::OPT_ccc_arcmt_modify:
        CmdArgs.push_back("-arcmt-modify");
        break;
      case options::OPT_ccc_arcmt_migrate:
        CmdArgs.push_back("-arcmt-migrate");
        CmdArgs.push_back("-mt-migrate-directory");
        CmdArgs.push_back(A->getValue());

        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
        break;
      }
    }
  } else {
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
  }

  if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
    if (ARCMTEnabled) {
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-ccc-arcmt-migrate";
    }
    CmdArgs.push_back("-mt-migrate-directory");
    CmdArgs.push_back(A->getValue());

    if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
                     options::OPT_objcmt_migrate_subscripting,
                     options::OPT_objcmt_migrate_property)) {
      // None specified, means enable them all.
      CmdArgs.push_back("-objcmt-migrate-literals");
      CmdArgs.push_back("-objcmt-migrate-subscripting");
      CmdArgs.push_back("-objcmt-migrate-property");
    } else {
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    }
  } else {
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
  }

  // Add preprocessing options like -I, -D, etc. if we are using the
  // preprocessor.
  //
  // FIXME: Support -fpreprocessed
  if (types::getPreprocessedType(InputType) != types::TY_INVALID)
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);

  // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
  // that "The compiler can only warn and ignore the option if not recognized".
  // When building with ccache, it will pass -D options to clang even on
  // preprocessed inputs and configure concludes that -fPIC is not supported.
  Args.ClaimAllArgs(options::OPT_D);

  // Manually translate -O4 to -O3; let clang reject others.
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4)) {
      CmdArgs.push_back("-O3");
      D.Diag(diag::warn_O4_is_O3);
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Warn about ignored options to clang.
  for (arg_iterator it = Args.filtered_begin(
       options::OPT_clang_ignored_gcc_optimization_f_Group),
       ie = Args.filtered_end(); it != ie; ++it) {
    D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
  }

  // Don't warn about unused -flto.  This can happen when we're preprocessing or
  // precompiling.
  Args.ClaimAllArgs(options::OPT_flto);

  Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
  if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
    CmdArgs.push_back("-pedantic");
  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
  Args.AddLastArg(CmdArgs, options::OPT_w);

  // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
  // (-ansi is equivalent to -std=c89 or -std=c++98).
  //
  // If a std is supplied, only add -trigraphs if it follows the
  // option.
  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
    if (Std->getOption().matches(options::OPT_ansi))
      if (types::isCXX(InputType))
        CmdArgs.push_back("-std=c++98");
      else
        CmdArgs.push_back("-std=c89");
    else
      Std->render(Args, CmdArgs);

    if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
                                 options::OPT_trigraphs))
      if (A != Std)
        A->render(Args, CmdArgs);
  } else {
    // Honor -std-default.
    //
    // FIXME: Clang doesn't correctly handle -std= when the input language
    // doesn't match. For the time being just ignore this for C++ inputs;
    // eventually we want to do all the standard defaulting here instead of
    // splitting it between the driver and clang -cc1.
    if (!types::isCXX(InputType))
      Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
                                "-std=", /*Joined=*/true);
    else if (IsWindowsMSVC)
      CmdArgs.push_back("-std=c++11");

    Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
  }

  // GCC's behavior for -Wwrite-strings is a bit strange:
  //  * In C, this "warning flag" changes the types of string literals from
  //    'char[N]' to 'const char[N]', and thus triggers an unrelated warning
  //    for the discarded qualifier.
  //  * In C++, this is just a normal warning flag.
  //
  // Implementing this warning correctly in C is hard, so we follow GCC's
  // behavior for now. FIXME: Directly diagnose uses of a string literal as
  // a non-const char* in C, rather than using this crude hack.
  if (!types::isCXX(InputType)) {
    // FIXME: This should behave just like a warning flag, and thus should also
    // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
    Arg *WriteStrings =
        Args.getLastArg(options::OPT_Wwrite_strings,
                        options::OPT_Wno_write_strings, options::OPT_w);
    if (WriteStrings &&
        WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
      CmdArgs.push_back("-fconst-strings");
  }

  // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
  // during C++ compilation, which it is by default. GCC keeps this define even
  // in the presence of '-w', match this behavior bug-for-bug.
  if (types::isCXX(InputType) &&
      Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated,
                   true)) {
    CmdArgs.push_back("-fdeprecated-macro");
  }

  // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
  if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
    if (Asm->getOption().matches(options::OPT_fasm))
      CmdArgs.push_back("-fgnu-keywords");
    else
      CmdArgs.push_back("-fno-gnu-keywords");
  }

  if (ShouldDisableDwarfDirectory(Args, getToolChain()))
    CmdArgs.push_back("-fno-dwarf-directory-asm");

  if (ShouldDisableAutolink(Args, getToolChain()))
    CmdArgs.push_back("-fno-autolink");

  // Add in -fdebug-compilation-dir if necessary.
  addDebugCompDirArg(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
                               options::OPT_ftemplate_depth_EQ)) {
    CmdArgs.push_back("-ftemplate-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
    CmdArgs.push_back("-foperator-arrow-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
    CmdArgs.push_back("-fconstexpr-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
    CmdArgs.push_back("-fconstexpr-steps");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
    CmdArgs.push_back("-fbracket-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
                               options::OPT_Wlarge_by_value_copy_def)) {
    if (A->getNumValues()) {
      StringRef bytes = A->getValue();
      CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
    } else
      CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
  }


  if (Args.hasArg(options::OPT_relocatable_pch))
    CmdArgs.push_back("-relocatable-pch");

  if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
    CmdArgs.push_back("-fconstant-string-class");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
    CmdArgs.push_back("-ftabstop");
    CmdArgs.push_back(A->getValue());
  }

  CmdArgs.push_back("-ferror-limit");
  if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
    CmdArgs.push_back(A->getValue());
  else
    CmdArgs.push_back("19");

  if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fmacro-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
    CmdArgs.push_back("-ftemplate-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fconstexpr-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  // Pass -fmessage-length=.
  CmdArgs.push_back("-fmessage-length");
  if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
    CmdArgs.push_back(A->getValue());
  } else {
    // If -fmessage-length=N was not specified, determine whether this is a
    // terminal and, if so, implicitly define -fmessage-length appropriately.
    unsigned N = llvm::sys::Process::StandardErrColumns();
    CmdArgs.push_back(Args.MakeArgString(Twine(N)));
  }

  // -fvisibility= and -fvisibility-ms-compat are of a piece.
  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
                                     options::OPT_fvisibility_ms_compat)) {
    if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back(A->getValue());
    } else {
      assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back("hidden");
      CmdArgs.push_back("-ftype-visibility");
      CmdArgs.push_back("default");
    }
  }

  Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);

  Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);

  // -fhosted is default.
  if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
      KernelOrKext)
    CmdArgs.push_back("-ffreestanding");

  // Forward -f (flag) options which we can pass directly.
  Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
  Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
  Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
  Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
  Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
  // AltiVec language extensions aren't relevant for assembling.
  if (!isa<PreprocessJobAction>(JA) || 
      Output.getType() != types::TY_PP_Asm)
    Args.AddLastArg(CmdArgs, options::OPT_faltivec);
  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
  Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);

  const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
  Sanitize.addArgs(Args, CmdArgs);

  if (!Args.hasFlag(options::OPT_fsanitize_recover,
                    options::OPT_fno_sanitize_recover,
                    true))
    CmdArgs.push_back("-fno-sanitize-recover");

  if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
                   options::OPT_fno_sanitize_undefined_trap_on_error, false))
    CmdArgs.push_back("-fsanitize-undefined-trap-on-error");

  // Report an error for -faltivec on anything other than PowerPC.
  if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
    if (!(getToolChain().getArch() == llvm::Triple::ppc ||
          getToolChain().getArch() == llvm::Triple::ppc64 ||
          getToolChain().getArch() == llvm::Triple::ppc64le))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "ppc/ppc64/ppc64le";

  if (getToolChain().SupportsProfiling())
    Args.AddLastArg(CmdArgs, options::OPT_pg);

  // -flax-vector-conversions is default.
  if (!Args.hasFlag(options::OPT_flax_vector_conversions,
                    options::OPT_fno_lax_vector_conversions))
    CmdArgs.push_back("-fno-lax-vector-conversions");

  if (Args.getLastArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-fapple-kext");

  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);

  if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
    CmdArgs.push_back("-ftrapv-handler");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);

  // -fno-strict-overflow implies -fwrapv if it isn't disabled, but
  // -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
  if (Arg *A = Args.getLastArg(options::OPT_fwrapv,
                               options::OPT_fno_wrapv)) {
    if (A->getOption().matches(options::OPT_fwrapv))
      CmdArgs.push_back("-fwrapv");
  } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
                                      options::OPT_fno_strict_overflow)) {
    if (A->getOption().matches(options::OPT_fno_strict_overflow))
      CmdArgs.push_back("-fwrapv");
  }

  if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
                               options::OPT_fno_reroll_loops))
    if (A->getOption().matches(options::OPT_freroll_loops))
      CmdArgs.push_back("-freroll-loops");

  Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
  Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
                  options::OPT_fno_unroll_loops);

  Args.AddLastArg(CmdArgs, options::OPT_pthread);


  // -stack-protector=0 is default.
  unsigned StackProtectorLevel = 0;
  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                               options::OPT_fstack_protector_all,
                               options::OPT_fstack_protector_strong,
                               options::OPT_fstack_protector)) {
    if (A->getOption().matches(options::OPT_fstack_protector)) {
      StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
        getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
    } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
      StackProtectorLevel = LangOptions::SSPStrong;
    else if (A->getOption().matches(options::OPT_fstack_protector_all))
      StackProtectorLevel = LangOptions::SSPReq;
  } else {
    StackProtectorLevel =
      getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
  }
  if (StackProtectorLevel) {
    CmdArgs.push_back("-stack-protector");
    CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
  }

  // --param ssp-buffer-size=
  for (arg_iterator it = Args.filtered_begin(options::OPT__param),
       ie = Args.filtered_end(); it != ie; ++it) {
    StringRef Str((*it)->getValue());
    if (Str.startswith("ssp-buffer-size=")) {
      if (StackProtectorLevel) {
        CmdArgs.push_back("-stack-protector-buffer-size");
        // FIXME: Verify the argument is a valid integer.
        CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
      }
      (*it)->claim();
    }
  }

  // Translate -mstackrealign
  if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
                   false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-force-align-stack");
  }
  if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
                   false)) {
    CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
  }

  if (Args.hasArg(options::OPT_mstack_alignment)) {
    StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
    CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
  }

  if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
                               options::OPT_mno_restrict_it)) {
    if (A->getOption().matches(options::OPT_mrestrict_it)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-restrict-it");
    } else {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-no-restrict-it");
    }
  } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
                                  TT.getArch() == llvm::Triple::thumb)) {
    // Windows on ARM expects restricted IT blocks
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-restrict-it");
  }

  if (TT.getArch() == llvm::Triple::arm ||
      TT.getArch() == llvm::Triple::thumb) {
    if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
                                 options::OPT_mno_long_calls)) {
      if (A->getOption().matches(options::OPT_mlong_calls)) {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-long-calls");
      }
    }
  }

  // Forward -f options with positive and negative forms; we translate
  // these by hand.
  if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
    StringRef fname = A->getValue();
    if (!llvm::sys::fs::exists(fname))
      D.Diag(diag::err_drv_no_such_file) << fname;
    else
      A->render(Args, CmdArgs);
  }

  if (Args.hasArg(options::OPT_mkernel)) {
    if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
      CmdArgs.push_back("-fapple-kext");
    if (!Args.hasArg(options::OPT_fbuiltin))
      CmdArgs.push_back("-fno-builtin");
    Args.ClaimAllArgs(options::OPT_fno_builtin);
  }
  // -fbuiltin is default.
  else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
    CmdArgs.push_back("-fno-builtin");

  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fblocks=0 is default.
  if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
                   getToolChain().IsBlocksDefault()) ||
        (Args.hasArg(options::OPT_fgnu_runtime) &&
         Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
         !Args.hasArg(options::OPT_fno_blocks))) {
    CmdArgs.push_back("-fblocks");

    if (!Args.hasArg(options::OPT_fgnu_runtime) && 
        !getToolChain().hasBlocksRuntime())
      CmdArgs.push_back("-fblocks-runtime-optional");
  }

  // -fmodules enables modules (off by default). However, for C++/Objective-C++,
  // users must also pass -fcxx-modules. The latter flag will disappear once the
  // modules implementation is solid for C++/Objective-C++ programs as well.
  bool HaveModules = false;
  if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
    bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, 
                                     options::OPT_fno_cxx_modules, 
                                     false);
    if (AllowedInCXX || !types::isCXX(InputType)) {
      CmdArgs.push_back("-fmodules");
      HaveModules = true;
    }
  }

  // -fmodule-maps enables module map processing (off by default) for header
  // checking.  It is implied by -fmodules.
  if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
                   false)) {
    CmdArgs.push_back("-fmodule-maps");
  }

  // -fmodules-decluse checks that modules used are declared so (off by
  // default).
  if (Args.hasFlag(options::OPT_fmodules_decluse,
                   options::OPT_fno_modules_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-decluse");
  }

  // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
  // all #included headers are part of modules.
  if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
                   options::OPT_fno_modules_strict_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-strict-decluse");
  }

  // -fmodule-name specifies the module that is currently being built (or
  // used for header checking by -fmodule-maps).
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_name))
    A->render(Args, CmdArgs);

  // -fmodule-map-file can be used to specify a file containing module
  // definitions.
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file))
    A->render(Args, CmdArgs);

  // -fmodule-cache-path specifies where our module files should be written.
  SmallString<128> ModuleCachePath;
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
    ModuleCachePath = A->getValue();
  if (HaveModules) {
    if (C.isForDiagnostics()) {
      // When generating crash reports, we want to emit the modules along with
      // the reproduction sources, so we ignore any provided module path.
      ModuleCachePath = Output.getFilename();
      llvm::sys::path::replace_extension(ModuleCachePath, ".cache");
      llvm::sys::path::append(ModuleCachePath, "modules");
    } else if (ModuleCachePath.empty()) {
      // No module path was provided: use the default.
      llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
                                             ModuleCachePath);
      llvm::sys::path::append(ModuleCachePath, "org.llvm.clang");
      llvm::sys::path::append(ModuleCachePath, "ModuleCache");
    }
    const char Arg[] = "-fmodules-cache-path=";
    ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg));
    CmdArgs.push_back(Args.MakeArgString(ModuleCachePath));
  }

  // When building modules and generating crashdumps, we need to dump a module
  // dependency VFS alongside the output.
  if (HaveModules && C.isForDiagnostics()) {
    SmallString<128> VFSDir(Output.getFilename());
    llvm::sys::path::replace_extension(VFSDir, ".cache");
    llvm::sys::path::append(VFSDir, "vfs");
    CmdArgs.push_back("-module-dependency-dir");
    CmdArgs.push_back(Args.MakeArgString(VFSDir));
  }

  if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path))
    if (HaveModules)
      A->render(Args, CmdArgs);

  // Pass through all -fmodules-ignore-macro arguments.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);

  Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);

  if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
    if (Args.hasArg(options::OPT_fbuild_session_timestamp))
      D.Diag(diag::err_drv_argument_not_allowed_with)
          << A->getAsString(Args) << "-fbuild-session-timestamp";

    llvm::sys::fs::file_status Status;
    if (llvm::sys::fs::status(A->getValue(), Status))
      D.Diag(diag::err_drv_no_such_file) << A->getValue();
    char TimeStamp[48];
    snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64,
             (uint64_t)Status.getLastModificationTime().toEpochTime());
    CmdArgs.push_back(Args.MakeArgString(TimeStamp));
  }

  if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
    if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
                         options::OPT_fbuild_session_file))
      D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);

    Args.AddLastArg(CmdArgs,
                    options::OPT_fmodules_validate_once_per_build_session);
  }

  Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);

  // -faccess-control is default.
  if (Args.hasFlag(options::OPT_fno_access_control,
                   options::OPT_faccess_control,
                   false))
    CmdArgs.push_back("-fno-access-control");

  // -felide-constructors is the default.
  if (Args.hasFlag(options::OPT_fno_elide_constructors,
                   options::OPT_felide_constructors,
                   false))
    CmdArgs.push_back("-fno-elide-constructors");

  // -frtti is default.
  if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
      KernelOrKext) {
    CmdArgs.push_back("-fno-rtti");

    // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
    if (Sanitize.sanitizesVptr()) {
      std::string NoRttiArg =
        Args.getLastArg(options::OPT_mkernel,
                        options::OPT_fapple_kext,
                        options::OPT_fno_rtti)->getAsString(Args);
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fsanitize=vptr" << NoRttiArg;
    }
  }

  // -fshort-enums=0 is default for all architectures except Hexagon.
  if (Args.hasFlag(options::OPT_fshort_enums,
                   options::OPT_fno_short_enums,
                   getToolChain().getArch() ==
                   llvm::Triple::hexagon))
    CmdArgs.push_back("-fshort-enums");

  // -fsigned-char is default.
  if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
                    isSignedCharDefault(getToolChain().getTriple())))
    CmdArgs.push_back("-fno-signed-char");

  // -fthreadsafe-static is default.
  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
                    options::OPT_fno_threadsafe_statics))
    CmdArgs.push_back("-fno-threadsafe-statics");

  // -fuse-cxa-atexit is default.
  if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
                    options::OPT_fno_use_cxa_atexit,
                    !IsWindowsCygnus && !IsWindowsGNU &&
                    getToolChain().getArch() != llvm::Triple::hexagon &&
                    getToolChain().getArch() != llvm::Triple::xcore) ||
      KernelOrKext)
    CmdArgs.push_back("-fno-use-cxa-atexit");

  // -fms-extensions=0 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   IsWindowsMSVC))
    CmdArgs.push_back("-fms-extensions");

  // -fms-compatibility=0 is default.
  if (Args.hasFlag(options::OPT_fms_compatibility, 
                   options::OPT_fno_ms_compatibility,
                   (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
                                                  options::OPT_fno_ms_extensions,
                                                  true))))
    CmdArgs.push_back("-fms-compatibility");

  // -fms-compatibility-version=17.00 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
      Args.hasArg(options::OPT_fms_compatibility_version)) {
    const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
    const Arg *MSCompatibilityVersion =
      Args.getLastArg(options::OPT_fms_compatibility_version);

    if (MSCVersion && MSCompatibilityVersion)
      D.Diag(diag::err_drv_argument_not_allowed_with)
          << MSCVersion->getAsString(Args)
          << MSCompatibilityVersion->getAsString(Args);

    std::string Ver;
    if (MSCompatibilityVersion)
      Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
    else if (MSCVersion)
      Ver = getMSCompatibilityVersion(MSCVersion->getValue());

    if (Ver.empty())
      CmdArgs.push_back("-fms-compatibility-version=17.00");
    else
      CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
  }

  // -fno-borland-extensions is default.
  if (Args.hasFlag(options::OPT_fborland_extensions,
                   options::OPT_fno_borland_extensions, false))
    CmdArgs.push_back("-fborland-extensions");

  // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
  // needs it.
  if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
                   options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
    CmdArgs.push_back("-fdelayed-template-parsing");

  // -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);

  if (Args.hasFlag(options::OPT_fgnu89_inline,
                   options::OPT_fno_gnu89_inline,
                   false))
    CmdArgs.push_back("-fgnu89-inline");

  if (Args.hasArg(options::OPT_fno_inline))
    CmdArgs.push_back("-fno-inline");

  if (Args.hasArg(options::OPT_fno_inline_functions))
    CmdArgs.push_back("-fno-inline-functions");

  ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);

  // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
  // legacy is the default. Except for deployment taget of 10.5,
  // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
  // gets ignored silently.
  if (objcRuntime.isNonFragile()) {
    if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
                      options::OPT_fno_objc_legacy_dispatch,
                      objcRuntime.isLegacyDispatchDefaultForArch(
                        getToolChain().getArch()))) {
      if (getToolChain().UseObjCMixedDispatch())
        CmdArgs.push_back("-fobjc-dispatch-method=mixed");
      else
        CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
    }
  }

  // When ObjectiveC legacy runtime is in effect on MacOSX,
  // turn on the option to do Array/Dictionary subscripting
  // by default.
  if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
      getToolChain().getTriple().isMacOSX() &&
      !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
      objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
      objcRuntime.isNeXTFamily())
    CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
  
  // -fencode-extended-block-signature=1 is default.
  if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
    CmdArgs.push_back("-fencode-extended-block-signature");
  }
  
  // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
  // NOTE: This logic is duplicated in ToolChains.cpp.
  bool ARC = isObjCAutoRefCount(Args);
  if (ARC) {
    getToolChain().CheckObjCARC();

    CmdArgs.push_back("-fobjc-arc");

    // FIXME: It seems like this entire block, and several around it should be
    // wrapped in isObjC, but for now we just use it here as this is where it
    // was being used previously.
    if (types::isCXX(InputType) && types::isObjC(InputType)) {
      if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
        CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
      else
        CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
    }

    // Allow the user to enable full exceptions code emission.
    // We define off for Objective-CC, on for Objective-C++.
    if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
                     options::OPT_fno_objc_arc_exceptions,
                     /*default*/ types::isCXX(InputType)))
      CmdArgs.push_back("-fobjc-arc-exceptions");
  }

  // -fobjc-infer-related-result-type is the default, except in the Objective-C
  // rewriter.
  if (rewriteKind != RK_None)
    CmdArgs.push_back("-fno-objc-infer-related-result-type");

  // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
  // takes precedence.
  const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
  if (!GCArg)
    GCArg = Args.getLastArg(options::OPT_fobjc_gc);
  if (GCArg) {
    if (ARC) {
      D.Diag(diag::err_drv_objc_gc_arr)
        << GCArg->getAsString(Args);
    } else if (getToolChain().SupportsObjCGC()) {
      GCArg->render(Args, CmdArgs);
    } else {
      // FIXME: We should move this to a hard error.
      D.Diag(diag::warn_drv_objc_gc_unsupported)
        << GCArg->getAsString(Args);
    }
  }

  // Handle GCC-style exception args.
  if (!C.getDriver().IsCLMode())
    addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
                     objcRuntime, CmdArgs);

  if (getToolChain().UseSjLjExceptions())
    CmdArgs.push_back("-fsjlj-exceptions");

  // C++ "sane" operator new.
  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fconstant-cfstrings is default, and may be subject to argument translation
  // on Darwin.
  if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
                    options::OPT_fno_constant_cfstrings) ||
      !Args.hasFlag(options::OPT_mconstant_cfstrings,
                    options::OPT_mno_constant_cfstrings))
    CmdArgs.push_back("-fno-constant-cfstrings");

  // -fshort-wchar default varies depending on platform; only
  // pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
                               options::OPT_fno_short_wchar))
    A->render(Args, CmdArgs);

  // -fno-pascal-strings is default, only pass non-default.
  if (Args.hasFlag(options::OPT_fpascal_strings,
                   options::OPT_fno_pascal_strings,
                   false))
    CmdArgs.push_back("-fpascal-strings");

  // Honor -fpack-struct= and -fpack-struct, if given. Note that
  // -fno-pack-struct doesn't apply to -fpack-struct=.
  if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
    std::string PackStructStr = "-fpack-struct=";
    PackStructStr += A->getValue();
    CmdArgs.push_back(Args.MakeArgString(PackStructStr));
  } else if (Args.hasFlag(options::OPT_fpack_struct,
                          options::OPT_fno_pack_struct, false)) {
    CmdArgs.push_back("-fpack-struct=1");
  }

  // Handle -fmax-type-align=N and -fno-type-align
  bool SkipMaxTypeAlign = Args.hasArg(options::OPT_fno_max_type_align);
  if (Arg *A = Args.getLastArg(options::OPT_fmax_type_align_EQ)) {
    if (!SkipMaxTypeAlign) {
      std::string MaxTypeAlignStr = "-fmax-type-align=";
      MaxTypeAlignStr += A->getValue();
      CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
    }
  } else if (getToolChain().getTriple().isOSDarwin()) {
    if (!SkipMaxTypeAlign) {
      std::string MaxTypeAlignStr = "-fmax-type-align=16";
      CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
    }
  }

  if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
    if (!Args.hasArg(options::OPT_fcommon))
      CmdArgs.push_back("-fno-common");
    Args.ClaimAllArgs(options::OPT_fno_common);
  }

  // -fcommon is default, only pass non-default.
  else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
    CmdArgs.push_back("-fno-common");

  // -fsigned-bitfields is default, and clang doesn't yet support
  // -funsigned-bitfields.
  if (!Args.hasFlag(options::OPT_fsigned_bitfields,
                    options::OPT_funsigned_bitfields))
    D.Diag(diag::warn_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);

  // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
  if (!Args.hasFlag(options::OPT_ffor_scope,
                    options::OPT_fno_for_scope))
    D.Diag(diag::err_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);

  // -finput_charset=UTF-8 is default. Reject others
  if (Arg *inputCharset = Args.getLastArg(
          options::OPT_finput_charset_EQ)) {
      StringRef value = inputCharset->getValue();
      if (value != "UTF-8")
          D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value;
  }

  // -fcaret-diagnostics is default.
  if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
                    options::OPT_fno_caret_diagnostics, true))
    CmdArgs.push_back("-fno-caret-diagnostics");

  // -fdiagnostics-fixit-info is default, only pass non-default.
  if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
                    options::OPT_fno_diagnostics_fixit_info))
    CmdArgs.push_back("-fno-diagnostics-fixit-info");

  // Enable -fdiagnostics-show-option by default.
  if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
                   options::OPT_fno_diagnostics_show_option))
    CmdArgs.push_back("-fdiagnostics-show-option");

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
    CmdArgs.push_back("-fdiagnostics-show-category");
    CmdArgs.push_back(A->getValue());
  }

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(
      options::OPT_fdiagnostics_show_note_include_stack,
      options::OPT_fno_diagnostics_show_note_include_stack)) {
    if (A->getOption().matches(
        options::OPT_fdiagnostics_show_note_include_stack))
      CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
    else
      CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
  }

  // Color diagnostics are the default, unless the terminal doesn't support
  // them.
  // Support both clang's -f[no-]color-diagnostics and gcc's
  // -f[no-]diagnostics-colors[=never|always|auto].
  enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
  for (const auto &Arg : Args) {
    const Option &O = Arg->getOption();
    if (!O.matches(options::OPT_fcolor_diagnostics) &&
        !O.matches(options::OPT_fdiagnostics_color) &&
        !O.matches(options::OPT_fno_color_diagnostics) &&
        !O.matches(options::OPT_fno_diagnostics_color) &&
        !O.matches(options::OPT_fdiagnostics_color_EQ))
      continue;

    Arg->claim();
    if (O.matches(options::OPT_fcolor_diagnostics) ||
        O.matches(options::OPT_fdiagnostics_color)) {
      ShowColors = Colors_On;
    } else if (O.matches(options::OPT_fno_color_diagnostics) ||
               O.matches(options::OPT_fno_diagnostics_color)) {
      ShowColors = Colors_Off;
    } else {
      assert(O.matches(options::OPT_fdiagnostics_color_EQ));
      StringRef value(Arg->getValue());
      if (value == "always")
        ShowColors = Colors_On;
      else if (value == "never")
        ShowColors = Colors_Off;
      else if (value == "auto")
        ShowColors = Colors_Auto;
      else
        getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
          << ("-fdiagnostics-color=" + value).str();
    }
  }
  if (ShowColors == Colors_On ||
      (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
    CmdArgs.push_back("-fcolor-diagnostics");

  if (Args.hasArg(options::OPT_fansi_escape_codes))
    CmdArgs.push_back("-fansi-escape-codes");

  if (!Args.hasFlag(options::OPT_fshow_source_location,
                    options::OPT_fno_show_source_location))
    CmdArgs.push_back("-fno-show-source-location");

  if (!Args.hasFlag(options::OPT_fshow_column,
                    options::OPT_fno_show_column,
                    true))
    CmdArgs.push_back("-fno-show-column");

  if (!Args.hasFlag(options::OPT_fspell_checking,
                    options::OPT_fno_spell_checking))
    CmdArgs.push_back("-fno-spell-checking");


  // -fno-asm-blocks is default.
  if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
                   false))
    CmdArgs.push_back("-fasm-blocks");

  // Enable vectorization per default according to the optimization level
  // selected. For optimization levels that want vectorization we use the alias
  // option to simplify the hasFlag logic.
  bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
  OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
    options::OPT_fvectorize;
  if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
                   options::OPT_fno_vectorize, EnableVec))
    CmdArgs.push_back("-vectorize-loops");

  // -fslp-vectorize is enabled based on the optimization level selected.
  bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
  OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
    options::OPT_fslp_vectorize;
  if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
                   options::OPT_fno_slp_vectorize, EnableSLPVec))
    CmdArgs.push_back("-vectorize-slp");

  // -fno-slp-vectorize-aggressive is default.
  if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
                   options::OPT_fno_slp_vectorize_aggressive, false))
    CmdArgs.push_back("-vectorize-slp-aggressive");

  if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
    A->render(Args, CmdArgs);

  // -fdollars-in-identifiers default varies depending on platform and
  // language; only pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
                               options::OPT_fno_dollars_in_identifiers)) {
    if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
      CmdArgs.push_back("-fdollars-in-identifiers");
    else
      CmdArgs.push_back("-fno-dollars-in-identifiers");
  }

  // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
  // practical purposes.
  if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
                               options::OPT_fno_unit_at_a_time)) {
    if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
      D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
  }

  if (Args.hasFlag(options::OPT_fapple_pragma_pack,
                   options::OPT_fno_apple_pragma_pack, false))
    CmdArgs.push_back("-fapple-pragma-pack");

  // le32-specific flags: 
  //  -fno-math-builtin: clang should not convert math builtins to intrinsics
  //                     by default.
  if (getToolChain().getArch() == llvm::Triple::le32) {
    CmdArgs.push_back("-fno-math-builtin");
  }

  // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
  //
  // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
  if (getToolChain().getTriple().isOSDarwin() &&
      (getToolChain().getArch() == llvm::Triple::arm ||
       getToolChain().getArch() == llvm::Triple::thumb)) {
    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
      CmdArgs.push_back("-fno-builtin-strcat");
    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
      CmdArgs.push_back("-fno-builtin-strcpy");
  }
#endif

  // Enable rewrite includes if the user's asked for it or if we're generating
  // diagnostics.
  // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
  // nice to enable this when doing a crashdump for modules as well.
  if (Args.hasFlag(options::OPT_frewrite_includes,
                   options::OPT_fno_rewrite_includes, false) ||
      (C.isForDiagnostics() && !HaveModules))
    CmdArgs.push_back("-frewrite-includes");

  // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
  if (Arg *A = Args.getLastArg(options::OPT_traditional,
                               options::OPT_traditional_cpp)) {
    if (isa<PreprocessJobAction>(JA))
      CmdArgs.push_back("-traditional-cpp");
    else
      D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
  }

  Args.AddLastArg(CmdArgs, options::OPT_dM);
  Args.AddLastArg(CmdArgs, options::OPT_dD);
  
  // Handle serialized diagnostics.
  if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
    CmdArgs.push_back("-serialize-diagnostic-file");
    CmdArgs.push_back(Args.MakeArgString(A->getValue()));
  }

  if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
    CmdArgs.push_back("-fretain-comments-from-system-headers");

  // Forward -fcomment-block-commands to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
  // Forward -fparse-all-comments to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);

  // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
  // parser.
  Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
  for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();

    // We translate this by hand to the -cc1 argument, since nightly test uses
    // it and developers have been trained to spell it with -mllvm.
    if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns")
      CmdArgs.push_back("-disable-llvm-optzns");
    else
      (*it)->render(Args, CmdArgs);
  }

  if (Output.getType() == types::TY_Dependencies) {
    // Handled with other dependency code.
  } else if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  for (const auto &II : Inputs) {
    addDashXForInput(Args, II, CmdArgs);

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      II.getInputArg().renderAsInput(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_undef);

  const char *Exec = getToolChain().getDriver().getClangProgramPath();

  // Optionally embed the -cc1 level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (const auto &Arg : Args)
      Arg->render(Args, OriginalArgs);

    SmallString<256> Flags;
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // Add the split debug info name to the command lines here so we
  // can propagate it to the backend.
  bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
    getToolChain().getTriple().isOSLinux() &&
    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
  const char *SplitDwarfOut;
  if (SplitDwarf) {
    CmdArgs.push_back("-split-dwarf-file");
    SplitDwarfOut = SplitDebugName(Args, Inputs);
    CmdArgs.push_back(SplitDwarfOut);
  }

  // Finally add the compile command to the compilation.
  if (Args.hasArg(options::OPT__SLASH_fallback) &&
      Output.getType() == types::TY_Object &&
      (InputType == types::TY_C || InputType == types::TY_CXX)) {
    Command *CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs,
                                                     Args, LinkingOutput);
    C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
  } else {
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
  }


  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (SplitDwarf && !isa<CompileJobAction>(JA))
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);

  if (Arg *A = Args.getLastArg(options::OPT_pg))
    if (Args.hasArg(options::OPT_fomit_frame_pointer))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fomit-frame-pointer" << A->getAsString(Args);

  // Claim some arguments which clang supports automatically.

  // -fpch-preprocess is used with gcc to add a special marker in the output to
  // include the PCH file. Clang's PTH solution is completely transparent, so we
  // do not need to deal with it at all.
  Args.ClaimAllArgs(options::OPT_fpch_preprocess);

  // Claim some arguments which clang doesn't support, but we don't
  // care to warn the user about.
  Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
  Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);

  // Disable warnings for clang -E -emit-llvm foo.c
  Args.ClaimAllArgs(options::OPT_emit_llvm);
}

/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
                                      ArgStringList &cmdArgs,
                                      RewriteKind rewriteKind) const {
  // Look for the controlling runtime option.
  Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
                                    options::OPT_fgnu_runtime,
                                    options::OPT_fobjc_runtime_EQ);

  // Just forward -fobjc-runtime= to the frontend.  This supercedes
  // options about fragility.
  if (runtimeArg &&
      runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
    ObjCRuntime runtime;
    StringRef value = runtimeArg->getValue();
    if (runtime.tryParse(value)) {
      getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
        << value;
    }

    runtimeArg->render(args, cmdArgs);
    return runtime;
  }

  // Otherwise, we'll need the ABI "version".  Version numbers are
  // slightly confusing for historical reasons:
  //   1 - Traditional "fragile" ABI
  //   2 - Non-fragile ABI, version 1
  //   3 - Non-fragile ABI, version 2
  unsigned objcABIVersion = 1;
  // If -fobjc-abi-version= is present, use that to set the version.
  if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
    StringRef value = abiArg->getValue();
    if (value == "1")
      objcABIVersion = 1;
    else if (value == "2")
      objcABIVersion = 2;
    else if (value == "3")
      objcABIVersion = 3;
    else
      getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
        << value;
  } else {
    // Otherwise, determine if we are using the non-fragile ABI.
    bool nonFragileABIIsDefault = 
      (rewriteKind == RK_NonFragile || 
       (rewriteKind == RK_None &&
        getToolChain().IsObjCNonFragileABIDefault()));
    if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
                     options::OPT_fno_objc_nonfragile_abi,
                     nonFragileABIIsDefault)) {
      // Determine the non-fragile ABI version to use.
#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
      unsigned nonFragileABIVersion = 1;
#else
      unsigned nonFragileABIVersion = 2;
#endif

      if (Arg *abiArg = args.getLastArg(
            options::OPT_fobjc_nonfragile_abi_version_EQ)) {
        StringRef value = abiArg->getValue();
        if (value == "1")
          nonFragileABIVersion = 1;
        else if (value == "2")
          nonFragileABIVersion = 2;
        else
          getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
            << value;
      }

      objcABIVersion = 1 + nonFragileABIVersion;
    } else {
      objcABIVersion = 1;
    }
  }

  // We don't actually care about the ABI version other than whether
  // it's non-fragile.
  bool isNonFragile = objcABIVersion != 1;

  // If we have no runtime argument, ask the toolchain for its default runtime.
  // However, the rewriter only really supports the Mac runtime, so assume that.
  ObjCRuntime runtime;
  if (!runtimeArg) {
    switch (rewriteKind) {
    case RK_None:
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
      break;
    case RK_Fragile:
      runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
      break;
    case RK_NonFragile:
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
      break;
    }

  // -fnext-runtime
  } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
    // On Darwin, make this use the default behavior for the toolchain.
    if (getToolChain().getTriple().isOSDarwin()) {
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);

    // Otherwise, build for a generic macosx port.
    } else {
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
    }

  // -fgnu-runtime
  } else {
    assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
    // Legacy behaviour is to target the gnustep runtime if we are i
    // non-fragile mode or the GCC runtime in fragile mode.
    if (isNonFragile)
      runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6));
    else
      runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
  }

  cmdArgs.push_back(args.MakeArgString(
                                 "-fobjc-runtime=" + runtime.getAsString()));
  return runtime;
}

static bool maybeConsumeDash(const std::string &EH, size_t &I) {
  bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
  I += HaveDash;
  return !HaveDash;
}

struct EHFlags {
  EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
  bool Synch;
  bool Asynch;
  bool NoExceptC;
};

/// /EH controls whether to run destructor cleanups when exceptions are
/// thrown.  There are three modifiers:
/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions.
/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions.
///      The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
/// - c: Assume that extern "C" functions are implicitly noexcept.  This
///      modifier is an optimization, so we ignore it for now.
/// The default is /EHs-c-, meaning cleanups are disabled.
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
  EHFlags EH;
  std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
  for (auto EHVal : EHArgs) {
    for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
      switch (EHVal[I]) {
      case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
      case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
      case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
      default: break;
      }
      D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
      break;
    }
  }
  return EH;
}

void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
  unsigned RTOptionID = options::OPT__SLASH_MT;

  if (Args.hasArg(options::OPT__SLASH_LDd))
    // The /LDd option implies /MTd. The dependent lib part can be overridden,
    // but defining _DEBUG is sticky.
    RTOptionID = options::OPT__SLASH_MTd;

  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
    RTOptionID = A->getOption().getID();

  switch(RTOptionID) {
    case options::OPT__SLASH_MD:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrt");
      break;
    case options::OPT__SLASH_MDd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrtd");
      break;
    case options::OPT__SLASH_MT:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmt");
      break;
    case options::OPT__SLASH_MTd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmtd");
      break;
    default:
      llvm_unreachable("Unexpected option ID.");
  }

  // This provides POSIX compatibility (maps 'open' to '_open'), which most
  // users want.  The /Za flag to cl.exe turns this off, but it's not
  // implemented in clang.
  CmdArgs.push_back("--dependent-lib=oldnames");

  // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
  // would produce interleaved output, so ignore /showIncludes in such cases.
  if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP))
    if (Arg *A = Args.getLastArg(options::OPT_show_includes))
      A->render(Args, CmdArgs);

  // This controls whether or not we emit RTTI data for polymorphic types.
  if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
                   /*default=*/false))
    CmdArgs.push_back("-fno-rtti-data");

  const Driver &D = getToolChain().getDriver();
  EHFlags EH = parseClangCLEHFlags(D, Args);
  // FIXME: Do something with NoExceptC.
  if (EH.Synch || EH.Asynch) {
    CmdArgs.push_back("-fexceptions");
    CmdArgs.push_back("-fcxx-exceptions");
  }

  // /EP should expand to -E -P.
  if (Args.hasArg(options::OPT__SLASH_EP)) {
    CmdArgs.push_back("-E");
    CmdArgs.push_back("-P");
  }

  Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
  Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
  if (MostGeneralArg && BestCaseArg)
    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
        << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);

  if (MostGeneralArg) {
    Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
    Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
    Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);

    Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
    Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
    if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << FirstConflict->getAsString(Args)
          << SecondConflict->getAsString(Args);

    if (SingleArg)
      CmdArgs.push_back("-fms-memptr-rep=single");
    else if (MultipleArg)
      CmdArgs.push_back("-fms-memptr-rep=multiple");
    else
      CmdArgs.push_back("-fms-memptr-rep=virtual");
  }

  if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
    A->render(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    if (Args.hasArg(options::OPT__SLASH_fallback))
      CmdArgs.push_back("msvc-fallback");
    else
      CmdArgs.push_back("msvc");
  }
}

visualstudio::Compile *Clang::getCLFallback() const {
  if (!CLFallback)
    CLFallback.reset(new visualstudio::Compile(getToolChain()));
  return CLFallback.get();
}

void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
                           const InputInfo &Output,
                           const InputInfoList &Inputs,
                           const ArgList &Args,
                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Don't warn about "clang -w -c foo.s"
  Args.ClaimAllArgs(options::OPT_w);
  // and "clang -emit-llvm -c foo.s"
  Args.ClaimAllArgs(options::OPT_emit_llvm);

  // Invoke ourselves in -cc1as mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1as");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = 
    getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  // Set the output mode, we currently only expect to be used as a real
  // assembler.
  CmdArgs.push_back("-filetype");
  CmdArgs.push_back("obj");

  // Set the main file name, so that debug info works even with
  // -save-temps or preprocessed assembly.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));

  // Add the target cpu
  const llvm::Triple &Triple = getToolChain().getTriple();
  std::string CPU = getCPUName(Args, Triple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  // Add the target features
  const Driver &D = getToolChain().getDriver();
  getTargetFeatures(D, Triple, Args, CmdArgs, true);

  // Ignore explicit -force_cpusubtype_ALL option.
  (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // Forward -g and handle debug info related flags, assuming we are dealing
  // with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    Args.ClaimAllArgs(options::OPT_g_Group);
    if (Arg *A = Args.getLastArg(options::OPT_g_Group))
      if (!A->getOption().matches(options::OPT_g0))
        CmdArgs.push_back("-g");

    if (Args.hasArg(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    if (Args.hasArg(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    if (Args.hasArg(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");

    // Add the -fdebug-compilation-dir flag if needed.
    addDebugCompDirArg(Args, CmdArgs);

    // Set the AT_producer to the clang version when using the integrated
    // assembler on assembly source files.
    CmdArgs.push_back("-dwarf-debug-producer");
    CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
  }

  // Optionally embed the -cc1as level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (const auto &Arg : Args)
      Arg->render(Args, OriginalArgs);

    SmallString<256> Flags;
    const char *Exec = getToolChain().getDriver().getClangProgramPath();
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // FIXME: Add -static support, once we have it.

  // Consume all the warning flags. Usually this would be handled more
  // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
  // doesn't handle that so rather than warning about unused flags that are
  // actually used, we'll lie by omission instead.
  // FIXME: Stop lying and consume only the appropriate driver flags
  for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
                    ie = Args.filtered_end();
       it != ie; ++it)
    (*it)->claim();

  CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
                                    getToolChain().getDriver());

  Args.AddAllArgs(CmdArgs, options::OPT_mllvm);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec = getToolChain().getDriver().getClangProgramPath();
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

void gcc::Common::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;

  for (const auto &A : Args) {
    if (forwardToGCC(A->getOption())) {
      // Don't forward any -g arguments to assembly steps.
      if (isa<AssembleJobAction>(JA) &&
          A->getOption().matches(options::OPT_g_Group))
        continue;

      // Don't forward any -W arguments to assembly and link steps.
      if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
          A->getOption().matches(options::OPT_W_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
      // to get to the assembler.
      A->claim();
      A->render(Args, CmdArgs);
    }
  }

  RenderExtraToolArgs(JA, CmdArgs);

  // If using a driver driver, force the arch.
  llvm::Triple::ArchType Arch = getToolChain().getArch();
  if (getToolChain().getTriple().isOSDarwin()) {
    CmdArgs.push_back("-arch");

    // FIXME: Remove these special cases.
    if (Arch == llvm::Triple::ppc)
      CmdArgs.push_back("ppc");
    else if (Arch == llvm::Triple::ppc64)
      CmdArgs.push_back("ppc64");
    else if (Arch == llvm::Triple::ppc64le)
      CmdArgs.push_back("ppc64le");
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
  }

  // Try to force gcc to match the tool chain we want, if we recognize
  // the arch.
  //
  // FIXME: The triple class should directly provide the information we want
  // here.
  if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
    CmdArgs.push_back("-m32");
  else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
           Arch == llvm::Triple::ppc64le)
    CmdArgs.push_back("-m64");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (const auto &II : Inputs) {
    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
        << getToolChain().getTripleString();

    if (types::canTypeBeUserSpecified(II.getType())) {
      CmdArgs.push_back("-x");
      CmdArgs.push_back(types::getTypeName(II.getType()));
    }

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else {
      const Arg &A = II.getInputArg();

      // Reverse translate some rewritten options.
      if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
        CmdArgs.push_back("-lstdc++");
        continue;
      }

      // Don't render as input, we need gcc to do the translations.
      A.render(Args, CmdArgs);
    }
  }

  const std::string customGCCName = D.getCCCGenericGCCName();
  const char *GCCName;
  if (!customGCCName.empty())
    GCCName = customGCCName.c_str();
  else if (D.CCCIsCXX()) {
    GCCName = "g++";
  } else
    GCCName = "gcc";

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
                                          ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-E");
}

void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
                                       ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // If -flto, etc. are present then make sure not to force assembly output.
  if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
      JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
    CmdArgs.push_back("-c");
  else {
    if (JA.getType() != types::TY_PP_Asm)
      D.Diag(diag::err_drv_invalid_gcc_output_type)
        << getTypeName(JA.getType());

    CmdArgs.push_back("-S");
  }
}

void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

// Hexagon tools start.
void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA,
                                        ArgStringList &CmdArgs) const {

}
void hexagon::Assemble::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;

  std::string MarchString = "-march=";
  MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString(MarchString));

  RenderExtraToolArgs(JA, CmdArgs);

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty())
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (const auto &II : Inputs) {
    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(clang::diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
      << getToolChain().getTripleString();

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ?
      II.getInputArg().render(Args, CmdArgs);
  }

  const char *GCCName = "hexagon-as";
  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &Args,
                               const char *LinkingOutput) const {

  const toolchains::Hexagon_TC& ToolChain =
    static_cast<const toolchains::Hexagon_TC&>(getToolChain());
  const Driver &D = ToolChain.getDriver();

  ArgStringList CmdArgs;

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  bool hasStaticArg = Args.hasArg(options::OPT_static);
  bool buildingLib = Args.hasArg(options::OPT_shared);
  bool buildPIE = Args.hasArg(options::OPT_pie);
  bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
  bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
  bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
  bool useShared = buildingLib && !hasStaticArg;

  //----------------------------------------------------------------------------
  // Silence warnings for various options
  //----------------------------------------------------------------------------

  Args.ClaimAllArgs(options::OPT_g_Group);
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
                                     // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_static_libgcc);

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  for (const auto &Opt : ToolChain.ExtraOpts)
    CmdArgs.push_back(Opt.c_str());

  std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));

  if (buildingLib) {
    CmdArgs.push_back("-shared");
    CmdArgs.push_back("-call_shared"); // should be the default, but doing as
                                       // hexagon-gcc does
  }

  if (hasStaticArg)
    CmdArgs.push_back("-static");

  if (buildPIE && !buildingLib)
    CmdArgs.push_back("-pie");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));
  }

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  const std::string MarchSuffix = "/" + MarchString;
  const std::string G0Suffix = "/G0";
  const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
  const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir)
                              + "/";
  const std::string StartFilesDir = RootDir
                                    + "hexagon/lib"
                                    + (buildingLib
                                       ? MarchG0Suffix : MarchSuffix);

  //----------------------------------------------------------------------------
  // moslib
  //----------------------------------------------------------------------------
  std::vector<std::string> oslibs;
  bool hasStandalone= false;

  for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();
    oslibs.push_back((*it)->getValue());
    hasStandalone = hasStandalone || (oslibs.back() == "standalone");
  }
  if (oslibs.empty()) {
    oslibs.push_back("standalone");
    hasStandalone = true;
  }

  //----------------------------------------------------------------------------
  // Start Files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {

    if (!buildingLib) {
      if (hasStandalone) {
        CmdArgs.push_back(
          Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
      }
      CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
    }
    std::string initObj = useShared ? "/initS.o" : "/init.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj));
  }

  //----------------------------------------------------------------------------
  // Library Search Paths
  //----------------------------------------------------------------------------
  const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
  for (const auto &LibPath : LibPaths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  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_u_Group);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  //----------------------------------------------------------------------------
  // Libraries
  //----------------------------------------------------------------------------
  if (incStdLib && incDefLibs) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    CmdArgs.push_back("--start-group");

    if (!buildingLib) {
      for(std::vector<std::string>::iterator i = oslibs.begin(),
            e = oslibs.end(); i != e; ++i)
        CmdArgs.push_back(Args.MakeArgString("-l" + *i));
      CmdArgs.push_back("-lc");
    }
    CmdArgs.push_back("-lgcc");

    CmdArgs.push_back("--end-group");
  }

  //----------------------------------------------------------------------------
  // End files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {
    std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
  }

  std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
  C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
}
// Hexagon tools end.

/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
const char *arm::getARMCPUForMArch(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  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();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  // Handle -march=native.
  if (MArch == "native") {
    std::string CPU = llvm::sys::getHostCPUName();
    if (CPU != "generic") {
      // Translate the native cpu into the architecture. The switch below will
      // then chose the minimum cpu for that arch.
      MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
    }
  }

  return Triple.getARMCPUForArch(MArch);
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
StringRef arm::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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  return getARMCPUForMArch(Args, Triple);
}

/// 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!
const char *arm::getLLVMArchSuffixForARM(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Case("strongarm", "v4")
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7")
    .Cases("cortex-r4", "cortex-r5", "v7r")
    .Case("cortex-m0", "v6m")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7em")
    .Case("swift", "v7s")
    .Case("cyclone", "v8")
    .Cases("cortex-a53", "cortex-a57", "v8")
    .Default("");
}

bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
  if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
    return llvm::StringSwitch<bool>(NaNArg->getValue())
               .Case("2008", true)
               .Case("legacy", false)
               .Default(false);

  // NaN2008 is the default for MIPS32r6/MIPS64r6.
  return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
             .Cases("mips32r6", "mips64r6", true)
             .Default(false);

  return false;
}

bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
                         StringRef ABIName) {
  if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
      Triple.getVendor() != llvm::Triple::MipsTechnologies)
    return false;

  if (ABIName != "32")
    return false;

  return llvm::StringSwitch<bool>(CPUName)
             .Cases("mips2", "mips3", "mips4", "mips5", true)
             .Cases("mips32", "mips32r2", true)
             .Cases("mips64", "mips64r2", true)
             .Default(false);
}

llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
    .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
    .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
    .Case("ppc64", llvm::Triple::ppc64)
    .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
    .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
           llvm::Triple::x86)
    .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
    // This is derived from the driver driver.
    .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
    .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
    .Cases("armv7s", "xscale", llvm::Triple::arm)
    .Case("arm64", llvm::Triple::aarch64)
    .Case("r600", llvm::Triple::r600)
    .Case("nvptx", llvm::Triple::nvptx)
    .Case("nvptx64", llvm::Triple::nvptx64)
    .Case("amdil", llvm::Triple::amdil)
    .Case("spir", llvm::Triple::spir)
    .Default(llvm::Triple::UnknownArch);
}

void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
  llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
  T.setArch(Arch);

  if (Str == "x86_64h")
    T.setArchName(Str);
  else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
    T.setOS(llvm::Triple::UnknownOS);
    T.setObjectFormat(llvm::Triple::MachO);
  }
}

const char *Clang::getBaseInputName(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  return Args.MakeArgString(
    llvm::sys::path::filename(Inputs[0].getBaseInput()));
}

const char *Clang::getBaseInputStem(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  const char *Str = getBaseInputName(Args, Inputs);

  if (const char *End = strrchr(Str, '.'))
    return Args.MakeArgString(std::string(Str, End));

  return Str;
}

const char *Clang::getDependencyFileName(const ArgList &Args,
                                         const InputInfoList &Inputs) {
  // FIXME: Think about this more.
  std::string Res;

  if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
    std::string Str(OutputOpt->getValue());
    Res = Str.substr(0, Str.rfind('.'));
  } else {
    Res = getBaseInputStem(Args, Inputs);
  }
  return Args.MakeArgString(Res + ".d");
}

void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // If -fno_integrated_as is used add -Q to the darwin assember driver to make
  // sure it runs its system assembler not clang's integrated assembler.
  // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
  // FIXME: at run-time detect assembler capabilities or rely on version
  // information forwarded by -target-assembler-version (future)
  if (Args.hasArg(options::OPT_fno_integrated_as)) {
    const llvm::Triple &T(getToolChain().getTriple());
    if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
      CmdArgs.push_back("-Q");
  }

  // Forward -g, assuming we are dealing with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    if (Args.hasArg(options::OPT_gstabs))
      CmdArgs.push_back("--gstabs");
    else if (Args.hasArg(options::OPT_g_Group))
      CmdArgs.push_back("-g");
  }

  // Derived from asm spec.
  AddMachOArch(Args, CmdArgs);

  // Use -force_cpusubtype_ALL on x86 by default.
  if (getToolChain().getArch() == llvm::Triple::x86 ||
      getToolChain().getArch() == llvm::Triple::x86_64 ||
      Args.hasArg(options::OPT_force__cpusubtype__ALL))
    CmdArgs.push_back("-force_cpusubtype_ALL");

  if (getToolChain().getArch() != llvm::Triple::x86_64 &&
      (((Args.hasArg(options::OPT_mkernel) ||
         Args.hasArg(options::OPT_fapple_kext)) &&
        getMachOToolChain().isKernelStatic()) ||
       Args.hasArg(options::OPT_static)))
    CmdArgs.push_back("-static");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  // asm_final spec is empty.

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::MachOTool::anchor() {}

void darwin::MachOTool::AddMachOArch(const ArgList &Args,
                                     ArgStringList &CmdArgs) const {
  StringRef ArchName = getMachOToolChain().getMachOArchName(Args);

  // Derived from darwin_arch spec.
  CmdArgs.push_back("-arch");
  CmdArgs.push_back(Args.MakeArgString(ArchName));

  // FIXME: Is this needed anymore?
  if (ArchName == "arm")
    CmdArgs.push_back("-force_cpusubtype_ALL");
}

bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
  // We only need to generate a temp path for LTO if we aren't compiling object
  // files. When compiling source files, we run 'dsymutil' after linking. We
  // don't run 'dsymutil' when compiling object files.
  for (const auto &Input : Inputs)
    if (Input.getType() != types::TY_Object)
      return true;

  return false;
}

void darwin::Link::AddLinkArgs(Compilation &C,
                               const ArgList &Args,
                               ArgStringList &CmdArgs,
                               const InputInfoList &Inputs) const {
  const Driver &D = getToolChain().getDriver();
  const toolchains::MachO &MachOTC = getMachOToolChain();

  unsigned Version[3] = { 0, 0, 0 };
  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
    bool HadExtra;
    if (!Driver::GetReleaseVersion(A->getValue(), Version[0],
                                   Version[1], Version[2], HadExtra) ||
        HadExtra)
      D.Diag(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");

  if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
    CmdArgs.push_back("-export_dynamic");

  // If we are using LTO, then automatically create a temporary file path for
  // the linker to use, so that it's lifetime will extend past a possible
  // dsymutil step.
  if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
    const char *TmpPath = C.getArgs().MakeArgString(
      D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
    C.addTempFile(TmpPath);
    CmdArgs.push_back("-object_path_lto");
    CmdArgs.push_back(TmpPath);
  }

  // Derived from the "link" spec.
  Args.AddAllArgs(CmdArgs, options::OPT_static);
  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-dynamic");
  if (Args.hasArg(options::OPT_fgnu_runtime)) {
    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
    // here. How do we wish to handle such things?
  }

  if (!Args.hasArg(options::OPT_dynamiclib)) {
    AddMachOArch(Args, CmdArgs);
    // FIXME: Why do this only on this path?
    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);

    Args.AddLastArg(CmdArgs, options::OPT_bundle);
    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
    Args.AddAllArgs(CmdArgs, options::OPT_client__name);

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
        (A = Args.getLastArg(options::OPT_current__version)) ||
        (A = Args.getLastArg(options::OPT_install__name)))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
  } else {
    CmdArgs.push_back("-dylib");

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_bundle)) ||
        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
        (A = Args.getLastArg(options::OPT_client__name)) ||
        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
        (A = Args.getLastArg(options::OPT_private__bundle)))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
                              "-dylib_compatibility_version");
    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
                              "-dylib_current_version");

    AddMachOArch(Args, CmdArgs);

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
                              "-dylib_install_name");
  }

  Args.AddLastArg(CmdArgs, options::OPT_all__load);
  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
  if (MachOTC.isTargetIOSBased())
    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
  Args.AddAllArgs(CmdArgs, options::OPT_force__load);
  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
  Args.AddAllArgs(CmdArgs, options::OPT_init);

  // Add the deployment target.
  MachOTC.addMinVersionArgs(Args, CmdArgs);

  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
  Args.AddLastArg(CmdArgs, options::OPT_single__module);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);

  if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
                                     options::OPT_fno_pie,
                                     options::OPT_fno_PIE)) {
    if (A->getOption().matches(options::OPT_fpie) ||
        A->getOption().matches(options::OPT_fPIE))
      CmdArgs.push_back("-pie");
    else
      CmdArgs.push_back("-no_pie");
  }

  Args.AddLastArg(CmdArgs, options::OPT_prebind);
  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);

  // Give --sysroot= preference, over the Apple specific behavior to also use
  // --isysroot as the syslibroot.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
  } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_y);
  Args.AddLastArg(CmdArgs, options::OPT_w);
  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
  Args.AddLastArg(CmdArgs, options::OPT_whyload);
  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
  Args.AddLastArg(CmdArgs, options::OPT_Mach);
}

enum LibOpenMP {
  LibUnknown,
  LibGOMP,
  LibIOMP5
};

void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");

  // The logic here is derived from gcc's behavior; most of which
  // comes from specs (starting with link_command). Consult gcc for
  // more information.
  ArgStringList CmdArgs;

  /// Hack(tm) to ignore linking errors when we are doing ARC migration.
  if (Args.hasArg(options::OPT_ccc_arcmt_check,
                  options::OPT_ccc_arcmt_migrate)) {
    for (const auto &Arg : Args)
      Arg->claim();
    const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("touch"));
    CmdArgs.push_back(Output.getFilename());
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
    return;
  }

  // I'm not sure why this particular decomposition exists in gcc, but
  // we follow suite for ease of comparison.
  AddLinkArgs(C, Args, CmdArgs, Inputs);

  Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_s);
  Args.AddAllArgs(CmdArgs, options::OPT_t);
  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
  Args.AddLastArg(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
  // members of static archive libraries which implement Objective-C classes or
  // categories.
  if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
    CmdArgs.push_back("-ObjC");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles))
    getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  LibOpenMP UsedOpenMPLib = LibUnknown;
  if (Args.hasArg(options::OPT_fopenmp)) {
    UsedOpenMPLib = LibGOMP;
  } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
    UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
        .Case("libgomp",  LibGOMP)
        .Case("libiomp5", LibIOMP5)
        .Default(LibUnknown);
    if (UsedOpenMPLib == LibUnknown)
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
        << A->getOption().getName() << A->getValue();
  }
  switch (UsedOpenMPLib) {
  case LibGOMP:
    CmdArgs.push_back("-lgomp");
    break;
  case LibIOMP5:
    CmdArgs.push_back("-liomp5");
    break;
  case LibUnknown:
    break;
  }

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
  
  if (isObjCRuntimeLinked(Args) &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // We use arclite library for both ARC and subscripting support.
    getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);

    CmdArgs.push_back("-framework");
    CmdArgs.push_back("Foundation");
    // Link libobj.
    CmdArgs.push_back("-lobjc");
  }

  if (LinkingOutput) {
    CmdArgs.push_back("-arch_multiple");
    CmdArgs.push_back("-final_output");
    CmdArgs.push_back(LinkingOutput);
  }

  if (Args.hasArg(options::OPT_fnested_functions))
    CmdArgs.push_back("-allow_stack_execute");

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);

    // link_ssp spec is empty.

    // Let the tool chain choose which runtime library to link.
    getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    // endfile_spec is empty.
  }

  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_F);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-create");
  assert(Output.isFilename() && "Unexpected lipo output.");

  CmdArgs.push_back("-output");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs) {
    assert(II.isFilename() && "Unexpected lipo input.");
    CmdArgs.push_back(II.getFilename());
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected dsymutil input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("--verify");
  CmdArgs.push_back("--debug-info");
  CmdArgs.push_back("--eh-frame");
  CmdArgs.push_back("--quiet");

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected verify input");

  // Grabbing the output of the earlier dsymutil run.
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  // FIXME: Find a real GCC, don't hard-code versions here
  std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
  const llvm::Triple &T = getToolChain().getTriple();
  std::string LibPath = "/usr/lib/";
  llvm::Triple::ArchType Arch = T.getArch();
  switch (Arch) {
  case llvm::Triple::x86:
    GCCLibPath +=
        ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
    break;
  case llvm::Triple::x86_64:
    GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
    GCCLibPath += "/4.5.2/amd64/";
    LibPath += "amd64/";
    break;
  default:
    llvm_unreachable("Unsupported architecture");
  }

  ArgStringList CmdArgs;

  // Demangle C++ names in errors
  CmdArgs.push_back("-C");

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    } else {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    }
    if (getToolChain().getDriver().CCCIsCXX())
      CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
  }

  CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
    CmdArgs.push_back("-lgcc_s");
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-lgcc");
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
  }
  CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
//    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
    }
    CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtn.o")));
  }

  CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
                                       + getToolChain().getTripleString()
                                       + "/4.2.4"));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: For some reason GCC passes -lgcc before adding
    // the default system libraries. Just mimic this for now.
    CmdArgs.push_back("-lgcc");

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-pthread");
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtend.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  bool NeedsKPIC = false;

  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    // When building 32-bit code on OpenBSD/amd64, we have to explicitly
    // instruct as in the base system to assemble 32-bit code.
    CmdArgs.push_back("--32");
    break;

  case llvm::Triple::ppc:
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
    break;

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    NeedsKPIC = true;
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
    break;

  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    NeedsKPIC = true;
    break;
  }

  default:
    break;
  }

  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void openbsd::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;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (getToolChain().getArch() == llvm::Triple::mips64)
    CmdArgs.push_back("-EB");
  else if (getToolChain().getArch() == llvm::Triple::mips64el)
    CmdArgs.push_back("-EL");

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Args.hasArg(options::OPT_nopie))
    CmdArgs.push_back("-nopie");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))  
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  std::string Triple = getToolChain().getTripleString();
  if (Triple.substr(0, 6) == "x86_64")
    Triple.replace(0, 6, "amd64");
  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
                                       "/4.2.1"));

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg)) 
        CmdArgs.push_back("-lm_p");
      else
        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");

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lpthread_p");
      else
         CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lc_p");
      else
         CmdArgs.push_back("-lc");
    }

    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    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");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void bitrig::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 ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lc_p");
      else
        CmdArgs.push_back("-lc");
    }

    StringRef MyArch;
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
      MyArch = "arm";
      break;
    case llvm::Triple::x86:
      MyArch = "i386";
      break;
    case llvm::Triple::x86_64:
      MyArch = "amd64";
      break;
    default:
      llvm_unreachable("Unsupported architecture");
    }
    CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");
  else if (getToolChain().getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("-a32");
  else if (getToolChain().getArch() == llvm::Triple::mips ||
           getToolChain().getArch() == llvm::Triple::mipsel ||
           getToolChain().getArch() == llvm::Triple::mips64 ||
           getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    addAssemblerKPIC(Args, CmdArgs);
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::armeb ||
             getToolChain().getArch() == llvm::Triple::thumb ||
             getToolChain().getArch() == llvm::Triple::thumbeb) {
    const Driver &D = getToolChain().getDriver();
    const llvm::Triple &Triple = getToolChain().getTriple();
    StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);

    if (FloatABI == "hard") {
      CmdArgs.push_back("-mfpu=vfp");
    } else {
      CmdArgs.push_back("-mfpu=softvfp");
    }

    switch(getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::GNUEABIHF:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::EABI:
      CmdArgs.push_back("-meabi=5");
      break;

    default:
      CmdArgs.push_back("-matpcs");
    }
  } else if (getToolChain().getArch() == llvm::Triple::sparc ||
             getToolChain().getArch() == llvm::Triple::sparcv9) {
    if (getToolChain().getArch() == llvm::Triple::sparc)
      CmdArgs.push_back("-Av8plusa");
    else
      CmdArgs.push_back("-Av9a");

    addAssemblerKPIC(Args, CmdArgs);
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const toolchains::FreeBSD& ToolChain = 
    static_cast<const toolchains::FreeBSD&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (IsPIE)
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld-elf.so.1");
    }
    if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
      llvm::Triple::ArchType Arch = ToolChain.getArch();
      if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
          Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
        CmdArgs.push_back("--hash-style=both");
      }
    }
    CmdArgs.push_back("--enable-new-dtags");
  }

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (ToolChain.getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386_fbsd");
  }

  if (ToolChain.getArch() == llvm::Triple::ppc) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32ppc_fbsd");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    const char *crt1 = nullptr;
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        crt1 = "gcrt1.o";
      else if (IsPIE)
        crt1 = "Scrt1.o";
      else
        crt1 = "crt1.o";
    }
    if (crt1)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

    const char *crtbegin = nullptr;
    if (Args.hasArg(options::OPT_static))
      crtbegin = "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared) || IsPIE)
      crtbegin = "crtbeginS.o";
    else
      crtbegin = "crtbegin.o";

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  const ToolChain::path_list Paths = ToolChain.getFilePaths();
  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
  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);

  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }
    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
    // the default system libraries. Just mimic this for now.
    if (Args.hasArg(options::OPT_pg))
      CmdArgs.push_back("-lgcc_p");
    else
      CmdArgs.push_back("-lgcc");
    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (Args.hasArg(options::OPT_pg)) {
      if (Args.hasArg(options::OPT_shared))
        CmdArgs.push_back("-lc");
      else
        CmdArgs.push_back("-lc_p");
      CmdArgs.push_back("-lgcc_p");
    } else {
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lgcc");
    }

    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || IsPIE)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
  }

  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);

  addProfileRT(ToolChain, Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // GNU as needs different flags for creating the correct output format
  // on architectures with different ABIs or optional feature sets.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    CmdArgs.push_back("--32");
    break;
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb: {
    std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
    CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
    break;
  }

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    addAssemblerKPIC(Args, CmdArgs);
    break;
  }

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  default:
    break;  
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void netbsd::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 (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  CmdArgs.push_back("--eh-frame-hdr");
  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld.elf_so");
    }
  }

  // Many NetBSD architectures support more than one ABI.
  // Determine the correct emulation for ld.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
    break;
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    CmdArgs.push_back("-m");
    switch (getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::EABI:
    case llvm::Triple::GNUEABI:
      CmdArgs.push_back("armelf_nbsd_eabi");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      CmdArgs.push_back("armelf_nbsd_eabihf");
      break;
    default:
      CmdArgs.push_back("armelf_nbsd");
      break;
    }
    break;
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    if (mips::hasMipsAbiArg(Args, "32")) {
      CmdArgs.push_back("-m");
      if (getToolChain().getArch() == llvm::Triple::mips64)
        CmdArgs.push_back("elf32btsmip");
      else
        CmdArgs.push_back("elf32ltsmip");
   } else if (mips::hasMipsAbiArg(Args, "64")) {
     CmdArgs.push_back("-m");
     if (getToolChain().getArch() == llvm::Triple::mips64)
       CmdArgs.push_back("elf64btsmip");
     else
       CmdArgs.push_back("elf64ltsmip");
   }
   break;

  case llvm::Triple::sparc:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32_sparc");
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf64_sparc");
    break;

  default:
    break;
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  unsigned Major, Minor, Micro;
  getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
  bool useLibgcc = true;
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) {
    switch(getToolChain().getArch()) {
    case llvm::Triple::aarch64:
    case llvm::Triple::arm:
    case llvm::Triple::armeb:
    case llvm::Triple::thumb:
    case llvm::Triple::thumbeb:
    case llvm::Triple::ppc:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      useLibgcc = false;
      break;
    default:
      break;
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");

    if (useLibgcc) {
      if (Args.hasArg(options::OPT_static)) {
        // libgcc_eh depends on libc, so resolve as much as possible,
        // pull in any new requirements from libc and then get the rest
        // of libgcc.
        CmdArgs.push_back("-lgcc_eh");
        CmdArgs.push_back("-lc");
        CmdArgs.push_back("-lgcc");
      } else {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("--as-needed");
        CmdArgs.push_back("-lgcc_s");
        CmdArgs.push_back("--no-as-needed");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                  "crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                 "crtendS.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                    "crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  bool NeedsKPIC = false;

  // 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) {
    if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
      CmdArgs.push_back("--x32");
    else
      CmdArgs.push_back("--64");
  } else if (getToolChain().getArch() == llvm::Triple::ppc) {
    CmdArgs.push_back("-a32");
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64");
    CmdArgs.push_back("-many");
    CmdArgs.push_back("-mlittle-endian");
  } else if (getToolChain().getArch() == llvm::Triple::sparc) {
    CmdArgs.push_back("-32");
    CmdArgs.push_back("-Av8plusa");
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::armeb) {
    StringRef MArch = getToolChain().getArchName();
    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
      CmdArgs.push_back("-mfpu=neon");
    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" ||
        MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
      CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");

    StringRef ARMFloatABI = tools::arm::getARMFloatABI(
        getToolChain().getDriver(), Args, getToolChain().getTriple());
    CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));

    Args.AddLastArg(CmdArgs, options::OPT_march_EQ);

    // FIXME: remove krait check when GNU tools support krait cpu
    // for now replace it with -march=armv7-a  to avoid a lower
    // march from being picked in the absence of a cpu flag.
    Arg *A;
    if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
      StringRef(A->getValue()) == "krait")
        CmdArgs.push_back("-march=armv7-a");
    else
      Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
    Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
  } else if (getToolChain().getArch() == llvm::Triple::mips ||
             getToolChain().getArch() == llvm::Triple::mipsel ||
             getToolChain().getArch() == llvm::Triple::mips64 ||
             getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
    ABIName = getGnuCompatibleMipsABIName(ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(ABIName.data());

    // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
    // or -mshared (not implemented) is in effect.
    bool IsPicOrPie = false;
    if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                 options::OPT_fpic, options::OPT_fno_pic,
                                 options::OPT_fPIE, options::OPT_fno_PIE,
                                 options::OPT_fpie, options::OPT_fno_pie)) {
      if (A->getOption().matches(options::OPT_fPIC) ||
          A->getOption().matches(options::OPT_fpic) ||
          A->getOption().matches(options::OPT_fPIE) ||
          A->getOption().matches(options::OPT_fpie))
        IsPicOrPie = true;
    }
    if (!IsPicOrPie)
      CmdArgs.push_back("-mno-shared");

    // LLVM doesn't support -mplt yet and acts as if it is always given.
    // However, -mplt has no effect with the N64 ABI.
    CmdArgs.push_back(ABIName == "64" ? "-KPIC" : "-call_nonpic");

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
      if (StringRef(A->getValue()) == "2008")
        CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
    }

    // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
    if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
                                 options::OPT_mfp64)) {
      A->claim();
      A->render(Args, CmdArgs);
    } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
                                   ABIName))
      CmdArgs.push_back("-mfpxx");

    // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
    // -mno-mips16 is actually -no-mips16.
    if (Arg *A = Args.getLastArg(options::OPT_mips16,
                                 options::OPT_mno_mips16)) {
      if (A->getOption().matches(options::OPT_mips16)) {
        A->claim();
        A->render(Args, CmdArgs);
      } else {
        A->claim();
        CmdArgs.push_back("-no-mips16");
      }
    }

    Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
                    options::OPT_mno_micromips);
    Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
    Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);

    if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
      // Do not use AddLastArg because not all versions of MIPS assembler
      // support -mmsa / -mno-msa options.
      if (A->getOption().matches(options::OPT_mmsa))
        CmdArgs.push_back(Args.MakeArgString("-mmsa"));
    }

    Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
                    options::OPT_msoft_float);

    Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
                    options::OPT_mno_odd_spreg);

    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::systemz) {
    // Always pass an -march option, since our default of z10 is later
    // than the GNU assembler's default.
    StringRef CPUName = getSystemZTargetCPU(Args);
    CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
  }

  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
  bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
                      Args.hasArg(options::OPT_static);
  if (!D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  if (StaticLibgcc || isAndroid) {
    if (D.CCCIsCXX())
      CmdArgs.push_back("-lgcc");
  } else {
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--as-needed");
    CmdArgs.push_back("-lgcc_s");
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--no-as-needed");
  }

  if (StaticLibgcc && !isAndroid)
    CmdArgs.push_back("-lgcc_eh");
  else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  // According to Android ABI, we have to link with libdl if we are
  // linking with non-static libgcc.
  //
  // NOTE: This fixes a link error on Android MIPS as well.  The non-static
  // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
  if (isAndroid && !StaticLibgcc)
    CmdArgs.push_back("-ldl");
}

static std::string getLinuxDynamicLinker(const ArgList &Args,
                                         const toolchains::Linux &ToolChain) {
  if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
    if (ToolChain.getTriple().isArch64Bit())
      return "/system/bin/linker64";
    else
      return "/system/bin/linker";
  } else if (ToolChain.getArch() == llvm::Triple::x86 ||
             ToolChain.getArch() == llvm::Triple::sparc)
    return "/lib/ld-linux.so.2";
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    return "/lib/ld-linux-aarch64.so.1";
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
    return "/lib/ld-linux-aarch64_be.so.1";
  else if (ToolChain.getArch() == llvm::Triple::arm ||
           ToolChain.getArch() == llvm::Triple::thumb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";
    else
      return "/lib/ld-linux.so.3";
  } else if (ToolChain.getArch() == llvm::Triple::armeb ||
             ToolChain.getArch() == llvm::Triple::thumbeb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";        /* TODO: check which dynamic linker name.  */
    else
      return "/lib/ld-linux.so.3";              /* TODO: check which dynamic linker name.  */
  } else if (ToolChain.getArch() == llvm::Triple::mips ||
             ToolChain.getArch() == llvm::Triple::mipsel ||
             ToolChain.getArch() == llvm::Triple::mips64 ||
             ToolChain.getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName);
    bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple());

    StringRef LibDir = llvm::StringSwitch<llvm::StringRef>(ABIName)
                           .Case("o32", "/lib")
                           .Case("n32", "/lib32")
                           .Case("n64", "/lib64")
                           .Default("/lib");
    StringRef LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1";

    return (LibDir + "/" + LibName).str();
  } else if (ToolChain.getArch() == llvm::Triple::ppc)
    return "/lib/ld.so.1";
  else if (ToolChain.getArch() == llvm::Triple::ppc64) {
    if (ppc::hasPPCAbiArg(Args, "elfv2"))
      return "/lib64/ld64.so.2";
    return "/lib64/ld64.so.1";
  } else if (ToolChain.getArch() == llvm::Triple::ppc64le) {
    if (ppc::hasPPCAbiArg(Args, "elfv1"))
      return "/lib64/ld64.so.1";
    return "/lib64/ld64.so.2";
  } else if (ToolChain.getArch() == llvm::Triple::systemz)
    return "/lib64/ld64.so.1";
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    return "/lib64/ld-linux.so.2";
  else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
           ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
    return "/libx32/ld-linux-x32.so.2";
  else
    return "/lib64/ld-linux-x86-64.so.2";
}

static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  // Make use of compiler-rt if --rtlib option is used
  ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);

  switch(RLT) {
  case ToolChain::RLT_CompilerRT:
    addClangRTLinux(TC, Args, CmdArgs);
    break;
  case ToolChain::RLT_Libgcc:
    AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
    break;
  }
}

void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  const toolchains::Linux& ToolChain =
    static_cast<const toolchains::Linux&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const bool isAndroid =
    ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    !Args.hasArg(options::OPT_static) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
     // On Android every code is PIC so every executable is PIE
     // Cannot use isPIEDefault here since otherwise
     // PIE only logic will be enabled during compilation
     isAndroid);

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (IsPIE)
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  for (const auto &Opt : ToolChain.ExtraOpts)
    CmdArgs.push_back(Opt.c_str());

  if (!Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("--eh-frame-hdr");
  }

  CmdArgs.push_back("-m");
  if (ToolChain.getArch() == llvm::Triple::x86)
    CmdArgs.push_back("elf_i386");
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    CmdArgs.push_back("aarch64linux");
  else if (ToolChain.getArch() == llvm::Triple::aarch64_be)
    CmdArgs.push_back("aarch64_be_linux");
  else if (ToolChain.getArch() == llvm::Triple::arm
           ||  ToolChain.getArch() == llvm::Triple::thumb)
    CmdArgs.push_back("armelf_linux_eabi");
  else if (ToolChain.getArch() == llvm::Triple::armeb
           ||  ToolChain.getArch() == llvm::Triple::thumbeb)
    CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME.  */
  else if (ToolChain.getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("elf32ppclinux");
  else if (ToolChain.getArch() == llvm::Triple::ppc64)
    CmdArgs.push_back("elf64ppc");
  else if (ToolChain.getArch() == llvm::Triple::ppc64le)
    CmdArgs.push_back("elf64lppc");
  else if (ToolChain.getArch() == llvm::Triple::sparc)
    CmdArgs.push_back("elf32_sparc");
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    CmdArgs.push_back("elf64_sparc");
  else if (ToolChain.getArch() == llvm::Triple::mips)
    CmdArgs.push_back("elf32btsmip");
  else if (ToolChain.getArch() == llvm::Triple::mipsel)
    CmdArgs.push_back("elf32ltsmip");
  else if (ToolChain.getArch() == llvm::Triple::mips64) {
    if (mips::hasMipsAbiArg(Args, "n32"))
      CmdArgs.push_back("elf32btsmipn32");
    else
      CmdArgs.push_back("elf64btsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::mips64el) {
    if (mips::hasMipsAbiArg(Args, "n32"))
      CmdArgs.push_back("elf32ltsmipn32");
    else
      CmdArgs.push_back("elf64ltsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::systemz)
    CmdArgs.push_back("elf64_s390");
  else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
           ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
    CmdArgs.push_back("elf32_x86_64");
  else
    CmdArgs.push_back("elf_x86_64");

  if (Args.hasArg(options::OPT_static)) {
    if (ToolChain.getArch() == llvm::Triple::arm ||
        ToolChain.getArch() == llvm::Triple::armeb ||
        ToolChain.getArch() == llvm::Triple::thumb ||
        ToolChain.getArch() == llvm::Triple::thumbeb)
      CmdArgs.push_back("-Bstatic");
    else
      CmdArgs.push_back("-static");
  } else if (Args.hasArg(options::OPT_shared)) {
    CmdArgs.push_back("-shared");
  }

  if (ToolChain.getArch() == llvm::Triple::arm ||
      ToolChain.getArch() == llvm::Triple::armeb ||
      ToolChain.getArch() == llvm::Triple::thumb ||
      ToolChain.getArch() == llvm::Triple::thumbeb ||
      (!Args.hasArg(options::OPT_static) &&
       !Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-dynamic-linker");
    CmdArgs.push_back(Args.MakeArgString(
        D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!isAndroid) {
      const char *crt1 = nullptr;
      if (!Args.hasArg(options::OPT_shared)){
        if (Args.hasArg(options::OPT_pg))
          crt1 = "gcrt1.o";
        else if (IsPIE)
          crt1 = "Scrt1.o";
        else
          crt1 = "crt1.o";
      }
      if (crt1)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
    }

    const char *crtbegin;
    if (Args.hasArg(options::OPT_static))
      crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared))
      crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
    else if (IsPIE)
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
    else
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));

    // Add crtfastmath.o if available and fast math is enabled.
    ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_u);

  const ToolChain::path_list Paths = ToolChain.getFilePaths();

  for (const auto &Path : Paths)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));

  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);

  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
  // The profile runtime also needs access to system libraries.
  addProfileRT(getToolChain(), Args, CmdArgs);

  if (D.CCCIsCXX() &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
      !Args.hasArg(options::OPT_static);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bstatic");
    ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bdynamic");
    CmdArgs.push_back("-lm");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--start-group");

      LibOpenMP UsedOpenMPLib = LibUnknown;
      if (Args.hasArg(options::OPT_fopenmp)) {
        UsedOpenMPLib = LibGOMP;
      } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
        UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
            .Case("libgomp",  LibGOMP)
            .Case("libiomp5", LibIOMP5)
            .Default(LibUnknown);
        if (UsedOpenMPLib == LibUnknown)
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << A->getValue();
      }
      switch (UsedOpenMPLib) {
      case LibGOMP:
        CmdArgs.push_back("-lgomp");

        // FIXME: Exclude this for platforms with libgomp that don't require
        // librt. Most modern Linux platforms require it, but some may not.
        CmdArgs.push_back("-lrt");
        break;
      case LibIOMP5:
        CmdArgs.push_back("-liomp5");
        break;
      case LibUnknown:
        break;
      }
      AddRunTimeLibs(ToolChain, D, CmdArgs, Args);

      if ((Args.hasArg(options::OPT_pthread) ||
           Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) &&
          !isAndroid)
        CmdArgs.push_back("-lpthread");

      CmdArgs.push_back("-lc");

      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--end-group");
      else
        AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
    }

    if (!Args.hasArg(options::OPT_nostartfiles)) {
      const char *crtend;
      if (Args.hasArg(options::OPT_shared))
        crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
      else if (IsPIE)
        crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
      else
        crtend = isAndroid ? "crtend_android.o" : "crtend.o";

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
      if (!isAndroid)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
    }
  }

  C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}

void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                   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");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void minix::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("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  addProfileRT(getToolChain(), Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lCompilerRT-Generic");
    CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
    CmdArgs.push_back(
         Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

/// DragonFly Tools

// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  bool UseGCC47 = false;
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47))
    UseGCC47 = false;

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  CmdArgs.push_back("--eh-frame-hdr");
  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-Bshareable");
    else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
    }
    CmdArgs.push_back("--hash-style=both");
  }

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt1.o")));
      else {
        if (Args.hasArg(options::OPT_pie))
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("Scrt1.o")));
        else
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("crt1.o")));
      }
    }
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crti.o")));
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
    //         rpaths
    if (UseGCC47)
      CmdArgs.push_back("-L/usr/lib/gcc47");
    else
      CmdArgs.push_back("-L/usr/lib/gcc44");

    if (!Args.hasArg(options::OPT_static)) {
      if (UseGCC47) {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc47");
      } else {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc44");
      }
    }

    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");

    if (!Args.hasArg(options::OPT_nolibc)) {
      CmdArgs.push_back("-lc");
    }

    if (UseGCC47) {
      if (Args.hasArg(options::OPT_static) ||
          Args.hasArg(options::OPT_static_libgcc)) {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("-lgcc_eh");
      } else {
        if (Args.hasArg(options::OPT_shared_libgcc)) {
          CmdArgs.push_back("-lgcc_pic");
          if (!Args.hasArg(options::OPT_shared))
            CmdArgs.push_back("-lgcc");
        } else {
          CmdArgs.push_back("-lgcc");
          CmdArgs.push_back("--as-needed");
          CmdArgs.push_back("-lgcc_pic");
          CmdArgs.push_back("--no-as-needed");
        }
      }
    } else {
      if (Args.hasArg(options::OPT_shared)) {
        CmdArgs.push_back("-lgcc_pic");
      } else {
        CmdArgs.push_back("-lgcc");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs,
                                  const StringRef RTName) {
  SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
  llvm::sys::path::append(LibSanitizer,
                          Twine("clang_rt.") + RTName + ".lib");
  CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
}

void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
  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) &&
      !C.getDriver().IsCLMode()) {
    CmdArgs.push_back("-defaultlib:libcmt");
  }

  CmdArgs.push_back("-nologo");

  if (Args.hasArg(options::OPT_g_Group)) {
    CmdArgs.push_back("-debug");
  }

  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);

  if (DLL) {
    CmdArgs.push_back(Args.MakeArgString("-dll"));

    SmallString<128> ImplibName(Output.getFilename());
    llvm::sys::path::replace_extension(ImplibName, "lib");
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
                                         ImplibName.str()));
  }

  if (getToolChain().getSanitizerArgs().needsAsanRt()) {
    CmdArgs.push_back(Args.MakeArgString("-debug"));
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
    // FIXME: Handle 64-bit.
    if (DLL) {
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
                            "asan_dll_thunk-i386");
    } else {
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
      addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
    }
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_l);
  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);

  // Add filenames immediately.
  for (const auto &Input : Inputs)
    if (Input.isFilename())
      CmdArgs.push_back(Input.getFilename());
    else
      Input.getInputArg().renderAsInput(Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
                                         const InputInfo &Output,
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
  C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}

// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
// If one cannot be found, return FallbackName.
// We do this special search to prevent clang-cl from falling back onto itself
// if it's available as cl.exe on the path.
static std::string FindFallback(const char *FallbackName,
                                const char *ClangProgramPath) {
  llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
  if (!OptPath.hasValue())
    return FallbackName;

  const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
  SmallVector<StringRef, 8> PathSegments;
  llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);

  for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
    const StringRef &PathSegment = PathSegments[i];
    if (PathSegment.empty())
      continue;

    SmallString<128> FilePath(PathSegment);
    llvm::sys::path::append(FilePath, FallbackName);
    if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
        !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
      return FilePath.str();
  }

  return FallbackName;
}

Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("/nologo");
  CmdArgs.push_back("/c"); // Compile only.
  CmdArgs.push_back("/W0"); // No warnings.

  // The goal is to be able to invoke this tool correctly based on
  // any flag accepted by clang-cl.

  // These are spelled the same way in clang and cl.exe,.
  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I);

  // Optimization level.
  if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
    if (A->getOption().getID() == options::OPT_O0) {
      CmdArgs.push_back("/Od");
    } else {
      StringRef OptLevel = A->getValue();
      if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
        A->render(Args, CmdArgs);
      else if (OptLevel == "3")
        CmdArgs.push_back("/Ox");
    }
  }

  // Flags for which clang-cl have an alias.
  // FIXME: How can we ensure this stays in sync with relevant clang-cl options?

  if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
                   /*default=*/false))
    CmdArgs.push_back("/GR-");
  if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
                               options::OPT_fno_function_sections))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
                          ? "/Gy"
                          : "/Gy-");
  if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
                               options::OPT_fno_data_sections))
    CmdArgs.push_back(
        A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
  if (Args.hasArg(options::OPT_fsyntax_only))
    CmdArgs.push_back("/Zs");
  if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
    CmdArgs.push_back("/Z7");

  std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
  for (const auto &Include : Includes)
    CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));

  // Flags that can simply be passed through.
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);

  // The order of these flags is relevant, so pick the last one.
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
                               options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
    A->render(Args, CmdArgs);


  // Input filename.
  assert(Inputs.size() == 1);
  const InputInfo &II = Inputs[0];
  assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
  CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
  if (II.isFilename())
    CmdArgs.push_back(II.getFilename());
  else
    II.getInputArg().renderAsInput(Args, CmdArgs);

  // Output filename.
  assert(Output.getType() == types::TY_Object);
  const char *Fo = Args.MakeArgString(std::string("/Fo") +
                                      Output.getFilename());
  CmdArgs.push_back(Fo);

  const Driver &D = getToolChain().getDriver();
  std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());
  return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
}


/// XCore Tools
// We pass assemble and link construction to the xcc tool.

void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  CmdArgs.push_back("-c");

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  if (Arg *A = Args.getLastArg(options::OPT_g_Group))
    if (!A->getOption().matches(options::OPT_g0))
      CmdArgs.push_back("-g");

  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   false))
    CmdArgs.push_back("-fverbose-asm");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  for (const auto &II : Inputs)
    CmdArgs.push_back(II.getFilename());

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
  if (EH.ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@


1.1.1.6.4.1
log
@file Tools.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:27 +0000
@
text
@d1 7404
@


1.1.1.6.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 7404
//===--- Tools.cpp - Tools Implementations --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <sys/stat.h>

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;

static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                    options::OPT_fpic, options::OPT_fno_pic,
                                    options::OPT_fPIE, options::OPT_fno_PIE,
                                    options::OPT_fpie, options::OPT_fno_pie);
  if (!LastPICArg)
    return;
  if (LastPICArg->getOption().matches(options::OPT_fPIC) ||
      LastPICArg->getOption().matches(options::OPT_fpic) ||
      LastPICArg->getOption().matches(options::OPT_fPIE) ||
      LastPICArg->getOption().matches(options::OPT_fpie)) {
    CmdArgs.push_back("-KPIC");
  }
}

/// CheckPreprocessingOptions - Perform some validation of preprocessing
/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
    if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP())
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "-E";
}

/// CheckCodeGenerationOptions - Perform some validation of code generation
/// arguments that is shared with gcc.
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
  // In gcc, only ARM checks this, but it seems reasonable to check universally.
  if (Args.hasArg(options::OPT_static))
    if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
                                       options::OPT_mdynamic_no_pic))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-static";
}

// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
static void QuoteTarget(StringRef Target,
                        SmallVectorImpl<char> &Res) {
  for (unsigned i = 0, e = Target.size(); i != e; ++i) {
    switch (Target[i]) {
    case ' ':
    case '\t':
      // Escape the preceding backslashes
      for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
        Res.push_back('\\');

      // Escape the space/tab
      Res.push_back('\\');
      break;
    case '$':
      Res.push_back('$');
      break;
    case '#':
      Res.push_back('\\');
      break;
    default:
      break;
    }

    Res.push_back(Target[i]);
  }
}

static void addDirectoryList(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             const char *ArgName,
                             const char *EnvVar) {
  const char *DirList = ::getenv(EnvVar);
  bool CombinedArg = false;

  if (!DirList)
    return; // Nothing to do.

  StringRef Name(ArgName);
  if (Name.equals("-I") || Name.equals("-L"))
    CombinedArg = true;

  StringRef Dirs(DirList);
  if (Dirs.empty()) // Empty string should not add '.'.
    return;

  StringRef::size_type Delim;
  while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
    if (Delim == 0) { // Leading colon.
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(".");
      }
    } else {
      if (CombinedArg) {
        CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
      } else {
        CmdArgs.push_back(ArgName);
        CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
      }
    }
    Dirs = Dirs.substr(Delim + 1);
  }

  if (Dirs.empty()) { // Trailing colon.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(".");
    }
  } else { // Add the last path.
    if (CombinedArg) {
      CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
    } else {
      CmdArgs.push_back(ArgName);
      CmdArgs.push_back(Args.MakeArgString(Dirs));
    }
  }
}

static void AddLinkerInputs(const ToolChain &TC,
                            const InputInfoList &Inputs, const ArgList &Args,
                            ArgStringList &CmdArgs) {
  const Driver &D = TC.getDriver();

  // Add extra linker input arguments which are not treated as inputs
  // (constructed via -Xarch_).
  Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    if (!TC.HasNativeLLVMSupport()) {
      // Don't try to pass LLVM inputs unless we have native support.
      if (II.getType() == types::TY_LLVM_IR ||
          II.getType() == types::TY_LTO_IR ||
          II.getType() == types::TY_LLVM_BC ||
          II.getType() == types::TY_LTO_BC)
        D.Diag(diag::err_drv_no_linker_llvm_support)
          << TC.getTripleString();
    }

    // Add filenames immediately.
    if (II.isFilename()) {
      CmdArgs.push_back(II.getFilename());
      continue;
    }

    // Otherwise, this is a linker input argument.
    const Arg &A = II.getInputArg();

    // Handle reserved library options.
    if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
      TC.AddCXXStdlibLibArgs(Args, CmdArgs);
    } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) {
      TC.AddCCKextLibArgs(Args, CmdArgs);
    } else
      A.renderAsInput(Args, CmdArgs);
  }

  // LIBRARY_PATH - included following the user specified library paths.
  //                and only supported on native toolchains.
  if (!TC.isCrossCompiling())
    addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
}

/// \brief Determine whether Objective-C automated reference counting is
/// enabled.
static bool isObjCAutoRefCount(const ArgList &Args) {
  return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
}

/// \brief Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
  if (isObjCAutoRefCount(Args)) {
    Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
    return true;
  }
  return Args.hasArg(options::OPT_fobjc_link_runtime);
}

static bool forwardToGCC(const Option &O) {
  // Don't forward inputs from the original command line.  They are added from
  // InputInfoList.
  return O.getKind() != Option::InputClass &&
         !O.hasFlag(options::DriverOption) &&
         !O.hasFlag(options::LinkerInput);
}

void Clang::AddPreprocessingOptions(Compilation &C,
                                    const JobAction &JA,
                                    const Driver &D,
                                    const ArgList &Args,
                                    ArgStringList &CmdArgs,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs) const {
  Arg *A;

  CheckPreprocessingOptions(D, Args);

  Args.AddLastArg(CmdArgs, options::OPT_C);
  Args.AddLastArg(CmdArgs, options::OPT_CC);

  // Handle dependency file generation.
  if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
      (A = Args.getLastArg(options::OPT_MD)) ||
      (A = Args.getLastArg(options::OPT_MMD))) {
    // Determine the output location.
    const char *DepFile;
    if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
      DepFile = MF->getValue();
      C.addFailureResultFile(DepFile, &JA);
    } else if (Output.getType() == types::TY_Dependencies) {
      DepFile = Output.getFilename();
    } else if (A->getOption().matches(options::OPT_M) ||
               A->getOption().matches(options::OPT_MM)) {
      DepFile = "-";
    } else {
      DepFile = getDependencyFileName(Args, Inputs);
      C.addFailureResultFile(DepFile, &JA);
    }
    CmdArgs.push_back("-dependency-file");
    CmdArgs.push_back(DepFile);

    // Add a default target if one wasn't specified.
    if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
      const char *DepTarget;

      // If user provided -o, that is the dependency target, except
      // when we are only generating a dependency file.
      Arg *OutputOpt = Args.getLastArg(options::OPT_o);
      if (OutputOpt && Output.getType() != types::TY_Dependencies) {
        DepTarget = OutputOpt->getValue();
      } else {
        // Otherwise derive from the base input.
        //
        // FIXME: This should use the computed output file location.
        SmallString<128> P(Inputs[0].getBaseInput());
        llvm::sys::path::replace_extension(P, "o");
        DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
      }

      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(DepTarget, Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));
    }

    if (A->getOption().matches(options::OPT_M) ||
        A->getOption().matches(options::OPT_MD))
      CmdArgs.push_back("-sys-header-deps");
  }

  if (Args.hasArg(options::OPT_MG)) {
    if (!A || A->getOption().matches(options::OPT_MD) ||
              A->getOption().matches(options::OPT_MMD))
      D.Diag(diag::err_drv_mg_requires_m_or_mm);
    CmdArgs.push_back("-MG");
  }

  Args.AddLastArg(CmdArgs, options::OPT_MP);

  // Convert all -MQ <target> args to -MT <quoted target>
  for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
                                             options::OPT_MQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = *it;
    A->claim();

    if (A->getOption().matches(options::OPT_MQ)) {
      CmdArgs.push_back("-MT");
      SmallString<128> Quoted;
      QuoteTarget(A->getValue(), Quoted);
      CmdArgs.push_back(Args.MakeArgString(Quoted));

    // -MT flag - no change
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Add -i* options, and automatically translate to
  // -include-pch/-include-pth for transparent PCH support. It's
  // wonky, but we include looking for .gch so we can support seamless
  // replacement into a build system already set up to be generating
  // .gch files.
  bool RenderedImplicitInclude = false;
  for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
         ie = Args.filtered_end(); it != ie; ++it) {
    const Arg *A = it;

    if (A->getOption().matches(options::OPT_include)) {
      bool IsFirstImplicitInclude = !RenderedImplicitInclude;
      RenderedImplicitInclude = true;

      // Use PCH if the user requested it.
      bool UsePCH = D.CCCUsePCH;

      bool FoundPTH = false;
      bool FoundPCH = false;
      SmallString<128> P(A->getValue());
      // We want the files to have a name like foo.h.pch. Add a dummy extension
      // so that replace_extension does the right thing.
      P += ".dummy";
      if (UsePCH) {
        llvm::sys::path::replace_extension(P, "pch");
        if (llvm::sys::fs::exists(P.str()))
          FoundPCH = true;
      }

      if (!FoundPCH) {
        llvm::sys::path::replace_extension(P, "pth");
        if (llvm::sys::fs::exists(P.str()))
          FoundPTH = true;
      }

      if (!FoundPCH && !FoundPTH) {
        llvm::sys::path::replace_extension(P, "gch");
        if (llvm::sys::fs::exists(P.str())) {
          FoundPCH = UsePCH;
          FoundPTH = !UsePCH;
        }
      }

      if (FoundPCH || FoundPTH) {
        if (IsFirstImplicitInclude) {
          A->claim();
          if (UsePCH)
            CmdArgs.push_back("-include-pch");
          else
            CmdArgs.push_back("-include-pth");
          CmdArgs.push_back(Args.MakeArgString(P.str()));
          continue;
        } else {
          // Ignore the PCH if not first on command line and emit warning.
          D.Diag(diag::warn_drv_pch_not_first_include)
              << P.str() << A->getAsString(Args);
        }
      }
    }

    // Not translated, render as usual.
    A->claim();
    A->render(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F,
                  options::OPT_index_header_map);

  // Add -Wp, and -Xassembler if using the preprocessor.

  // FIXME: There is a very unfortunate problem here, some troubled
  // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
  // really support that we would have to parse and then translate
  // those options. :(
  Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
                       options::OPT_Xpreprocessor);

  // -I- is a deprecated GCC feature, reject it.
  if (Arg *A = Args.getLastArg(options::OPT_I_))
    D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args);

  // If we have a --sysroot, and don't have an explicit -isysroot flag, add an
  // -isysroot to the CC1 invocation.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    if (!Args.hasArg(options::OPT_isysroot)) {
      CmdArgs.push_back("-isysroot");
      CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
    }
  }

  // Parse additional include paths from environment variables.
  // FIXME: We should probably sink the logic for handling these from the
  // frontend into the driver. It will allow deleting 4 otherwise unused flags.
  // CPATH - included following the user specified includes (but prior to
  // builtin and standard includes).
  addDirectoryList(Args, CmdArgs, "-I", "CPATH");
  // C_INCLUDE_PATH - system includes enabled when compiling C.
  addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH");
  // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
  addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH");
  // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
  addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH");
  // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
  addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");

  // Add C++ include arguments, if needed.
  if (types::isCXX(Inputs[0].getType()))
    getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);

  // Add system include arguments.
  getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
}

/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting.
//
// FIXME: tblgen this.
static std::string getAArch64TargetCPU(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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  return "generic";
}

// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return true;

  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
  case llvm::Triple::arm:
  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
    if (Triple.isOSDarwin())
      return true;
    return false;

  case llvm::Triple::ppc64le:
  case llvm::Triple::systemz:
  case llvm::Triple::xcore:
    return false;
  }
}

static bool isNoCommonDefault(const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  default:
    return false;

  case llvm::Triple::xcore:
    return true;
  }
}

// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
static void getAArch64FPUFeatures(const Driver &D, const Arg *A,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
  StringRef FPU = A->getValue();
  if (FPU == "fp-armv8") {
    Features.push_back("+fp-armv8");
  } else if (FPU == "neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
  } else if (FPU == "crypto-neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("+crypto");
  } else if (FPU == "neon") {
    Features.push_back("+neon");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Handle -mhwdiv=.
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef HWDiv = A->getValue();
  if (HWDiv == "arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("-hwdiv");
  } else if (HWDiv == "thumb") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
    Features.push_back("+hwdiv-arm");
    Features.push_back("+hwdiv");
  } else if (HWDiv == "none") {
    Features.push_back("-hwdiv-arm");
    Features.push_back("-hwdiv");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
 
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
static void getARMFPUFeatures(const Driver &D, const Arg *A,
                              const ArgList &Args,
                              std::vector<const char *> &Features) {
  StringRef FPU = A->getValue();

  // Set the target features based on the FPU.
  if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
    // Disable any default FPU support.
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-neon");
  } else if (FPU == "vfp") {
    Features.push_back("+vfp2");
    Features.push_back("-neon");
  } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
    Features.push_back("+vfp3");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp3" || FPU == "vfpv3") {
    Features.push_back("+vfp3");
    Features.push_back("-neon");
  } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("-neon");
  } else if (FPU == "vfp4" || FPU == "vfpv4") {
    Features.push_back("+vfp4");
    Features.push_back("-neon");
  } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
    Features.push_back("+vfp4");
    Features.push_back("+d16");
    Features.push_back("+fp-only-sp");
    Features.push_back("-neon");
  } else if (FPU == "fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("-neon");
    Features.push_back("-crypto");
  } else if (FPU == "neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("-crypto");
  } else if (FPU == "crypto-neon-fp-armv8") {
    Features.push_back("+fp-armv8");
    Features.push_back("+neon");
    Features.push_back("+crypto");
  } else if (FPU == "neon") {
    Features.push_back("+neon");
  } else if (FPU == "none") {
    Features.push_back("-vfp2");
    Features.push_back("-vfp3");
    Features.push_back("-vfp4");
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  } else
    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}

// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
                                     const llvm::Triple &Triple) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi)
          << A->getAsString(Args);
        FloatABI = "soft";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    switch (Triple.getOS()) {
    case llvm::Triple::Darwin:
    case llvm::Triple::MacOSX:
    case llvm::Triple::IOS: {
      // Darwin defaults to "softfp" for v6 and v7.
      //
      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
      std::string ArchName =
        arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
      if (StringRef(ArchName).startswith("v6") ||
          StringRef(ArchName).startswith("v7"))
        FloatABI = "softfp";
      else
        FloatABI = "soft";
      break;
    }

    case llvm::Triple::FreeBSD:
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      default:
        // FreeBSD defaults to soft float
        FloatABI = "soft";
        break;
      }
      break;

    default:
      switch(Triple.getEnvironment()) {
      case llvm::Triple::GNUEABIHF:
        FloatABI = "hard";
        break;
      case llvm::Triple::GNUEABI:
        FloatABI = "softfp";
        break;
      case llvm::Triple::EABIHF:
        FloatABI = "hard";
        break;
      case llvm::Triple::EABI:
        // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
        FloatABI = "softfp";
        break;
      case llvm::Triple::MachO: {
        FloatABI = "soft";
        break;
      }
      case llvm::Triple::Android: {
        std::string ArchName =
          arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
        if (StringRef(ArchName).startswith("v7"))
          FloatABI = "softfp";
        else
          FloatABI = "soft";
        break;
      }
      default:
        // Assume "soft", but warn the user we are guessing.
        FloatABI = "soft";
        D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
        break;
      }
    }
  }

  return FloatABI;
}

static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features,
                                 bool ForAS) {
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
  if (!ForAS) {
    // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
    // yet (it uses the -mfloat-abi and -msoft-float options), and it is
    // stripped out by the ARM target. We should probably pass this a new
    // -target-option, which is handled by the -cc1/-cc1as invocation.
    //
    // FIXME2:  For consistency, it would be ideal if we set up the target
    // machine state the same when using the frontend or the assembler. We don't
    // currently do that for the assembler, we pass the options directly to the
    // backend and never even instantiate the frontend TargetInfo. If we did,
    // and used its handleTargetFeatures hook, then we could ensure the
    // assembler and the frontend behave the same.

    // Use software floating point operations?
    if (FloatABI == "soft")
      Features.push_back("+soft-float");

    // Use software floating point argument passing?
    if (FloatABI != "hard")
      Features.push_back("+soft-float-abi");
  }

  // Honor -mfpu=.
  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
    getARMFPUFeatures(D, A, Args, Features);
  if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
    getARMHWDivFeatures(D, A, Args, Features);

  // Setting -msoft-float effectively disables NEON because of the GCC
  // implementation, although the same isn't true of VFP or VFP3.
  if (FloatABI == "soft") {
    Features.push_back("-neon");
    // Also need to explicitly disable features which imply NEON.
    Features.push_back("-crypto");
  }

  // En/disable crc
  if (Arg *A = Args.getLastArg(options::OPT_mcrc,
                               options::OPT_mnocrc)) {
    if (A->getOption().matches(options::OPT_mcrc))
      Features.push_back("+crc");
    else
      Features.push_back("-crc");
  }
}

void Clang::AddARMTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs,
                             bool KernelOrKext) const {
  const Driver &D = getToolChain().getDriver();
  // Get the effective triple, which takes into account the deployment target.
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple Triple(TripleStr);
  std::string CPUName = arm::getARMTargetCPU(Args, Triple);

  // Select the ABI to use.
  //
  // FIXME: Support -meabi.
  const char *ABIName = 0;
  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
  } else if (Triple.isOSDarwin()) {
    // The backend is hardwired to assume AAPCS for M-class processors, ensure
    // the frontend matches that.
    if (Triple.getEnvironment() == llvm::Triple::EABI ||
        Triple.getEnvironment() == llvm::Triple::MachO ||
        StringRef(CPUName).startswith("cortex-m")) {
      ABIName = "aapcs";
    } else {
      ABIName = "apcs-gnu";
    }
  } else {
    // Select the default based on the platform.
    switch(Triple.getEnvironment()) {
    case llvm::Triple::Android:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::GNUEABIHF:
      ABIName = "aapcs-linux";
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::EABI:
      ABIName = "aapcs";
      break;
    default:
      ABIName = "apcs-gnu";
    }
  }
  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName);

  // Determine floating point ABI from the options & target defaults.
  StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else if (FloatABI == "softfp") {
    // Floating point operations are hard, but argument passing is soft.
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  } else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  // Kernel code has more strict alignment requirements.
  if (KernelOrKext) {
    if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-long-calls");
    }

    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-strict-align");

    // The kext linker doesn't know how to deal with movw/movt.
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-arm-use-movt=0");
  }

  // Setting -mno-global-merge disables the codegen global merge pass. Setting 
  // -mglobal-merge has no effect as the pass is enabled by default.
  if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
                               options::OPT_mno_global_merge)) {
    if (A->getOption().matches(options::OPT_mno_global_merge))
      CmdArgs.push_back("-mno-global-merge");
  }

  if (!Args.hasFlag(options::OPT_mimplicit_float,
                    options::OPT_mno_implicit_float,
                    true))
    CmdArgs.push_back("-no-implicit-float");

    // llvm does not support reserving registers in general. There is support
    // for reserving r9 on ARM though (defined as a platform-specific register
    // in ARM EABI).
    if (Args.hasArg(options::OPT_ffixed_r9)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-reserve-r9");
    }
}

// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
static void getMipsCPUAndABI(const ArgList &Args,
                             const llvm::Triple &Triple,
                             StringRef &CPUName,
                             StringRef &ABIName) {
  const char *DefMips32CPU = "mips32r2";
  const char *DefMips64CPU = "mips64r2";

  if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
                               options::OPT_mcpu_EQ))
    CPUName = A->getValue();

  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
    ABIName = A->getValue();
    // Convert a GNU style Mips ABI name to the name
    // accepted by LLVM Mips backend.
    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
      .Case("32", "o32")
      .Case("64", "n64")
      .Default(ABIName);
  }

  // Setup default CPU and ABI names.
  if (CPUName.empty() && ABIName.empty()) {
    switch (Triple.getArch()) {
    default:
      llvm_unreachable("Unexpected triple arch name");
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
      CPUName = DefMips32CPU;
      break;
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      CPUName = DefMips64CPU;
      break;
    }
  }

  if (!ABIName.empty()) {
    // Deduce CPU name from ABI name.
    CPUName = llvm::StringSwitch<const char *>(ABIName)
      .Cases("32", "o32", "eabi", DefMips32CPU)
      .Cases("n32", "n64", "64", DefMips64CPU)
      .Default("");
  }
  else if (!CPUName.empty()) {
    // Deduce ABI name from CPU name.
    ABIName = llvm::StringSwitch<const char *>(CPUName)
      .Cases("mips32", "mips32r2", "o32")
      .Cases("mips64", "mips64r2", "n64")
      .Default("");
  }

  // FIXME: Warn on inconsistent cpu and abi usage.
}

// Convert ABI name to the GNU tools acceptable variant.
static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
  return llvm::StringSwitch<llvm::StringRef>(ABI)
    .Case("o32", "32")
    .Case("n64", "64")
    .Default(ABI);
}

// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float,
                               options::OPT_mfloat_abi_EQ)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
    else {
      FloatABI = A->getValue();
      if (FloatABI != "soft" && FloatABI != "hard") {
        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
        FloatABI = "hard";
      }
    }
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "hard", because it's a default value used by gcc.
    // When we start to recognize specific target MIPS processors,
    // we will be able to select the default more correctly.
    FloatABI = "hard";
  }

  return FloatABI;
}

static void AddTargetFeature(const ArgList &Args,
                             std::vector<const char *> &Features,
                             OptSpecifier OnOpt, OptSpecifier OffOpt,
                             StringRef FeatureName) {
  if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
    if (A->getOption().matches(OnOpt))
      Features.push_back(Args.MakeArgString("+" + FeatureName));
    else
      Features.push_back(Args.MakeArgString("-" + FeatureName));
  }
}

static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
                                  std::vector<const char *> &Features) {
  StringRef FloatABI = getMipsFloatABI(D, Args);
  if (FloatABI == "soft") {
    // FIXME: Note, this is a hack. We need to pass the selected float
    // mode to the MipsTargetInfoBase to define appropriate macros there.
    // Now it is the only method.
    Features.push_back("+soft-float");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
    if (StringRef(A->getValue()) == "2008")
      Features.push_back("+nan2008");
  }

  AddTargetFeature(Args, Features, options::OPT_msingle_float,
                   options::OPT_mdouble_float, "single-float");
  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
                   "mips16");
  AddTargetFeature(Args, Features, options::OPT_mmicromips,
                   options::OPT_mno_micromips, "micromips");
  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
                   "dsp");
  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
                   "dspr2");
  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
                   "msa");
  AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32,
                   "fp64");
}

void Clang::AddMIPSTargetArgs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();
  StringRef CPUName;
  StringRef ABIName;
  const llvm::Triple &Triple = getToolChain().getTriple();
  getMipsCPUAndABI(Args, Triple, CPUName, ABIName);

  CmdArgs.push_back("-target-abi");
  CmdArgs.push_back(ABIName.data());

  StringRef FloatABI = getMipsFloatABI(D, Args);

  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    CmdArgs.push_back("-msoft-float");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("soft");
  }
  else {
    // Floating point operations and argument passing are hard.
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mfloat-abi");
    CmdArgs.push_back("hard");
  }

  if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
    if (A->getOption().matches(options::OPT_mxgot)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mxgot");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
                               options::OPT_mno_ldc1_sdc1)) {
    if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-ldc1-sdc1");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
                               options::OPT_mno_check_zero_division)) {
    if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-mno-check-zero-division");
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_G)) {
    StringRef v = A->getValue();
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v));
    A->claim();
  }
}

/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
static std::string getPPCTargetCPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    StringRef CPUName = A->getValue();

    if (CPUName == "native") {
      std::string CPU = llvm::sys::getHostCPUName();
      if (!CPU.empty() && CPU != "generic")
        return CPU;
      else
        return "";
    }

    return llvm::StringSwitch<const char *>(CPUName)
      .Case("common", "generic")
      .Case("440", "440")
      .Case("440fp", "440")
      .Case("450", "450")
      .Case("601", "601")
      .Case("602", "602")
      .Case("603", "603")
      .Case("603e", "603e")
      .Case("603ev", "603ev")
      .Case("604", "604")
      .Case("604e", "604e")
      .Case("620", "620")
      .Case("630", "pwr3")
      .Case("G3", "g3")
      .Case("7400", "7400")
      .Case("G4", "g4")
      .Case("7450", "7450")
      .Case("G4+", "g4+")
      .Case("750", "750")
      .Case("970", "970")
      .Case("G5", "g5")
      .Case("a2", "a2")
      .Case("a2q", "a2q")
      .Case("e500mc", "e500mc")
      .Case("e5500", "e5500")
      .Case("power3", "pwr3")
      .Case("power4", "pwr4")
      .Case("power5", "pwr5")
      .Case("power5x", "pwr5x")
      .Case("power6", "pwr6")
      .Case("power6x", "pwr6x")
      .Case("power7", "pwr7")
      .Case("pwr3", "pwr3")
      .Case("pwr4", "pwr4")
      .Case("pwr5", "pwr5")
      .Case("pwr5x", "pwr5x")
      .Case("pwr6", "pwr6")
      .Case("pwr6x", "pwr6x")
      .Case("pwr7", "pwr7")
      .Case("powerpc", "ppc")
      .Case("powerpc64", "ppc64")
      .Case("powerpc64le", "ppc64le")
      .Default("");
  }

  return "";
}

static void getPPCTargetFeatures(const ArgList &Args,
                                 std::vector<const char *> &Features) {
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
    // pass the correct option to the backend while calling the frontend
    // option the same.
    // TODO: Change the LLVM backend option maybe?
    if (Name == "mfcrf")
      Name = "mfocrf";

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }

  // Altivec is a bit weird, allow overriding of the Altivec feature here.
  AddTargetFeature(Args, Features, options::OPT_faltivec,
                   options::OPT_fno_altivec, "altivec");
}

/// Get the (LLVM) name of the R600 gpu we are targeting.
static std::string getR600TargetGPU(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
    const char *GPUName = A->getValue();
    return llvm::StringSwitch<const char *>(GPUName)
      .Cases("rv630", "rv635", "r600")
      .Cases("rv610", "rv620", "rs780", "rs880")
      .Case("rv740", "rv770")
      .Case("palm", "cedar")
      .Cases("sumo", "sumo2", "sumo")
      .Case("hemlock", "cypress")
      .Case("aruba", "cayman")
      .Default(GPUName);
  }
  return "";
}

static void getSparcTargetFeatures(const ArgList &Args,
                                   std::vector<const char *> Features) {
  bool SoftFloatABI = true;
  if (Arg *A =
          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_mhard_float))
      SoftFloatABI = false;
  }
  if (SoftFloatABI)
    Features.push_back("+soft-float");
}

void Clang::AddSparcTargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // Select the float ABI as determined by -msoft-float, -mhard-float, and
  StringRef FloatABI;
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mhard_float)) {
    if (A->getOption().matches(options::OPT_msoft_float))
      FloatABI = "soft";
    else if (A->getOption().matches(options::OPT_mhard_float))
      FloatABI = "hard";
  }

  // If unspecified, choose the default based on the platform.
  if (FloatABI.empty()) {
    // Assume "soft", but warn the user we are guessing.
    FloatABI = "soft";
    D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
  }

  if (FloatABI == "soft") {
    // Floating point operations and argument passing are soft.
    //
    // FIXME: This changes CPP defines, we need -target-soft-float.
    CmdArgs.push_back("-msoft-float");
  } else {
    assert(FloatABI == "hard" && "Invalid float abi!");
    CmdArgs.push_back("-mhard-float");
  }
}

static const char *getSystemZTargetCPU(const ArgList &Args) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
    return A->getValue();
  return "z10";
}

static const char *getX86TargetCPU(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
    if (StringRef(A->getValue()) != "native") {
      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
        return "core-avx2";

      return A->getValue();
    }

    // FIXME: Reject attempts to use -march=native unless the target matches
    // the host.
    //
    // FIXME: We should also incorporate the detected target features for use
    // with -native.
    std::string CPU = llvm::sys::getHostCPUName();
    if (!CPU.empty() && CPU != "generic")
      return Args.MakeArgString(CPU);
  }

  // Select the default CPU if none was given (or detection failed).

  if (Triple.getArch() != llvm::Triple::x86_64 &&
      Triple.getArch() != llvm::Triple::x86)
    return 0; // This routine is only handling x86 targets.

  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;

  // FIXME: Need target hooks.
  if (Triple.isOSDarwin()) {
    if (Triple.getArchName() == "x86_64h")
      return "core-avx2";
    return Is64Bit ? "core2" : "yonah";
  }

  // On Android use targets compatible with gcc
  if (Triple.getEnvironment() == llvm::Triple::Android)
    return Is64Bit ? "x86-64" : "i686";

  // Everything else goes to x86-64 in 64-bit mode.
  if (Is64Bit)
    return "x86-64";

  switch (Triple.getOS()) {
  case llvm::Triple::FreeBSD:
  case llvm::Triple::NetBSD:
  case llvm::Triple::OpenBSD:
    return "i486";
  case llvm::Triple::Haiku:
    return "i586";
  case llvm::Triple::Bitrig:
    return "i686";
  default:
    // Fallback to p4.
    return "pentium4";
  }
}

static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
  switch(T.getArch()) {
  default:
    return "";

  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
    return getAArch64TargetCPU(Args, T);

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    return arm::getARMTargetCPU(Args, T);

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, T, CPUName, ABIName);
    return CPUName;
  }

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le: {
    std::string TargetCPUName = getPPCTargetCPU(Args);
    // LLVM may default to generating code for the native CPU,
    // but, like gcc, we default to a more generic option for
    // each architecture. (except on Darwin)
    if (TargetCPUName.empty() && !T.isOSDarwin()) {
      if (T.getArch() == llvm::Triple::ppc64)
        TargetCPUName = "ppc64";
      else if (T.getArch() == llvm::Triple::ppc64le)
        TargetCPUName = "ppc64le";
      else
        TargetCPUName = "ppc";
    }
    return TargetCPUName;
  }

  case llvm::Triple::sparc:
  case llvm::Triple::sparcv9:
    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
      return A->getValue();
    return "";

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    return getX86TargetCPU(Args, T);

  case llvm::Triple::hexagon:
    return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();

  case llvm::Triple::systemz:
    return getSystemZTargetCPU(Args);

  case llvm::Triple::r600:
    return getR600TargetGPU(Args);
  }
}

static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
                          ArgStringList &CmdArgs) {
  // Tell the linker to load the plugin. This has to come before AddLinkerInputs
  // as gold requires -plugin to come before any -plugin-opt that -Wl might
  // forward.
  CmdArgs.push_back("-plugin");
  std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
  CmdArgs.push_back(Args.MakeArgString(Plugin));

  // Try to pass driver level flags relevant to LTO code generation down to
  // the plugin.

  // Handle flags for selecting CPU variants.
  std::string CPU = getCPUName(Args, ToolChain.getTriple());
  if (!CPU.empty())
    CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
}

static void getX86TargetFeatures(const llvm::Triple &Triple,
                                 const ArgList &Args,
                                 std::vector<const char *> &Features) {
  if (Triple.getArchName() == "x86_64h") {
    // x86_64h implies quite a few of the more modern subtarget features
    // for Haswell class CPUs, but not all of them. Opt-out of a few.
    Features.push_back("-rdrnd");
    Features.push_back("-aes");
    Features.push_back("-pclmul");
    Features.push_back("-rtm");
    Features.push_back("-hle");
    Features.push_back("-fsgsbase");
  }

  if (Triple.getEnvironment() == llvm::Triple::Android) {
    // Add sse3 feature to comply with gcc on Android
    Features.push_back("+sse3");
  }

  // Now add any that the user explicitly requested on the command line,
  // which may override the defaults.
  for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
                    ie = Args.filtered_end();
       it != ie; ++it) {
    StringRef Name = (*it)->getOption().getName();
    (*it)->claim();

    // Skip over "-m".
    assert(Name.startswith("m") && "Invalid feature name.");
    Name = Name.substr(1);

    bool IsNegative = Name.startswith("no-");
    if (IsNegative)
      Name = Name.substr(3);

    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
  }
}

void Clang::AddX86TargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  if (!Args.hasFlag(options::OPT_mred_zone,
                    options::OPT_mno_red_zone,
                    true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-disable-red-zone");

  // Default to avoid implicit floating-point for kernel/kext code, but allow
  // that to be overridden with -mno-soft-float.
  bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
                          Args.hasArg(options::OPT_fapple_kext));
  if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
                               options::OPT_mno_soft_float,
                               options::OPT_mimplicit_float,
                               options::OPT_mno_implicit_float)) {
    const Option &O = A->getOption();
    NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
                       O.matches(options::OPT_msoft_float));
  }
  if (NoImplicitFloat)
    CmdArgs.push_back("-no-implicit-float");
}

static inline bool HasPICArg(const ArgList &Args) {
  return Args.hasArg(options::OPT_fPIC)
    || Args.hasArg(options::OPT_fpic);
}

static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) {
  return Args.getLastArg(options::OPT_G,
                         options::OPT_G_EQ,
                         options::OPT_msmall_data_threshold_EQ);
}

static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
  std::string value;
  if (HasPICArg(Args))
    value = "0";
  else if (Arg *A = GetLastSmallDataThresholdArg(Args)) {
    value = A->getValue();
    A->claim();
  }
  return value;
}

void Clang::AddHexagonTargetArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-fno-signed-char");
  CmdArgs.push_back("-mqdsp6-compat");
  CmdArgs.push_back("-Wreturn-type");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back(Args.MakeArgString(
                        "-hexagon-small-data-threshold=" + SmallDataThreshold));
  }

  if (!Args.hasArg(options::OPT_fno_short_enums))
    CmdArgs.push_back("-fshort-enums");
  if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
    CmdArgs.push_back ("-mllvm");
    CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
  }
  CmdArgs.push_back ("-mllvm");
  CmdArgs.push_back ("-machine-sink-split=0");
}

static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
                                     std::vector<const char *> &Features) {
  // Honor -mfpu=.
  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
    getAArch64FPUFeatures(D, A, Args, Features);
  else
    Features.push_back("+neon");

  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
    Features.push_back("-fp-armv8");
    Features.push_back("-crypto");
    Features.push_back("-neon");
  }
}

static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args, ArgStringList &CmdArgs,
                              bool ForAS) {
  std::vector<const char *> Features;
  switch (Triple.getArch()) {
  default:
    break;
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    getMIPSTargetFeatures(D, Args, Features);
    break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    getARMTargetFeatures(D, Triple, Args, Features, ForAS);
    break;

  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    getPPCTargetFeatures(Args, Features);
    break;
  case llvm::Triple::sparc:
    getSparcTargetFeatures(Args, Features);
    break;
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_be:
    getAArch64TargetFeatures(D, Args, Features);
    break;
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    getX86TargetFeatures(Triple, Args, Features);
    break;
  }

  // Find the last of each feature.
  llvm::StringMap<unsigned> LastOpt;
  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    const char *Name = Features[I];
    assert(Name[0] == '-' || Name[0] == '+');
    LastOpt[Name + 1] = I;
  }

  for (unsigned I = 0, N = Features.size(); I < N; ++I) {
    // If this feature was overridden, ignore it.
    const char *Name = Features[I];
    llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
    assert(LastI != LastOpt.end());
    unsigned Last = LastI->second;
    if (Last != I)
      continue;

    CmdArgs.push_back("-target-feature");
    CmdArgs.push_back(Name);
  }
}

static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
                                          const llvm::Triple &Triple) {
  // We use the zero-cost exception tables for Objective-C if the non-fragile
  // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
  // later.
  if (runtime.isNonFragile())
    return true;

  if (!Triple.isMacOSX())
    return false;

  return (!Triple.isMacOSXVersionLT(10,5) &&
          (Triple.getArch() == llvm::Triple::x86_64 ||
           Triple.getArch() == llvm::Triple::arm));
}

namespace {
  struct ExceptionSettings {
    bool ExceptionsEnabled;
    bool ShouldUseExceptionTables;
    ExceptionSettings() : ExceptionsEnabled(false),
                          ShouldUseExceptionTables(false) {}
  };
} // end anonymous namespace.

// exceptionSettings() exists to share the logic between -cc1 and linker invocations.
static ExceptionSettings exceptionSettings(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  ExceptionSettings ES;

  // Are exceptions enabled by default?
  ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);

  // This keeps track of whether exceptions were explicitly turned on or off.
  bool DidHaveExplicitExceptionFlag = false;

  if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
                               options::OPT_fno_exceptions)) {
    if (A->getOption().matches(options::OPT_fexceptions))
      ES.ExceptionsEnabled = true;
    else
      ES.ExceptionsEnabled = false;

    DidHaveExplicitExceptionFlag = true;
  }

  // Exception tables and cleanups can be enabled with -fexceptions even if the
  // language itself doesn't support exceptions.
  if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
    ES.ShouldUseExceptionTables = true;

  return ES;
}

/// addExceptionArgs - Adds exception related arguments to the driver command
/// arguments. There's a master flag, -fexceptions and also language specific
/// flags to enable/disable C++ and Objective-C exceptions.
/// This makes it possible to for example disable C++ exceptions but enable
/// Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
                             const llvm::Triple &Triple,
                             bool KernelOrKext,
                             const ObjCRuntime &objcRuntime,
                             ArgStringList &CmdArgs) {
  if (KernelOrKext) {
    // -mkernel and -fapple-kext imply no exceptions, so claim exception related
    // arguments now to avoid warnings about unused arguments.
    Args.ClaimAllArgs(options::OPT_fexceptions);
    Args.ClaimAllArgs(options::OPT_fno_exceptions);
    Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
    Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
    Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
    return;
  }

   // Gather the exception settings from the command line arguments.
   ExceptionSettings ES = exceptionSettings(Args, Triple);

  // Obj-C exceptions are enabled by default, regardless of -fexceptions. This
  // is not necessarily sensible, but follows GCC.
  if (types::isObjC(InputType) &&
      Args.hasFlag(options::OPT_fobjc_exceptions,
                   options::OPT_fno_objc_exceptions,
                   true)) {
    CmdArgs.push_back("-fobjc-exceptions");

    ES.ShouldUseExceptionTables |=
      shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
  }

  if (types::isCXX(InputType)) {
    bool CXXExceptionsEnabled = ES.ExceptionsEnabled;

    if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
                                 options::OPT_fno_cxx_exceptions,
                                 options::OPT_fexceptions,
                                 options::OPT_fno_exceptions)) {
      if (A->getOption().matches(options::OPT_fcxx_exceptions))
        CXXExceptionsEnabled = true;
      else if (A->getOption().matches(options::OPT_fno_cxx_exceptions))
        CXXExceptionsEnabled = false;
    }

    if (CXXExceptionsEnabled) {
      CmdArgs.push_back("-fcxx-exceptions");

      ES.ShouldUseExceptionTables = true;
    }
  }

  if (ES.ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");
}

static bool ShouldDisableAutolink(const ArgList &Args,
                             const ToolChain &TC) {
  bool Default = true;
  if (TC.getTriple().isOSDarwin()) {
    // The native darwin assembler doesn't support the linker_option directives,
    // so we disable them if we think the .s file will be passed to it.
    Default = TC.useIntegratedAs();
  }
  return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
                       Default);
}

static bool ShouldDisableCFI(const ArgList &Args,
                             const ToolChain &TC) {
  bool Default = true;
  if (TC.getTriple().isOSDarwin()) {
    // The native darwin assembler doesn't support cfi directives, so
    // we disable them if we think the .s file will be passed to it.
    Default = TC.useIntegratedAs();
  }
  return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
                       options::OPT_fno_dwarf2_cfi_asm,
                       Default);
}

static bool ShouldDisableDwarfDirectory(const ArgList &Args,
                                        const ToolChain &TC) {
  bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
                                        options::OPT_fno_dwarf_directory_asm,
                                        TC.useIntegratedAs());
  return !UseDwarfDirectory;
}

/// \brief Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
  if (isa<CompileJobAction>(A))
    return true;

  for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
    if (ContainsCompileAction(*it))
      return true;

  return false;
}

/// \brief Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
  bool RelaxDefault = true;

  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    RelaxDefault = A->getOption().matches(options::OPT_O0);

  if (RelaxDefault) {
    RelaxDefault = false;
    for (ActionList::const_iterator it = C.getActions().begin(),
           ie = C.getActions().end(); it != ie; ++it) {
      if (ContainsCompileAction(*it)) {
        RelaxDefault = true;
        break;
      }
    }
  }

  return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
    RelaxDefault);
}

static void CollectArgsForIntegratedAssembler(Compilation &C,
                                              const ArgList &Args,
                                              ArgStringList &CmdArgs,
                                              const Driver &D) {
    if (UseRelaxAll(C, Args))
      CmdArgs.push_back("-mrelax-all");

    // When passing -I arguments to the assembler we sometimes need to
    // unconditionally take the next argument.  For example, when parsing
    // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
    // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
    // arg after parsing the '-I' arg.
    bool TakeNextArg = false;

    // When using an integrated assembler, translate -Wa, and -Xassembler
    // options.
    for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
                                               options::OPT_Xassembler),
           ie = Args.filtered_end(); it != ie; ++it) {
      const Arg *A = *it;
      A->claim();

      for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
        StringRef Value = A->getValue(i);
        if (TakeNextArg) {
          CmdArgs.push_back(Value.data());
          TakeNextArg = false;
          continue;
        }

        if (Value == "-force_cpusubtype_ALL") {
          // Do nothing, this is the default and we don't support anything else.
        } else if (Value == "-L") {
          CmdArgs.push_back("-msave-temp-labels");
        } else if (Value == "--fatal-warnings") {
          CmdArgs.push_back("-mllvm");
          CmdArgs.push_back("-fatal-assembler-warnings");
        } else if (Value == "--noexecstack") {
          CmdArgs.push_back("-mnoexecstack");
        } else if (Value == "-compress-debug-sections" ||
                   Value == "--compress-debug-sections") {
          D.Diag(diag::warn_missing_debug_compression);
        } else if (Value.startswith("-I")) {
          CmdArgs.push_back(Value.data());
          // We need to consume the next argument if the current arg is a plain
          // -I. The next arg will be the include directory.
          if (Value == "-I")
            TakeNextArg = true;
        } else {
          D.Diag(diag::err_drv_unsupported_option_argument)
            << A->getOption().getName() << Value;
        }
      }
    }
}

// Until ARM libraries are build separately, we have them all in one library
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
  if (TC.getArch() == llvm::Triple::arm)
    return "arm";
  else
    return TC.getArchName();
}

static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
  // The runtimes are located in the OS-specific resource directory.
  SmallString<128> Res(TC.getDriver().ResourceDir);
  llvm::sys::path::append(Res, "lib", TC.getOS());
  return Res;
}

// This adds the static libclang_rt.arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
static void addClangRTLinux(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibClangRT,
      Twine("libclang_rt.") + getArchNameForCompilerRTLib(TC) + ".a");

  CmdArgs.push_back(Args.MakeArgString(LibClangRT));
  CmdArgs.push_back("-lgcc_s");
  if (TC.getDriver().CCCIsCXX())
    CmdArgs.push_back("-lgcc_eh");
}

static void addProfileRT(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
  if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
        Args.hasArg(options::OPT_fprofile_generate) ||
        Args.hasArg(options::OPT_fprofile_instr_generate) ||
        Args.hasArg(options::OPT_fcreate_profile) ||
        Args.hasArg(options::OPT_coverage)))
    return;

  SmallString<128> LibProfile = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibProfile,
      Twine("libclang_rt.profile-") + getArchNameForCompilerRTLib(TC) + ".a");

  CmdArgs.push_back(Args.MakeArgString(LibProfile));
}

static void addSanitizerRTLinkFlags(
    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
    const StringRef Sanitizer, bool BeforeLibStdCXX,
    bool ExportSymbols = true) {
  // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.a".
  SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
  llvm::sys::path::append(LibSanitizer,
                          (Twine("libclang_rt.") + Sanitizer + "-" +
                           getArchNameForCompilerRTLib(TC) + ".a"));

  // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
  // etc.) so that the linker picks custom versions of the global 'operator
  // new' and 'operator delete' symbols. We take the extreme (but simple)
  // strategy of inserting it at the front of the link command. It also
  // needs to be forced to end up in the executable, so wrap it in
  // whole-archive.
  SmallVector<const char *, 3> LibSanitizerArgs;
  LibSanitizerArgs.push_back("-whole-archive");
  LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
  LibSanitizerArgs.push_back("-no-whole-archive");

  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());

  CmdArgs.push_back("-lpthread");
  CmdArgs.push_back("-lrt");
  CmdArgs.push_back("-ldl");
  CmdArgs.push_back("-lm");

  // If possible, use a dynamic symbols file to export the symbols from the
  // runtime library. If we can't do so, use -export-dynamic instead to export
  // all symbols from the binary.
  if (ExportSymbols) {
    if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
      CmdArgs.push_back(
          Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
    else
      CmdArgs.push_back("-export-dynamic");
  }
}

/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (TC.getTriple().getEnvironment() == llvm::Triple::Android) {
    SmallString<128> LibAsan = getCompilerRTLibDir(TC);
    llvm::sys::path::append(LibAsan,
                            (Twine("libclang_rt.asan-") +
                             getArchNameForCompilerRTLib(TC) + "-android.so"));
    CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
  } else {
    if (!Args.hasArg(options::OPT_shared))
      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
  }
}

/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addTsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true);
}

/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addMsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true);
}

/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addLsanRT(const ToolChain &TC, const ArgList &Args,
                      ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
}

/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs, bool IsCXX,
                       bool HasOtherSanitizerRt) {
  // Need a copy of sanitizer_common. This could come from another sanitizer
  // runtime; if we're not including one, include our own copy.
  if (!HasOtherSanitizerRt)
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);

  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false);

  // Only include the bits of the runtime which need a C++ ABI library if
  // we're linking in C++ mode.
  if (IsCXX)
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false);
}

static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
  if (!Args.hasArg(options::OPT_shared))
    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
}

// Should be called before we add C++ ABI library.
static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
                                 ArgStringList &CmdArgs) {
  const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
  const Driver &D = TC.getDriver();
  if (Sanitize.needsUbsanRt())
    addUbsanRT(TC, Args, CmdArgs, D.CCCIsCXX(),
                    Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                    Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
  if (Sanitize.needsAsanRt())
    addAsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsTsanRt())
    addTsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsMsanRt())
    addMsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsLsanRt())
    addLsanRT(TC, Args, CmdArgs);
  if (Sanitize.needsDfsanRt())
    addDfsanRT(TC, Args, CmdArgs);
}

static bool shouldUseFramePointerForTarget(const ArgList &Args,
                                           const llvm::Triple &Triple) {
  switch (Triple.getArch()) {
  // Don't use a frame pointer on linux if optimizing for certain targets.
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::systemz:
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    if (Triple.isOSLinux())
      if (Arg *A = Args.getLastArg(options::OPT_O_Group))
        if (!A->getOption().matches(options::OPT_O0))
          return false;
    return true;
  case llvm::Triple::xcore:
    return false;
  default:
    return true;
  }
}

static bool shouldUseFramePointer(const ArgList &Args,
                                  const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
                               options::OPT_fomit_frame_pointer))
    return A->getOption().matches(options::OPT_fno_omit_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

static bool shouldUseLeafFramePointer(const ArgList &Args,
                                      const llvm::Triple &Triple) {
  if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
                               options::OPT_momit_leaf_frame_pointer))
    return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);

  return shouldUseFramePointerForTarget(Args, Triple);
}

/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
  SmallString<128> cwd;
  if (!llvm::sys::fs::current_path(cwd)) {
    CmdArgs.push_back("-fdebug-compilation-dir");
    CmdArgs.push_back(Args.MakeArgString(cwd));
  }
}

static const char *SplitDebugName(const ArgList &Args,
                                  const InputInfoList &Inputs) {
  Arg *FinalOutput = Args.getLastArg(options::OPT_o);
  if (FinalOutput && Args.hasArg(options::OPT_c)) {
    SmallString<128> T(FinalOutput->getValue());
    llvm::sys::path::replace_extension(T, "dwo");
    return Args.MakeArgString(T);
  } else {
    // Use the compilation dir.
    SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
    SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
    llvm::sys::path::replace_extension(F, "dwo");
    T += F;
    return Args.MakeArgString(F);
  }
}

static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
                           const Tool &T, const JobAction &JA,
                           const ArgList &Args, const InputInfo &Output,
                           const char *OutFile) {
  ArgStringList ExtractArgs;
  ExtractArgs.push_back("--extract-dwo");

  ArgStringList StripArgs;
  StripArgs.push_back("--strip-dwo");

  // Grabbing the output of the earlier compile step.
  StripArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(Output.getFilename());
  ExtractArgs.push_back(OutFile);

  const char *Exec =
    Args.MakeArgString(TC.GetProgramPath("objcopy"));

  // First extract the dwo sections.
  C.addCommand(new Command(JA, T, Exec, ExtractArgs));

  // Then remove them from the original .o file.
  C.addCommand(new Command(JA, T, Exec, StripArgs));
}

static bool isOptimizationLevelFast(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group))
    if (A->getOption().matches(options::OPT_Ofast))
      return true;
  return false;
}

/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4) ||
        A->getOption().matches(options::OPT_Ofast))
      return true;

    if (A->getOption().matches(options::OPT_O0))
      return false;

    assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");

    // Vectorize -Os.
    StringRef S(A->getValue());
    if (S == "s")
      return true;

    // Don't vectorize -Oz.
    if (S == "z")
      return false;

    unsigned OptLevel = 0;
    if (S.getAsInteger(10, OptLevel))
      return false;

    return OptLevel > 1;
  }

  return false;
}

/// Add -x lang to \p CmdArgs for \p Input.
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
                             ArgStringList &CmdArgs) {
  // When using -verify-pch, we don't want to provide the type
  // 'precompiled-header' if it was inferred from the file extension
  if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
    return;

  CmdArgs.push_back("-x");
  if (Args.hasArg(options::OPT_rewrite_objc))
    CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
  else
    CmdArgs.push_back(types::getTypeName(Input.getType()));
}

void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                         const InputInfo &Output,
                         const InputInfoList &Inputs,
                         const ArgList &Args,
                         const char *LinkingOutput) const {
  bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
                                  options::OPT_fapple_kext);
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");

  // Invoke ourselves in -cc1 mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  // Select the appropriate action.
  RewriteKind rewriteKind = RK_None;
  
  if (isa<AnalyzeJobAction>(JA)) {
    assert(JA.getType() == types::TY_Plist && "Invalid output type.");
    CmdArgs.push_back("-analyze");
  } else if (isa<MigrateJobAction>(JA)) {
    CmdArgs.push_back("-migrate");
  } else if (isa<PreprocessJobAction>(JA)) {
    if (Output.getType() == types::TY_Dependencies)
      CmdArgs.push_back("-Eonly");
    else {
      CmdArgs.push_back("-E");
      if (Args.hasArg(options::OPT_rewrite_objc) &&
          !Args.hasArg(options::OPT_g_Group))
        CmdArgs.push_back("-P");
    }
  } else if (isa<AssembleJobAction>(JA)) {
    CmdArgs.push_back("-emit-obj");

    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);

    // Also ignore explicit -force_cpusubtype_ALL option.
    (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
  } else if (isa<PrecompileJobAction>(JA)) {
    // Use PCH if the user requested it.
    bool UsePCH = D.CCCUsePCH;

    if (JA.getType() == types::TY_Nothing)
      CmdArgs.push_back("-fsyntax-only");
    else if (UsePCH)
      CmdArgs.push_back("-emit-pch");
    else
      CmdArgs.push_back("-emit-pth");
  } else if (isa<VerifyPCHJobAction>(JA)) {
    CmdArgs.push_back("-verify-pch");
  } else {
    assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");

    if (JA.getType() == types::TY_Nothing) {
      CmdArgs.push_back("-fsyntax-only");
    } else if (JA.getType() == types::TY_LLVM_IR ||
               JA.getType() == types::TY_LTO_IR) {
      CmdArgs.push_back("-emit-llvm");
    } else if (JA.getType() == types::TY_LLVM_BC ||
               JA.getType() == types::TY_LTO_BC) {
      CmdArgs.push_back("-emit-llvm-bc");
    } else if (JA.getType() == types::TY_PP_Asm) {
      CmdArgs.push_back("-S");
    } else if (JA.getType() == types::TY_AST) {
      CmdArgs.push_back("-emit-pch");
    } else if (JA.getType() == types::TY_ModuleFile) {
      CmdArgs.push_back("-module-file-info");
    } else if (JA.getType() == types::TY_RewrittenObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_NonFragile;
    } else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
      CmdArgs.push_back("-rewrite-objc");
      rewriteKind = RK_Fragile;
    } else {
      assert(JA.getType() == types::TY_PP_Asm &&
             "Unexpected output type!");
    }
  }

  // The make clang go fast button.
  CmdArgs.push_back("-disable-free");

  // Disable the verification pass in -asserts builds.
#ifdef NDEBUG
  CmdArgs.push_back("-disable-llvm-verifier");
#endif

  // Set the main file name, so that debug info works even with
  // -save-temps.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(getBaseInputName(Args, Inputs));

  // Some flags which affect the language (via preprocessor
  // defines).
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-static-define");

  if (isa<AnalyzeJobAction>(JA)) {
    // Enable region store model by default.
    CmdArgs.push_back("-analyzer-store=region");

    // Treat blocks as analysis entry points.
    CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");

    CmdArgs.push_back("-analyzer-eagerly-assume");

    // Add default argument set.
    if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
      CmdArgs.push_back("-analyzer-checker=core");

      if (getToolChain().getTriple().getOS() != llvm::Triple::Win32)
        CmdArgs.push_back("-analyzer-checker=unix");

      if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
        CmdArgs.push_back("-analyzer-checker=osx");
      
      CmdArgs.push_back("-analyzer-checker=deadcode");
      
      if (types::isCXX(Inputs[0].getType()))
        CmdArgs.push_back("-analyzer-checker=cplusplus");

      // Enable the following experimental checkers for testing. 
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");      
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
      CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
    }

    // Set the output format. The default is plist, for (lame) historical
    // reasons.
    CmdArgs.push_back("-analyzer-output");
    if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
      CmdArgs.push_back(A->getValue());
    else
      CmdArgs.push_back("plist");

    // Disable the presentation of standard compiler warnings when
    // using --analyze.  We only want to show static analyzer diagnostics
    // or frontend errors.
    CmdArgs.push_back("-w");

    // Add -Xanalyzer arguments when running as analyzer.
    Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
  }

  CheckCodeGenerationOptions(D, Args);

  bool PIE = getToolChain().isPIEDefault();
  bool PIC = PIE || getToolChain().isPICDefault();
  bool IsPICLevelTwo = PIC;

  // Android-specific defaults for PIC/PIE
  if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
      PIC = true; // "-fpic"
      break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      PIC = true; // "-fPIC"
      IsPICLevelTwo = true;
      break;

    default:
      break;
    }
  }

  // For the PIC and PIE flag options, this logic is different from the
  // legacy logic in very old versions of GCC, as that logic was just
  // a bug no one had ever fixed. This logic is both more rational and
  // consistent with GCC's new logic now that the bugs are fixed. The last
  // argument relating to either PIC or PIE wins, and no other argument is
  // used. If the last argument is any flavor of the '-fno-...' arguments,
  // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
  // at the same level.
  Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
                                 options::OPT_fpic, options::OPT_fno_pic,
                                 options::OPT_fPIE, options::OPT_fno_PIE,
                                 options::OPT_fpie, options::OPT_fno_pie);
  // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
  // is forced, then neither PIC nor PIE flags will have no effect.
  if (!getToolChain().isPICDefaultForced()) {
    if (LastPICArg) {
      Option O = LastPICArg->getOption();
      if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
          O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
        PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
        PIC = PIE || O.matches(options::OPT_fPIC) ||
              O.matches(options::OPT_fpic);
        IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
                        O.matches(options::OPT_fPIC);
      } else {
        PIE = PIC = false;
      }
    }
  }

  // Introduce a Darwin-specific hack. If the default is PIC but the flags
  // specified while enabling PIC enabled level 1 PIC, just force it back to
  // level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
  // informal testing).
  if (PIC && getToolChain().getTriple().isOSDarwin())
    IsPICLevelTwo |= getToolChain().isPICDefault();

  // Note that these flags are trump-cards. Regardless of the order w.r.t. the
  // PIC or PIE options above, if these show up, PIC is disabled.
  llvm::Triple Triple(TripleStr);
  if (KernelOrKext &&
      (!Triple.isiOS() || Triple.isOSVersionLT(6)))
    PIC = PIE = false;
  if (Args.hasArg(options::OPT_static))
    PIC = PIE = false;

  if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
    // This is a very special mode. It trumps the other modes, almost no one
    // uses it, and it isn't even valid on any OS but Darwin.
    if (!getToolChain().getTriple().isOSDarwin())
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();

    // FIXME: Warn when this flag trumps some other PIC or PIE flag.

    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back("dynamic-no-pic");

    // Only a forced PIC mode can cause the actual compile to have PIC defines
    // etc., no flags are sufficient. This behavior was selected to closely
    // match that of llvm-gcc and Apple GCC before that.
    if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back("2");
    }
  } else {
    // Currently, LLVM only knows about PIC vs. static; the PIE differences are
    // handled in Clang's IRGen by the -pie-level flag.
    CmdArgs.push_back("-mrelocation-model");
    CmdArgs.push_back(PIC ? "pic" : "static");

    if (PIC) {
      CmdArgs.push_back("-pic-level");
      CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      if (PIE) {
        CmdArgs.push_back("-pie-level");
        CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
      }
    }
  }

  if (!Args.hasFlag(options::OPT_fmerge_all_constants,
                    options::OPT_fno_merge_all_constants))
    CmdArgs.push_back("-fno-merge-all-constants");

  // LLVM Code Generator Options.

  if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
    CmdArgs.push_back("-mregparm");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
                               options::OPT_freg_struct_return)) {
    if (getToolChain().getArch() != llvm::Triple::x86) {
      D.Diag(diag::err_drv_unsupported_opt_for_target)
        << A->getSpelling() << getToolChain().getTriple().str();
    } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
      CmdArgs.push_back("-fpcc-struct-return");
    } else {
      assert(A->getOption().matches(options::OPT_freg_struct_return));
      CmdArgs.push_back("-freg-struct-return");
    }
  }

  if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
    CmdArgs.push_back("-mrtd");

  if (shouldUseFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-mdisable-fp-elim");
  if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
                    options::OPT_fno_zero_initialized_in_bss))
    CmdArgs.push_back("-mno-zero-initialized-in-bss");

  bool OFastEnabled = isOptimizationLevelFast(Args);
  // If -Ofast is the optimization level, then -fstrict-aliasing should be
  // enabled.  This alias option is being used to simplify the hasFlag logic.
  OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_fstrict_aliasing;
  if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
                    options::OPT_fno_strict_aliasing, true))
    CmdArgs.push_back("-relaxed-aliasing");
  if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
                    options::OPT_fno_struct_path_tbaa))
    CmdArgs.push_back("-no-struct-path-tbaa");
  if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
                   false))
    CmdArgs.push_back("-fstrict-enums");
  if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
                    options::OPT_fno_optimize_sibling_calls))
    CmdArgs.push_back("-mdisable-tail-calls");

  // Handle segmented stacks.
  if (Args.hasArg(options::OPT_fsplit_stack))
    CmdArgs.push_back("-split-stacks");

  // If -Ofast is the optimization level, then -ffast-math should be enabled.
  // This alias option is being used to simplify the getLastArg logic.
  OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
    options::OPT_ffast_math;
  
  // Handle various floating point optimization flags, mapping them to the
  // appropriate LLVM code generation flags. The pattern for all of these is to
  // default off the codegen optimizations, and if any flag enables them and no
  // flag disables them after the flag enabling them, enable the codegen
  // optimization. This is complicated by several "umbrella" flags.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_infinities,
                               options::OPT_fno_honor_infinities))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_infinities)
      CmdArgs.push_back("-menable-no-infs");
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffinite_math_only,
                               options::OPT_fno_finite_math_only,
                               options::OPT_fhonor_nans,
                               options::OPT_fno_honor_nans))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_finite_math_only &&
        A->getOption().getID() != options::OPT_fhonor_nans)
      CmdArgs.push_back("-menable-no-nans");

  // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
  bool MathErrno = getToolChain().IsMathErrnoDefault();
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_fmath_errno,
                               options::OPT_fno_math_errno)) {
    // Turning on -ffast_math (with either flag) removes the need for MathErrno.
    // However, turning *off* -ffast_math merely restores the toolchain default
    // (which may be false).
    if (A->getOption().getID() == options::OPT_fno_math_errno ||
        A->getOption().getID() == options::OPT_ffast_math ||
        A->getOption().getID() == options::OPT_Ofast)
      MathErrno = false;
    else if (A->getOption().getID() == options::OPT_fmath_errno)
      MathErrno = true;
  }
  if (MathErrno)
    CmdArgs.push_back("-fmath-errno");

  // There are several flags which require disabling very specific
  // optimizations. Any of these being disabled forces us to turn off the
  // entire set of LLVM optimizations, so collect them through all the flag
  // madness.
  bool AssociativeMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fassociative_math,
                               options::OPT_fno_associative_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_associative_math)
      AssociativeMath = true;
  bool ReciprocalMath = false;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_freciprocal_math,
                               options::OPT_fno_reciprocal_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fno_reciprocal_math)
      ReciprocalMath = true;
  bool SignedZeros = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_fsigned_zeros,
                               options::OPT_fno_signed_zeros))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_fsigned_zeros)
      SignedZeros = false;
  bool TrappingMath = true;
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_funsafe_math_optimizations,
                               options::OPT_fno_unsafe_math_optimizations,
                               options::OPT_ftrapping_math,
                               options::OPT_fno_trapping_math))
    if (A->getOption().getID() != options::OPT_fno_fast_math &&
        A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
        A->getOption().getID() != options::OPT_ftrapping_math)
      TrappingMath = false;
  if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
      !TrappingMath)
    CmdArgs.push_back("-menable-unsafe-fp-math");


  // Validate and pass through -fp-contract option. 
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math,
                               options::OPT_ffp_contract)) {
    if (A->getOption().getID() == options::OPT_ffp_contract) {
      StringRef Val = A->getValue();
      if (Val == "fast" || Val == "on" || Val == "off") {
        CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
      } else {
        D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Val;
      }
    } else if (A->getOption().matches(options::OPT_ffast_math) ||
               (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
      // If fast-math is set then set the fp-contract mode to fast.
      CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
    }
  }

  // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
  // and if we find them, tell the frontend to provide the appropriate
  // preprocessor macros. This is distinct from enabling any optimizations as
  // these options induce language changes which must survive serialization
  // and deserialization, etc.
  if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
                               options::OPT_fno_fast_math))
      if (!A->getOption().matches(options::OPT_fno_fast_math))
        CmdArgs.push_back("-ffast-math");
  if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math))
    if (A->getOption().matches(options::OPT_ffinite_math_only))
      CmdArgs.push_back("-ffinite-math-only");

  // Decide whether to use verbose asm. Verbose assembly is the default on
  // toolchains which have the integrated assembler on by default.
  bool IsIntegratedAssemblerDefault =
      getToolChain().IsIntegratedAssemblerDefault();
  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   IsIntegratedAssemblerDefault) ||
      Args.hasArg(options::OPT_dA))
    CmdArgs.push_back("-masm-verbose");

  if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
                    IsIntegratedAssemblerDefault))
    CmdArgs.push_back("-no-integrated-as");

  if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Structure");
  }
  if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
    CmdArgs.push_back("-mdebug-pass");
    CmdArgs.push_back("Arguments");
  }

  // Enable -mconstructor-aliases except on darwin, where we have to
  // work around a linker bug;  see <rdar://problem/7651567>.
  if (!getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-mconstructor-aliases");

  // Darwin's kernel doesn't support guard variables; just die if we
  // try to use them.
  if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
    CmdArgs.push_back("-fforbid-guard-variables");

  if (Args.hasArg(options::OPT_mms_bitfields)) {
    CmdArgs.push_back("-mms-bitfields");
  }

  // This is a coarse approximation of what llvm-gcc actually does, both
  // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
  // complicated ways.
  bool AsynchronousUnwindTables =
      Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
                   options::OPT_fno_asynchronous_unwind_tables,
                   (getToolChain().IsUnwindTablesDefault() ||
                    getToolChain().getSanitizerArgs().needsUnwindTables()) &&
                       !KernelOrKext);
  if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
                   AsynchronousUnwindTables))
    CmdArgs.push_back("-munwind-tables");

  getToolChain().addClangTargetOptions(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
    CmdArgs.push_back("-mlimit-float-precision");
    CmdArgs.push_back(A->getValue());
  }

  // FIXME: Handle -mtune=.
  (void) Args.hasArg(options::OPT_mtune_EQ);

  if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
    CmdArgs.push_back("-mcode-model");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target cpu
  std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
  llvm::Triple ETriple(ETripleStr);
  std::string CPU = getCPUName(Args, ETriple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
    CmdArgs.push_back("-mfpmath");
    CmdArgs.push_back(A->getValue());
  }

  // Add the target features
  getTargetFeatures(D, ETriple, Args, CmdArgs, false);

  // Add target specific flags.
  switch(getToolChain().getArch()) {
  default:
    break;

  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
    break;

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    AddMIPSTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::sparc:
    AddSparcTargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    AddX86TargetArgs(Args, CmdArgs);
    break;

  case llvm::Triple::hexagon:
    AddHexagonTargetArgs(Args, CmdArgs);
    break;
  }

  // Add clang-cl arguments.
  if (getToolChain().getDriver().IsCLMode())
    AddClangCLArgs(Args, CmdArgs);

  // 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());
  }

  if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
    CmdArgs.push_back("-momit-leaf-frame-pointer");

  // Explicitly error on some things we know we don't support and can't just
  // ignore.
  types::ID InputType = Inputs[0].getType();
  if (!Args.hasArg(options::OPT_fallow_unsupported)) {
    Arg *Unsupported;
    if (types::isCXX(InputType) &&
        getToolChain().getTriple().isOSDarwin() &&
        getToolChain().getArch() == llvm::Triple::x86) {
      if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
          (Unsupported = Args.getLastArg(options::OPT_mkernel)))
        D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
          << Unsupported->getOption().getName();
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_v);
  Args.AddLastArg(CmdArgs, options::OPT_H);
  if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-header-include-file");
    CmdArgs.push_back(D.CCPrintHeadersFilename ?
                      D.CCPrintHeadersFilename : "-");
  }
  Args.AddLastArg(CmdArgs, options::OPT_P);
  Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);

  if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
    CmdArgs.push_back("-diagnostic-log-file");
    CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
                      D.CCLogDiagnosticsFilename : "-");
  }

  // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
  // are preserved, all other debug options are substituted with "-g".
  Args.ClaimAllArgs(options::OPT_g_Group);
  if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
    if (A->getOption().matches(options::OPT_gline_tables_only)) {
      // FIXME: we should support specifying dwarf version with
      // -gline-tables-only.
      CmdArgs.push_back("-gline-tables-only");
      // Default is dwarf-2 for darwin.
      if (getToolChain().getTriple().isOSDarwin())
        CmdArgs.push_back("-gdwarf-2");
    } else if (A->getOption().matches(options::OPT_gdwarf_2))
      CmdArgs.push_back("-gdwarf-2");
    else if (A->getOption().matches(options::OPT_gdwarf_3))
      CmdArgs.push_back("-gdwarf-3");
    else if (A->getOption().matches(options::OPT_gdwarf_4))
      CmdArgs.push_back("-gdwarf-4");
    else if (!A->getOption().matches(options::OPT_g0) &&
             !A->getOption().matches(options::OPT_ggdb0)) {
      // Default is dwarf-2 for darwin.
      if (getToolChain().getTriple().isOSDarwin())
        CmdArgs.push_back("-gdwarf-2");
      else
        CmdArgs.push_back("-g");
    }
  }

  // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
  Args.ClaimAllArgs(options::OPT_g_flags_Group);
  if (Args.hasArg(options::OPT_gcolumn_info))
    CmdArgs.push_back("-dwarf-column-info");

  // FIXME: Move backend command line options to the module.
  // -gsplit-dwarf should turn on -g and enable the backend dwarf
  // splitting and extraction.
  // FIXME: Currently only works on Linux.
  if (getToolChain().getTriple().isOSLinux() &&
      Args.hasArg(options::OPT_gsplit_dwarf)) {
    CmdArgs.push_back("-g");
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-split-dwarf=Enable");
  }

  // -ggnu-pubnames turns on gnu style pubnames in the backend.
  if (Args.hasArg(options::OPT_ggnu_pubnames)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
  }

  // -gdwarf-aranges turns on the emission of the aranges section in the
  // backend.
  if (Args.hasArg(options::OPT_gdwarf_aranges)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-arange-section");
  }

  if (Args.hasFlag(options::OPT_fdebug_types_section,
                   options::OPT_fno_debug_types_section, false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-generate-type-units");
  }

  if (Args.hasFlag(options::OPT_ffunction_sections,
                   options::OPT_fno_function_sections, false)) {
    CmdArgs.push_back("-ffunction-sections");
  }

  if (Args.hasFlag(options::OPT_fdata_sections,
                   options::OPT_fno_data_sections, false)) {
    CmdArgs.push_back("-fdata-sections");
  }

  Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);

  if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
      (Args.hasArg(options::OPT_fprofile_instr_use) ||
       Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
    D.Diag(diag::err_drv_argument_not_allowed_with)
      << "-fprofile-instr-generate" << "-fprofile-instr-use";

  Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);

  if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
    A->render(Args, CmdArgs);
  else if (Args.hasArg(options::OPT_fprofile_instr_use))
    CmdArgs.push_back("-fprofile-instr-use=pgo-data");

  if (Args.hasArg(options::OPT_ftest_coverage) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-notes");
  if (Args.hasArg(options::OPT_fprofile_arcs) ||
      Args.hasArg(options::OPT_coverage))
    CmdArgs.push_back("-femit-coverage-data");

  if (C.getArgs().hasArg(options::OPT_c) ||
      C.getArgs().hasArg(options::OPT_S)) {
    if (Output.isFilename()) {
      CmdArgs.push_back("-coverage-file");
      SmallString<128> CoverageFilename(Output.getFilename());
      if (llvm::sys::path::is_relative(CoverageFilename.str())) {
        SmallString<128> Pwd;
        if (!llvm::sys::fs::current_path(Pwd)) {
          llvm::sys::path::append(Pwd, CoverageFilename.str());
          CoverageFilename.swap(Pwd);
        }
      }
      CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
    }
  }

  // Pass options for controlling the default header search paths.
  if (Args.hasArg(options::OPT_nostdinc)) {
    CmdArgs.push_back("-nostdsysteminc");
    CmdArgs.push_back("-nobuiltininc");
  } else {
    if (Args.hasArg(options::OPT_nostdlibinc))
        CmdArgs.push_back("-nostdsysteminc");
    Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
    Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
  }

  // Pass the path to compiler resource files.
  CmdArgs.push_back("-resource-dir");
  CmdArgs.push_back(D.ResourceDir.c_str());

  Args.AddLastArg(CmdArgs, options::OPT_working_directory);

  bool ARCMTEnabled = false;
  if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
    if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
                                       options::OPT_ccc_arcmt_modify,
                                       options::OPT_ccc_arcmt_migrate)) {
      ARCMTEnabled = true;
      switch (A->getOption().getID()) {
      default:
        llvm_unreachable("missed a case");
      case options::OPT_ccc_arcmt_check:
        CmdArgs.push_back("-arcmt-check");
        break;
      case options::OPT_ccc_arcmt_modify:
        CmdArgs.push_back("-arcmt-modify");
        break;
      case options::OPT_ccc_arcmt_migrate:
        CmdArgs.push_back("-arcmt-migrate");
        CmdArgs.push_back("-mt-migrate-directory");
        CmdArgs.push_back(A->getValue());

        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
        break;
      }
    }
  } else {
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
    Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
  }

  if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
    if (ARCMTEnabled) {
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-ccc-arcmt-migrate";
    }
    CmdArgs.push_back("-mt-migrate-directory");
    CmdArgs.push_back(A->getValue());

    if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
                     options::OPT_objcmt_migrate_subscripting,
                     options::OPT_objcmt_migrate_property)) {
      // None specified, means enable them all.
      CmdArgs.push_back("-objcmt-migrate-literals");
      CmdArgs.push_back("-objcmt-migrate-subscripting");
      CmdArgs.push_back("-objcmt-migrate-property");
    } else {
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
      Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    }
  } else {
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
    Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
  }

  // Add preprocessing options like -I, -D, etc. if we are using the
  // preprocessor.
  //
  // FIXME: Support -fpreprocessed
  if (types::getPreprocessedType(InputType) != types::TY_INVALID)
    AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);

  // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
  // that "The compiler can only warn and ignore the option if not recognized".
  // When building with ccache, it will pass -D options to clang even on
  // preprocessed inputs and configure concludes that -fPIC is not supported.
  Args.ClaimAllArgs(options::OPT_D);

  // Manually translate -O4 to -O3; let clang reject others.
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O4)) {
      CmdArgs.push_back("-O3");
      D.Diag(diag::warn_O4_is_O3);
    } else {
      A->render(Args, CmdArgs);
    }
  }

  // Don't warn about unused -flto.  This can happen when we're preprocessing or
  // precompiling.
  Args.ClaimAllArgs(options::OPT_flto);

  Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
  if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
    CmdArgs.push_back("-pedantic");
  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
  Args.AddLastArg(CmdArgs, options::OPT_w);

  // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
  // (-ansi is equivalent to -std=c89 or -std=c++98).
  //
  // If a std is supplied, only add -trigraphs if it follows the
  // option.
  if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
    if (Std->getOption().matches(options::OPT_ansi))
      if (types::isCXX(InputType))
        CmdArgs.push_back("-std=c++98");
      else
        CmdArgs.push_back("-std=c89");
    else
      Std->render(Args, CmdArgs);

    if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
                                 options::OPT_trigraphs))
      if (A != Std)
        A->render(Args, CmdArgs);
  } else {
    // Honor -std-default.
    //
    // FIXME: Clang doesn't correctly handle -std= when the input language
    // doesn't match. For the time being just ignore this for C++ inputs;
    // eventually we want to do all the standard defaulting here instead of
    // splitting it between the driver and clang -cc1.
    if (!types::isCXX(InputType))
      Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
                                "-std=", /*Joined=*/true);
    else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32)
      CmdArgs.push_back("-std=c++11");

    Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
  }

  // GCC's behavior for -Wwrite-strings is a bit strange:
  //  * In C, this "warning flag" changes the types of string literals from
  //    'char[N]' to 'const char[N]', and thus triggers an unrelated warning
  //    for the discarded qualifier.
  //  * In C++, this is just a normal warning flag.
  //
  // Implementing this warning correctly in C is hard, so we follow GCC's
  // behavior for now. FIXME: Directly diagnose uses of a string literal as
  // a non-const char* in C, rather than using this crude hack.
  if (!types::isCXX(InputType)) {
    // FIXME: This should behave just like a warning flag, and thus should also
    // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
    Arg *WriteStrings =
        Args.getLastArg(options::OPT_Wwrite_strings,
                        options::OPT_Wno_write_strings, options::OPT_w);
    if (WriteStrings &&
        WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
      CmdArgs.push_back("-fconst-strings");
  }

  // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
  // during C++ compilation, which it is by default. GCC keeps this define even
  // in the presence of '-w', match this behavior bug-for-bug.
  if (types::isCXX(InputType) &&
      Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated,
                   true)) {
    CmdArgs.push_back("-fdeprecated-macro");
  }

  // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
  if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
    if (Asm->getOption().matches(options::OPT_fasm))
      CmdArgs.push_back("-fgnu-keywords");
    else
      CmdArgs.push_back("-fno-gnu-keywords");
  }

  if (ShouldDisableCFI(Args, getToolChain()))
    CmdArgs.push_back("-fno-dwarf2-cfi-asm");

  if (ShouldDisableDwarfDirectory(Args, getToolChain()))
    CmdArgs.push_back("-fno-dwarf-directory-asm");

  if (ShouldDisableAutolink(Args, getToolChain()))
    CmdArgs.push_back("-fno-autolink");

  // Add in -fdebug-compilation-dir if necessary.
  addDebugCompDirArg(Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
                               options::OPT_ftemplate_depth_EQ)) {
    CmdArgs.push_back("-ftemplate-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
    CmdArgs.push_back("-foperator-arrow-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
    CmdArgs.push_back("-fconstexpr-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
    CmdArgs.push_back("-fconstexpr-steps");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
    CmdArgs.push_back("-fbracket-depth");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
                               options::OPT_Wlarge_by_value_copy_def)) {
    if (A->getNumValues()) {
      StringRef bytes = A->getValue();
      CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
    } else
      CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
  }


  if (Args.hasArg(options::OPT_relocatable_pch))
    CmdArgs.push_back("-relocatable-pch");

  if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
    CmdArgs.push_back("-fconstant-string-class");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
    CmdArgs.push_back("-ftabstop");
    CmdArgs.push_back(A->getValue());
  }

  CmdArgs.push_back("-ferror-limit");
  if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
    CmdArgs.push_back(A->getValue());
  else
    CmdArgs.push_back("19");

  if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fmacro-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
    CmdArgs.push_back("-ftemplate-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
    CmdArgs.push_back("-fconstexpr-backtrace-limit");
    CmdArgs.push_back(A->getValue());
  }

  // Pass -fmessage-length=.
  CmdArgs.push_back("-fmessage-length");
  if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
    CmdArgs.push_back(A->getValue());
  } else {
    // If -fmessage-length=N was not specified, determine whether this is a
    // terminal and, if so, implicitly define -fmessage-length appropriately.
    unsigned N = llvm::sys::Process::StandardErrColumns();
    CmdArgs.push_back(Args.MakeArgString(Twine(N)));
  }

  // -fvisibility= and -fvisibility-ms-compat are of a piece.
  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
                                     options::OPT_fvisibility_ms_compat)) {
    if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back(A->getValue());
    } else {
      assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
      CmdArgs.push_back("-fvisibility");
      CmdArgs.push_back("hidden");
      CmdArgs.push_back("-ftype-visibility");
      CmdArgs.push_back("default");
    }
  }

  Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);

  Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);

  // -fhosted is default.
  if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
      KernelOrKext)
    CmdArgs.push_back("-ffreestanding");

  // Forward -f (flag) options which we can pass directly.
  Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
  Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
  Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
  Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
  Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
  // AltiVec language extensions aren't relevant for assembling.
  if (!isa<PreprocessJobAction>(JA) || 
      Output.getType() != types::TY_PP_Asm)
    Args.AddLastArg(CmdArgs, options::OPT_faltivec);
  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
  Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);

  const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
  Sanitize.addArgs(Args, CmdArgs);

  if (!Args.hasFlag(options::OPT_fsanitize_recover,
                    options::OPT_fno_sanitize_recover,
                    true))
    CmdArgs.push_back("-fno-sanitize-recover");

  if (Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
      Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
                   options::OPT_fno_sanitize_undefined_trap_on_error, false))
    CmdArgs.push_back("-fsanitize-undefined-trap-on-error");

  // Report an error for -faltivec on anything other than PowerPC.
  if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
    if (!(getToolChain().getArch() == llvm::Triple::ppc ||
          getToolChain().getArch() == llvm::Triple::ppc64 ||
          getToolChain().getArch() == llvm::Triple::ppc64le))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "ppc/ppc64/ppc64le";

  if (getToolChain().SupportsProfiling())
    Args.AddLastArg(CmdArgs, options::OPT_pg);

  // -flax-vector-conversions is default.
  if (!Args.hasFlag(options::OPT_flax_vector_conversions,
                    options::OPT_fno_lax_vector_conversions))
    CmdArgs.push_back("-fno-lax-vector-conversions");

  if (Args.getLastArg(options::OPT_fapple_kext))
    CmdArgs.push_back("-fapple-kext");

  if (Args.hasFlag(options::OPT_frewrite_includes,
                   options::OPT_fno_rewrite_includes, false))
    CmdArgs.push_back("-frewrite-includes");

  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);

  if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
    CmdArgs.push_back("-ftrapv-handler");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);

  // -fno-strict-overflow implies -fwrapv if it isn't disabled, but
  // -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
  if (Arg *A = Args.getLastArg(options::OPT_fwrapv,
                               options::OPT_fno_wrapv)) {
    if (A->getOption().matches(options::OPT_fwrapv))
      CmdArgs.push_back("-fwrapv");
  } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
                                      options::OPT_fno_strict_overflow)) {
    if (A->getOption().matches(options::OPT_fno_strict_overflow))
      CmdArgs.push_back("-fwrapv");
  }

  if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
                               options::OPT_fno_reroll_loops))
    if (A->getOption().matches(options::OPT_freroll_loops))
      CmdArgs.push_back("-freroll-loops");

  Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
  Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
                  options::OPT_fno_unroll_loops);

  Args.AddLastArg(CmdArgs, options::OPT_pthread);


  // -stack-protector=0 is default.
  unsigned StackProtectorLevel = 0;
  if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
                               options::OPT_fstack_protector_all,
                               options::OPT_fstack_protector_strong,
                               options::OPT_fstack_protector)) {
    if (A->getOption().matches(options::OPT_fstack_protector))
      StackProtectorLevel = LangOptions::SSPOn;
    else if (A->getOption().matches(options::OPT_fstack_protector_strong))
      StackProtectorLevel = LangOptions::SSPStrong;
    else if (A->getOption().matches(options::OPT_fstack_protector_all))
      StackProtectorLevel = LangOptions::SSPReq;
  } else {
    StackProtectorLevel =
      getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
  }
  if (StackProtectorLevel) {
    CmdArgs.push_back("-stack-protector");
    CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
  }

  // --param ssp-buffer-size=
  for (arg_iterator it = Args.filtered_begin(options::OPT__param),
       ie = Args.filtered_end(); it != ie; ++it) {
    StringRef Str((*it)->getValue());
    if (Str.startswith("ssp-buffer-size=")) {
      if (StackProtectorLevel) {
        CmdArgs.push_back("-stack-protector-buffer-size");
        // FIXME: Verify the argument is a valid integer.
        CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
      }
      (*it)->claim();
    }
  }

  // Translate -mstackrealign
  if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
                   false)) {
    CmdArgs.push_back("-backend-option");
    CmdArgs.push_back("-force-align-stack");
  }
  if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
                   false)) {
    CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
  }

  if (Args.hasArg(options::OPT_mstack_alignment)) {
    StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
    CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
  }
  // -mkernel implies -mstrict-align; don't add the redundant option.
  if (!KernelOrKext) {
    if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
                                 options::OPT_munaligned_access)) {
      if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-strict-align");
      } else {
        CmdArgs.push_back("-backend-option");
        CmdArgs.push_back("-arm-no-strict-align");
      }
    }
  }

  if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
                               options::OPT_mno_restrict_it)) {
    if (A->getOption().matches(options::OPT_mrestrict_it)) {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-restrict-it");
    } else {
      CmdArgs.push_back("-backend-option");
      CmdArgs.push_back("-arm-no-restrict-it");
    }
  }

  // Forward -f options with positive and negative forms; we translate
  // these by hand.
  if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
    StringRef fname = A->getValue();
    if (!llvm::sys::fs::exists(fname))
      D.Diag(diag::err_drv_no_such_file) << fname;
    else
      A->render(Args, CmdArgs);
  }

  if (Args.hasArg(options::OPT_mkernel)) {
    if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
      CmdArgs.push_back("-fapple-kext");
    if (!Args.hasArg(options::OPT_fbuiltin))
      CmdArgs.push_back("-fno-builtin");
    Args.ClaimAllArgs(options::OPT_fno_builtin);
  }
  // -fbuiltin is default.
  else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
    CmdArgs.push_back("-fno-builtin");

  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fblocks=0 is default.
  if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
                   getToolChain().IsBlocksDefault()) ||
        (Args.hasArg(options::OPT_fgnu_runtime) &&
         Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
         !Args.hasArg(options::OPT_fno_blocks))) {
    CmdArgs.push_back("-fblocks");

    if (!Args.hasArg(options::OPT_fgnu_runtime) && 
        !getToolChain().hasBlocksRuntime())
      CmdArgs.push_back("-fblocks-runtime-optional");
  }

  // -fmodules enables modules (off by default). However, for C++/Objective-C++,
  // users must also pass -fcxx-modules. The latter flag will disappear once the
  // modules implementation is solid for C++/Objective-C++ programs as well.
  bool HaveModules = false;
  if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
    bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, 
                                     options::OPT_fno_cxx_modules, 
                                     false);
    if (AllowedInCXX || !types::isCXX(InputType)) {
      CmdArgs.push_back("-fmodules");
      HaveModules = true;
    }
  }

  // -fmodule-maps enables module map processing (off by default) for header
  // checking.  It is implied by -fmodules.
  if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
                   false)) {
    CmdArgs.push_back("-fmodule-maps");
  }

  // -fmodules-decluse checks that modules used are declared so (off by
  // default).
  if (Args.hasFlag(options::OPT_fmodules_decluse,
                   options::OPT_fno_modules_decluse,
                   false)) {
    CmdArgs.push_back("-fmodules-decluse");
  }

  // -fmodule-name specifies the module that is currently being built (or
  // used for header checking by -fmodule-maps).
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
    A->claim();
    A->render(Args, CmdArgs);
  }

  // -fmodule-map-file can be used to specify a file containing module
  // definitions.
  if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) {
    A->claim();
    A->render(Args, CmdArgs);
  }

  // If a module path was provided, pass it along. Otherwise, use a temporary
  // directory.
  if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) {
    A->claim();
    if (HaveModules) {
      A->render(Args, CmdArgs);
    }
  } else if (HaveModules) {
    SmallString<128> DefaultModuleCache;
    llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
                                           DefaultModuleCache);
    llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
    llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
    const char Arg[] = "-fmodules-cache-path=";
    DefaultModuleCache.insert(DefaultModuleCache.begin(),
                              Arg, Arg + strlen(Arg));
    CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
  }

  // Pass through all -fmodules-ignore-macro arguments.
  Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
  Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);

  Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);

  if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
    if (!Args.getLastArg(options::OPT_fbuild_session_timestamp))
      D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);

    Args.AddLastArg(CmdArgs,
                    options::OPT_fmodules_validate_once_per_build_session);
  }

  // -faccess-control is default.
  if (Args.hasFlag(options::OPT_fno_access_control,
                   options::OPT_faccess_control,
                   false))
    CmdArgs.push_back("-fno-access-control");

  // -felide-constructors is the default.
  if (Args.hasFlag(options::OPT_fno_elide_constructors,
                   options::OPT_felide_constructors,
                   false))
    CmdArgs.push_back("-fno-elide-constructors");

  // -frtti is default.
  if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
      KernelOrKext) {
    CmdArgs.push_back("-fno-rtti");

    // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
    if (Sanitize.sanitizesVptr()) {
      std::string NoRttiArg =
        Args.getLastArg(options::OPT_mkernel,
                        options::OPT_fapple_kext,
                        options::OPT_fno_rtti)->getAsString(Args);
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fsanitize=vptr" << NoRttiArg;
    }
  }

  // -fshort-enums=0 is default for all architectures except Hexagon.
  if (Args.hasFlag(options::OPT_fshort_enums,
                   options::OPT_fno_short_enums,
                   getToolChain().getArch() ==
                   llvm::Triple::hexagon))
    CmdArgs.push_back("-fshort-enums");

  // -fsigned-char is default.
  if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
                    isSignedCharDefault(getToolChain().getTriple())))
    CmdArgs.push_back("-fno-signed-char");

  // -fthreadsafe-static is default.
  if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
                    options::OPT_fno_threadsafe_statics))
    CmdArgs.push_back("-fno-threadsafe-statics");

  // -fuse-cxa-atexit is default.
  if (!Args.hasFlag(
           options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
           getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
               getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
               getToolChain().getArch() != llvm::Triple::hexagon &&
               getToolChain().getArch() != llvm::Triple::xcore) ||
      KernelOrKext)
    CmdArgs.push_back("-fno-use-cxa-atexit");

  // -fms-extensions=0 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
    CmdArgs.push_back("-fms-extensions");

  // -fms-compatibility=0 is default.
  if (Args.hasFlag(options::OPT_fms_compatibility, 
                   options::OPT_fno_ms_compatibility,
                   (getToolChain().getTriple().getOS() == llvm::Triple::Win32 &&
                    Args.hasFlag(options::OPT_fms_extensions, 
                                 options::OPT_fno_ms_extensions,
                                 true))))
    CmdArgs.push_back("-fms-compatibility");

  // -fmsc-version=1700 is default.
  if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
      Args.hasArg(options::OPT_fmsc_version)) {
    StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
    if (msc_ver.empty())
      CmdArgs.push_back("-fmsc-version=1700");
    else
      CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
  }


  // -fno-borland-extensions is default.
  if (Args.hasFlag(options::OPT_fborland_extensions,
                   options::OPT_fno_borland_extensions, false))
    CmdArgs.push_back("-fborland-extensions");

  // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
  // needs it.
  if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
                   options::OPT_fno_delayed_template_parsing,
                   getToolChain().getTriple().getOS() == llvm::Triple::Win32))
    CmdArgs.push_back("-fdelayed-template-parsing");

  // -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);

  if (Args.hasFlag(options::OPT_fgnu89_inline,
                   options::OPT_fno_gnu89_inline,
                   false))
    CmdArgs.push_back("-fgnu89-inline");

  if (Args.hasArg(options::OPT_fno_inline))
    CmdArgs.push_back("-fno-inline");

  if (Args.hasArg(options::OPT_fno_inline_functions))
    CmdArgs.push_back("-fno-inline-functions");

  ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);

  // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
  // legacy is the default. Except for deployment taget of 10.5,
  // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
  // gets ignored silently.
  if (objcRuntime.isNonFragile()) {
    if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
                      options::OPT_fno_objc_legacy_dispatch,
                      objcRuntime.isLegacyDispatchDefaultForArch(
                        getToolChain().getArch()))) {
      if (getToolChain().UseObjCMixedDispatch())
        CmdArgs.push_back("-fobjc-dispatch-method=mixed");
      else
        CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
    }
  }

  // When ObjectiveC legacy runtime is in effect on MacOSX,
  // turn on the option to do Array/Dictionary subscripting
  // by default.
  if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
      getToolChain().getTriple().isMacOSX() &&
      !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
      objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
      objcRuntime.isNeXTFamily())
    CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
  
  // -fencode-extended-block-signature=1 is default.
  if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
    CmdArgs.push_back("-fencode-extended-block-signature");
  }
  
  // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
  // NOTE: This logic is duplicated in ToolChains.cpp.
  bool ARC = isObjCAutoRefCount(Args);
  if (ARC) {
    getToolChain().CheckObjCARC();

    CmdArgs.push_back("-fobjc-arc");

    // FIXME: It seems like this entire block, and several around it should be
    // wrapped in isObjC, but for now we just use it here as this is where it
    // was being used previously.
    if (types::isCXX(InputType) && types::isObjC(InputType)) {
      if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
        CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
      else
        CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
    }

    // Allow the user to enable full exceptions code emission.
    // We define off for Objective-CC, on for Objective-C++.
    if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
                     options::OPT_fno_objc_arc_exceptions,
                     /*default*/ types::isCXX(InputType)))
      CmdArgs.push_back("-fobjc-arc-exceptions");
  }

  // -fobjc-infer-related-result-type is the default, except in the Objective-C
  // rewriter.
  if (rewriteKind != RK_None)
    CmdArgs.push_back("-fno-objc-infer-related-result-type");

  // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
  // takes precedence.
  const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
  if (!GCArg)
    GCArg = Args.getLastArg(options::OPT_fobjc_gc);
  if (GCArg) {
    if (ARC) {
      D.Diag(diag::err_drv_objc_gc_arr)
        << GCArg->getAsString(Args);
    } else if (getToolChain().SupportsObjCGC()) {
      GCArg->render(Args, CmdArgs);
    } else {
      // FIXME: We should move this to a hard error.
      D.Diag(diag::warn_drv_objc_gc_unsupported)
        << GCArg->getAsString(Args);
    }
  }

  // Add exception args.
  addExceptionArgs(Args, InputType, getToolChain().getTriple(),
                   KernelOrKext, objcRuntime, CmdArgs);

  if (getToolChain().UseSjLjExceptions())
    CmdArgs.push_back("-fsjlj-exceptions");

  // C++ "sane" operator new.
  if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
                    options::OPT_fno_assume_sane_operator_new))
    CmdArgs.push_back("-fno-assume-sane-operator-new");

  // -fconstant-cfstrings is default, and may be subject to argument translation
  // on Darwin.
  if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
                    options::OPT_fno_constant_cfstrings) ||
      !Args.hasFlag(options::OPT_mconstant_cfstrings,
                    options::OPT_mno_constant_cfstrings))
    CmdArgs.push_back("-fno-constant-cfstrings");

  // -fshort-wchar default varies depending on platform; only
  // pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
                               options::OPT_fno_short_wchar))
    A->render(Args, CmdArgs);

  // -fno-pascal-strings is default, only pass non-default.
  if (Args.hasFlag(options::OPT_fpascal_strings,
                   options::OPT_fno_pascal_strings,
                   false))
    CmdArgs.push_back("-fpascal-strings");

  // Honor -fpack-struct= and -fpack-struct, if given. Note that
  // -fno-pack-struct doesn't apply to -fpack-struct=.
  if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
    std::string PackStructStr = "-fpack-struct=";
    PackStructStr += A->getValue();
    CmdArgs.push_back(Args.MakeArgString(PackStructStr));
  } else if (Args.hasFlag(options::OPT_fpack_struct,
                          options::OPT_fno_pack_struct, false)) {
    CmdArgs.push_back("-fpack-struct=1");
  }

  if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
    if (!Args.hasArg(options::OPT_fcommon))
      CmdArgs.push_back("-fno-common");
    Args.ClaimAllArgs(options::OPT_fno_common);
  }

  // -fcommon is default, only pass non-default.
  else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
    CmdArgs.push_back("-fno-common");

  // -fsigned-bitfields is default, and clang doesn't yet support
  // -funsigned-bitfields.
  if (!Args.hasFlag(options::OPT_fsigned_bitfields,
                    options::OPT_funsigned_bitfields))
    D.Diag(diag::warn_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);

  // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
  if (!Args.hasFlag(options::OPT_ffor_scope,
                    options::OPT_fno_for_scope))
    D.Diag(diag::err_drv_clang_unsupported)
      << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);

  // -fcaret-diagnostics is default.
  if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
                    options::OPT_fno_caret_diagnostics, true))
    CmdArgs.push_back("-fno-caret-diagnostics");

  // -fdiagnostics-fixit-info is default, only pass non-default.
  if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
                    options::OPT_fno_diagnostics_fixit_info))
    CmdArgs.push_back("-fno-diagnostics-fixit-info");

  // Enable -fdiagnostics-show-option by default.
  if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
                   options::OPT_fno_diagnostics_show_option))
    CmdArgs.push_back("-fdiagnostics-show-option");

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
    CmdArgs.push_back("-fdiagnostics-show-category");
    CmdArgs.push_back(A->getValue());
  }

  if (const Arg *A =
        Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    CmdArgs.push_back(A->getValue());
  }

  if (Arg *A = Args.getLastArg(
      options::OPT_fdiagnostics_show_note_include_stack,
      options::OPT_fno_diagnostics_show_note_include_stack)) {
    if (A->getOption().matches(
        options::OPT_fdiagnostics_show_note_include_stack))
      CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
    else
      CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
  }

  // Color diagnostics are the default, unless the terminal doesn't support
  // them.
  // Support both clang's -f[no-]color-diagnostics and gcc's
  // -f[no-]diagnostics-colors[=never|always|auto].
  enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
  for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
       it != ie; ++it) {
    const Option &O = (*it)->getOption();
    if (!O.matches(options::OPT_fcolor_diagnostics) &&
        !O.matches(options::OPT_fdiagnostics_color) &&
        !O.matches(options::OPT_fno_color_diagnostics) &&
        !O.matches(options::OPT_fno_diagnostics_color) &&
        !O.matches(options::OPT_fdiagnostics_color_EQ))
      continue;

    (*it)->claim();
    if (O.matches(options::OPT_fcolor_diagnostics) ||
        O.matches(options::OPT_fdiagnostics_color)) {
      ShowColors = Colors_On;
    } else if (O.matches(options::OPT_fno_color_diagnostics) ||
               O.matches(options::OPT_fno_diagnostics_color)) {
      ShowColors = Colors_Off;
    } else {
      assert(O.matches(options::OPT_fdiagnostics_color_EQ));
      StringRef value((*it)->getValue());
      if (value == "always")
        ShowColors = Colors_On;
      else if (value == "never")
        ShowColors = Colors_Off;
      else if (value == "auto")
        ShowColors = Colors_Auto;
      else
        getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
          << ("-fdiagnostics-color=" + value).str();
    }
  }
  if (ShowColors == Colors_On ||
      (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
    CmdArgs.push_back("-fcolor-diagnostics");

  if (Args.hasArg(options::OPT_fansi_escape_codes))
    CmdArgs.push_back("-fansi-escape-codes");

  if (!Args.hasFlag(options::OPT_fshow_source_location,
                    options::OPT_fno_show_source_location))
    CmdArgs.push_back("-fno-show-source-location");

  if (!Args.hasFlag(options::OPT_fshow_column,
                    options::OPT_fno_show_column,
                    true))
    CmdArgs.push_back("-fno-show-column");

  if (!Args.hasFlag(options::OPT_fspell_checking,
                    options::OPT_fno_spell_checking))
    CmdArgs.push_back("-fno-spell-checking");


  // -fno-asm-blocks is default.
  if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
                   false))
    CmdArgs.push_back("-fasm-blocks");

  // Enable vectorization per default according to the optimization level
  // selected. For optimization levels that want vectorization we use the alias
  // option to simplify the hasFlag logic.
  bool EnableVec = shouldEnableVectorizerAtOLevel(Args);
  OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
    options::OPT_fvectorize;
  if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
                   options::OPT_fno_vectorize, EnableVec))
    CmdArgs.push_back("-vectorize-loops");

  // -fslp-vectorize is default.
  if (Args.hasFlag(options::OPT_fslp_vectorize,
                   options::OPT_fno_slp_vectorize, true))
    CmdArgs.push_back("-vectorize-slp");

  // -fno-slp-vectorize-aggressive is default.
  if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
                   options::OPT_fno_slp_vectorize_aggressive, false))
    CmdArgs.push_back("-vectorize-slp-aggressive");

  if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
    A->render(Args, CmdArgs);

  // -fdollars-in-identifiers default varies depending on platform and
  // language; only pass if specified.
  if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
                               options::OPT_fno_dollars_in_identifiers)) {
    if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
      CmdArgs.push_back("-fdollars-in-identifiers");
    else
      CmdArgs.push_back("-fno-dollars-in-identifiers");
  }

  // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
  // practical purposes.
  if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
                               options::OPT_fno_unit_at_a_time)) {
    if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
      D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
  }

  if (Args.hasFlag(options::OPT_fapple_pragma_pack,
                   options::OPT_fno_apple_pragma_pack, false))
    CmdArgs.push_back("-fapple-pragma-pack");

  // le32-specific flags: 
  //  -fno-math-builtin: clang should not convert math builtins to intrinsics
  //                     by default.
  if (getToolChain().getArch() == llvm::Triple::le32) {
    CmdArgs.push_back("-fno-math-builtin");
  }

  // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
  //
  // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
  if (getToolChain().getTriple().isOSDarwin() &&
      (getToolChain().getArch() == llvm::Triple::arm ||
       getToolChain().getArch() == llvm::Triple::thumb)) {
    if (!Args.hasArg(options::OPT_fbuiltin_strcat))
      CmdArgs.push_back("-fno-builtin-strcat");
    if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
      CmdArgs.push_back("-fno-builtin-strcpy");
  }
#endif

  // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
  if (Arg *A = Args.getLastArg(options::OPT_traditional,
                               options::OPT_traditional_cpp)) {
    if (isa<PreprocessJobAction>(JA))
      CmdArgs.push_back("-traditional-cpp");
    else
      D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
  }

  Args.AddLastArg(CmdArgs, options::OPT_dM);
  Args.AddLastArg(CmdArgs, options::OPT_dD);
  
  // Handle serialized diagnostics.
  if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
    CmdArgs.push_back("-serialize-diagnostic-file");
    CmdArgs.push_back(Args.MakeArgString(A->getValue()));
  }

  if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
    CmdArgs.push_back("-fretain-comments-from-system-headers");

  // Forward -fcomment-block-commands to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
  // Forward -fparse-all-comments to -cc1.
  Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);

  // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
  // parser.
  Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
  for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();

    // We translate this by hand to the -cc1 argument, since nightly test uses
    // it and developers have been trained to spell it with -mllvm.
    if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns")
      CmdArgs.push_back("-disable-llvm-optzns");
    else
      (*it)->render(Args, CmdArgs);
  }

  if (Output.getType() == types::TY_Dependencies) {
    // Handled with other dependency code.
  } else if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    addDashXForInput(Args, II, CmdArgs);

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      II.getInputArg().renderAsInput(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_undef);

  const char *Exec = getToolChain().getDriver().getClangProgramPath();

  // Optionally embed the -cc1 level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (ArgList::const_iterator it = Args.begin(),
           ie = Args.end(); it != ie; ++it)
      (*it)->render(Args, OriginalArgs);

    SmallString<256> Flags;
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // Add the split debug info name to the command lines here so we
  // can propagate it to the backend.
  bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
    getToolChain().getTriple().isOSLinux() &&
    (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
  const char *SplitDwarfOut;
  if (SplitDwarf) {
    CmdArgs.push_back("-split-dwarf-file");
    SplitDwarfOut = SplitDebugName(Args, Inputs);
    CmdArgs.push_back(SplitDwarfOut);
  }

  // Finally add the compile command to the compilation.
  if (Args.hasArg(options::OPT__SLASH_fallback) &&
      Output.getType() == types::TY_Object) {
    tools::visualstudio::Compile CL(getToolChain());
    Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
                                       LinkingOutput);
    C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
  } else {
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
  }


  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (SplitDwarf && !isa<CompileJobAction>(JA))
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);

  if (Arg *A = Args.getLastArg(options::OPT_pg))
    if (Args.hasArg(options::OPT_fomit_frame_pointer))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << "-fomit-frame-pointer" << A->getAsString(Args);

  // Claim some arguments which clang supports automatically.

  // -fpch-preprocess is used with gcc to add a special marker in the output to
  // include the PCH file. Clang's PTH solution is completely transparent, so we
  // do not need to deal with it at all.
  Args.ClaimAllArgs(options::OPT_fpch_preprocess);

  // Claim some arguments which clang doesn't support, but we don't
  // care to warn the user about.
  Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
  Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);

  // Disable warnings for clang -E -emit-llvm foo.c
  Args.ClaimAllArgs(options::OPT_emit_llvm);
}

/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
                                      ArgStringList &cmdArgs,
                                      RewriteKind rewriteKind) const {
  // Look for the controlling runtime option.
  Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
                                    options::OPT_fgnu_runtime,
                                    options::OPT_fobjc_runtime_EQ);

  // Just forward -fobjc-runtime= to the frontend.  This supercedes
  // options about fragility.
  if (runtimeArg &&
      runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
    ObjCRuntime runtime;
    StringRef value = runtimeArg->getValue();
    if (runtime.tryParse(value)) {
      getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
        << value;
    }

    runtimeArg->render(args, cmdArgs);
    return runtime;
  }

  // Otherwise, we'll need the ABI "version".  Version numbers are
  // slightly confusing for historical reasons:
  //   1 - Traditional "fragile" ABI
  //   2 - Non-fragile ABI, version 1
  //   3 - Non-fragile ABI, version 2
  unsigned objcABIVersion = 1;
  // If -fobjc-abi-version= is present, use that to set the version.
  if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
    StringRef value = abiArg->getValue();
    if (value == "1")
      objcABIVersion = 1;
    else if (value == "2")
      objcABIVersion = 2;
    else if (value == "3")
      objcABIVersion = 3;
    else
      getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
        << value;
  } else {
    // Otherwise, determine if we are using the non-fragile ABI.
    bool nonFragileABIIsDefault = 
      (rewriteKind == RK_NonFragile || 
       (rewriteKind == RK_None &&
        getToolChain().IsObjCNonFragileABIDefault()));
    if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
                     options::OPT_fno_objc_nonfragile_abi,
                     nonFragileABIIsDefault)) {
      // Determine the non-fragile ABI version to use.
#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
      unsigned nonFragileABIVersion = 1;
#else
      unsigned nonFragileABIVersion = 2;
#endif

      if (Arg *abiArg = args.getLastArg(
            options::OPT_fobjc_nonfragile_abi_version_EQ)) {
        StringRef value = abiArg->getValue();
        if (value == "1")
          nonFragileABIVersion = 1;
        else if (value == "2")
          nonFragileABIVersion = 2;
        else
          getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
            << value;
      }

      objcABIVersion = 1 + nonFragileABIVersion;
    } else {
      objcABIVersion = 1;
    }
  }

  // We don't actually care about the ABI version other than whether
  // it's non-fragile.
  bool isNonFragile = objcABIVersion != 1;

  // If we have no runtime argument, ask the toolchain for its default runtime.
  // However, the rewriter only really supports the Mac runtime, so assume that.
  ObjCRuntime runtime;
  if (!runtimeArg) {
    switch (rewriteKind) {
    case RK_None:
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
      break;
    case RK_Fragile:
      runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
      break;
    case RK_NonFragile:
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
      break;
    }

  // -fnext-runtime
  } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
    // On Darwin, make this use the default behavior for the toolchain.
    if (getToolChain().getTriple().isOSDarwin()) {
      runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);

    // Otherwise, build for a generic macosx port.
    } else {
      runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
    }

  // -fgnu-runtime
  } else {
    assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
    // Legacy behaviour is to target the gnustep runtime if we are i
    // non-fragile mode or the GCC runtime in fragile mode.
    if (isNonFragile)
      runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6));
    else
      runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
  }

  cmdArgs.push_back(args.MakeArgString(
                                 "-fobjc-runtime=" + runtime.getAsString()));
  return runtime;
}

void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
  unsigned RTOptionID = options::OPT__SLASH_MT;

  if (Args.hasArg(options::OPT__SLASH_LDd))
    // The /LDd option implies /MTd. The dependent lib part can be overridden,
    // but defining _DEBUG is sticky.
    RTOptionID = options::OPT__SLASH_MTd;

  if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
    RTOptionID = A->getOption().getID();

  switch(RTOptionID) {
    case options::OPT__SLASH_MD:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrt");
      break;
    case options::OPT__SLASH_MDd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("-D_DLL");
      CmdArgs.push_back("--dependent-lib=msvcrtd");
      break;
    case options::OPT__SLASH_MT:
      if (Args.hasArg(options::OPT__SLASH_LDd))
        CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmt");
      break;
    case options::OPT__SLASH_MTd:
      CmdArgs.push_back("-D_DEBUG");
      CmdArgs.push_back("-D_MT");
      CmdArgs.push_back("--dependent-lib=libcmtd");
      break;
    default:
      llvm_unreachable("Unexpected option ID.");
  }

  // This provides POSIX compatibility (maps 'open' to '_open'), which most
  // users want.  The /Za flag to cl.exe turns this off, but it's not
  // implemented in clang.
  CmdArgs.push_back("--dependent-lib=oldnames");

  if (Arg *A = Args.getLastArg(options::OPT_show_includes))
    A->render(Args, CmdArgs);

  // RTTI is currently not supported, so disable it by default.
  if (!Args.hasArg(options::OPT_frtti, options::OPT_fno_rtti))
    CmdArgs.push_back("-fno-rtti");

  const Driver &D = getToolChain().getDriver();
  Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
  Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
  if (MostGeneralArg && BestCaseArg)
    D.Diag(clang::diag::err_drv_argument_not_allowed_with)
        << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);

  if (MostGeneralArg) {
    Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
    Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
    Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);

    Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
    Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
    if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
      D.Diag(clang::diag::err_drv_argument_not_allowed_with)
          << FirstConflict->getAsString(Args)
          << SecondConflict->getAsString(Args);

    if (SingleArg)
      CmdArgs.push_back("-fms-memptr-rep=single");
    else if (MultipleArg)
      CmdArgs.push_back("-fms-memptr-rep=multiple");
    else
      CmdArgs.push_back("-fms-memptr-rep=virtual");
  }

  if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
    A->render(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
    CmdArgs.push_back("-fdiagnostics-format");
    if (Args.hasArg(options::OPT__SLASH_fallback))
      CmdArgs.push_back("msvc-fallback");
    else
      CmdArgs.push_back("msvc");
  }
}

void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
                           const InputInfo &Output,
                           const InputInfoList &Inputs,
                           const ArgList &Args,
                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Don't warn about "clang -w -c foo.s"
  Args.ClaimAllArgs(options::OPT_w);
  // and "clang -emit-llvm -c foo.s"
  Args.ClaimAllArgs(options::OPT_emit_llvm);

  // Invoke ourselves in -cc1as mode.
  //
  // FIXME: Implement custom jobs for internal actions.
  CmdArgs.push_back("-cc1as");

  // Add the "effective" target triple.
  CmdArgs.push_back("-triple");
  std::string TripleStr = 
    getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
  CmdArgs.push_back(Args.MakeArgString(TripleStr));

  // Set the output mode, we currently only expect to be used as a real
  // assembler.
  CmdArgs.push_back("-filetype");
  CmdArgs.push_back("obj");

  // Set the main file name, so that debug info works even with
  // -save-temps or preprocessed assembly.
  CmdArgs.push_back("-main-file-name");
  CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));

  // Add the target cpu
  const llvm::Triple &Triple = getToolChain().getTriple();
  std::string CPU = getCPUName(Args, Triple);
  if (!CPU.empty()) {
    CmdArgs.push_back("-target-cpu");
    CmdArgs.push_back(Args.MakeArgString(CPU));
  }

  // Add the target features
  const Driver &D = getToolChain().getDriver();
  getTargetFeatures(D, Triple, Args, CmdArgs, true);

  // Ignore explicit -force_cpusubtype_ALL option.
  (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // Forward -g and handle debug info related flags, assuming we are dealing
  // with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    Args.ClaimAllArgs(options::OPT_g_Group);
    if (Arg *A = Args.getLastArg(options::OPT_g_Group))
      if (!A->getOption().matches(options::OPT_g0))
        CmdArgs.push_back("-g");

    // Add the -fdebug-compilation-dir flag if needed.
    addDebugCompDirArg(Args, CmdArgs);

    // Set the AT_producer to the clang version when using the integrated
    // assembler on assembly source files.
    CmdArgs.push_back("-dwarf-debug-producer");
    CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
  }

  // Optionally embed the -cc1as level arguments into the debug info, for build
  // analysis.
  if (getToolChain().UseDwarfDebugFlags()) {
    ArgStringList OriginalArgs;
    for (ArgList::const_iterator it = Args.begin(),
           ie = Args.end(); it != ie; ++it)
      (*it)->render(Args, OriginalArgs);

    SmallString<256> Flags;
    const char *Exec = getToolChain().getDriver().getClangProgramPath();
    Flags += Exec;
    for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
      Flags += " ";
      Flags += OriginalArgs[i];
    }
    CmdArgs.push_back("-dwarf-debug-flags");
    CmdArgs.push_back(Args.MakeArgString(Flags.str()));
  }

  // FIXME: Add -static support, once we have it.

  // Consume all the warning flags. Usually this would be handled more
  // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
  // doesn't handle that so rather than warning about unused flags that are
  // actually used, we'll lie by omission instead.
  // FIXME: Stop lying and consume only the appropriate driver flags
  for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
                    ie = Args.filtered_end();
       it != ie; ++it)
    (*it)->claim();

  CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
                                    getToolChain().getDriver());

  Args.AddAllArgs(CmdArgs, options::OPT_mllvm);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec = getToolChain().getDriver().getClangProgramPath();
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

void gcc::Common::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;

  for (ArgList::const_iterator
         it = Args.begin(), ie = Args.end(); it != ie; ++it) {
    Arg *A = *it;
    if (forwardToGCC(A->getOption())) {
      // Don't forward any -g arguments to assembly steps.
      if (isa<AssembleJobAction>(JA) &&
          A->getOption().matches(options::OPT_g_Group))
        continue;

      // Don't forward any -W arguments to assembly and link steps.
      if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
          A->getOption().matches(options::OPT_W_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
      // to get to the assembler.
      A->claim();
      A->render(Args, CmdArgs);
    }
  }

  RenderExtraToolArgs(JA, CmdArgs);

  // If using a driver driver, force the arch.
  llvm::Triple::ArchType Arch = getToolChain().getArch();
  if (getToolChain().getTriple().isOSDarwin()) {
    CmdArgs.push_back("-arch");

    // FIXME: Remove these special cases.
    if (Arch == llvm::Triple::ppc)
      CmdArgs.push_back("ppc");
    else if (Arch == llvm::Triple::ppc64)
      CmdArgs.push_back("ppc64");
    else if (Arch == llvm::Triple::ppc64le)
      CmdArgs.push_back("ppc64le");
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
  }

  // Try to force gcc to match the tool chain we want, if we recognize
  // the arch.
  //
  // FIXME: The triple class should directly provide the information we want
  // here.
  if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
    CmdArgs.push_back("-m32");
  else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
           Arch == llvm::Triple::ppc64le)
    CmdArgs.push_back("-m64");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
        << getToolChain().getTripleString();

    if (types::canTypeBeUserSpecified(II.getType())) {
      CmdArgs.push_back("-x");
      CmdArgs.push_back(types::getTypeName(II.getType()));
    }

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else {
      const Arg &A = II.getInputArg();

      // Reverse translate some rewritten options.
      if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
        CmdArgs.push_back("-lstdc++");
        continue;
      }

      // Don't render as input, we need gcc to do the translations.
      A.render(Args, CmdArgs);
    }
  }

  const std::string customGCCName = D.getCCCGenericGCCName();
  const char *GCCName;
  if (!customGCCName.empty())
    GCCName = customGCCName.c_str();
  else if (D.CCCIsCXX()) {
    GCCName = "g++";
  } else
    GCCName = "gcc";

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
                                          ArgStringList &CmdArgs) const {
  CmdArgs.push_back("-E");
}

void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
                                       ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();

  // If -flto, etc. are present then make sure not to force assembly output.
  if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
      JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
    CmdArgs.push_back("-c");
  else {
    if (JA.getType() != types::TY_PP_Asm)
      D.Diag(diag::err_drv_invalid_gcc_output_type)
        << getTypeName(JA.getType());

    CmdArgs.push_back("-S");
  }
}

void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

// Hexagon tools start.
void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA,
                                        ArgStringList &CmdArgs) const {

}
void hexagon::Assemble::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;

  std::string MarchString = "-march=";
  MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString(MarchString));

  RenderExtraToolArgs(JA, CmdArgs);

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Unexpected output");
    CmdArgs.push_back("-fsyntax-only");
  }

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty())
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  // Only pass -x if gcc will understand it; otherwise hope gcc
  // understands the suffix correctly. The main use case this would go
  // wrong in is for linker inputs if they happened to have an odd
  // suffix; really the only way to get this to happen is a command
  // like '-x foobar a.c' which will treat a.c like a linker input.
  //
  // FIXME: For the linker case specifically, can we safely convert
  // inputs into '-Wl,' options?
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;

    // Don't try to pass LLVM or AST inputs to a generic gcc.
    if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
        II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
      D.Diag(clang::diag::err_drv_no_linker_llvm_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_AST)
      D.Diag(clang::diag::err_drv_no_ast_support)
        << getToolChain().getTripleString();
    else if (II.getType() == types::TY_ModuleFile)
      D.Diag(diag::err_drv_no_module_support)
      << getToolChain().getTripleString();

    if (II.isFilename())
      CmdArgs.push_back(II.getFilename());
    else
      // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ?
      II.getInputArg().render(Args, CmdArgs);
  }

  const char *GCCName = "hexagon-as";
  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));

}
void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
                                    ArgStringList &CmdArgs) const {
  // The types are (hopefully) good enough.
}

void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs,
                               const ArgList &Args,
                               const char *LinkingOutput) const {

  const toolchains::Hexagon_TC& ToolChain =
    static_cast<const toolchains::Hexagon_TC&>(getToolChain());
  const Driver &D = ToolChain.getDriver();

  ArgStringList CmdArgs;

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  bool hasStaticArg = Args.hasArg(options::OPT_static);
  bool buildingLib = Args.hasArg(options::OPT_shared);
  bool buildPIE = Args.hasArg(options::OPT_pie);
  bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
  bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
  bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
  bool useShared = buildingLib && !hasStaticArg;

  //----------------------------------------------------------------------------
  // Silence warnings for various options
  //----------------------------------------------------------------------------

  Args.ClaimAllArgs(options::OPT_g_Group);
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
                                     // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_static_libgcc);

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
         e = ToolChain.ExtraOpts.end();
       i != e; ++i)
    CmdArgs.push_back(i->c_str());

  std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
  CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));

  if (buildingLib) {
    CmdArgs.push_back("-shared");
    CmdArgs.push_back("-call_shared"); // should be the default, but doing as
                                       // hexagon-gcc does
  }

  if (hasStaticArg)
    CmdArgs.push_back("-static");

  if (buildPIE && !buildingLib)
    CmdArgs.push_back("-pie");

  std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
  if (!SmallDataThreshold.empty()) {
    CmdArgs.push_back(
      Args.MakeArgString(std::string("-G") + SmallDataThreshold));
  }

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  const std::string MarchSuffix = "/" + MarchString;
  const std::string G0Suffix = "/G0";
  const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
  const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir)
                              + "/";
  const std::string StartFilesDir = RootDir
                                    + "hexagon/lib"
                                    + (buildingLib
                                       ? MarchG0Suffix : MarchSuffix);

  //----------------------------------------------------------------------------
  // moslib
  //----------------------------------------------------------------------------
  std::vector<std::string> oslibs;
  bool hasStandalone= false;

  for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ),
         ie = Args.filtered_end(); it != ie; ++it) {
    (*it)->claim();
    oslibs.push_back((*it)->getValue());
    hasStandalone = hasStandalone || (oslibs.back() == "standalone");
  }
  if (oslibs.empty()) {
    oslibs.push_back("standalone");
    hasStandalone = true;
  }

  //----------------------------------------------------------------------------
  // Start Files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {

    if (!buildingLib) {
      if (hasStandalone) {
        CmdArgs.push_back(
          Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
      }
      CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
    }
    std::string initObj = useShared ? "/initS.o" : "/init.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj));
  }

  //----------------------------------------------------------------------------
  // Library Search Paths
  //----------------------------------------------------------------------------
  const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
  for (ToolChain::path_list::const_iterator
         i = LibPaths.begin(),
         e = LibPaths.end();
       i != e;
       ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));

  //----------------------------------------------------------------------------
  //
  //----------------------------------------------------------------------------
  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_u_Group);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  //----------------------------------------------------------------------------
  // Libraries
  //----------------------------------------------------------------------------
  if (incStdLib && incDefLibs) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    CmdArgs.push_back("--start-group");

    if (!buildingLib) {
      for(std::vector<std::string>::iterator i = oslibs.begin(),
            e = oslibs.end(); i != e; ++i)
        CmdArgs.push_back(Args.MakeArgString("-l" + *i));
      CmdArgs.push_back("-lc");
    }
    CmdArgs.push_back("-lgcc");

    CmdArgs.push_back("--end-group");
  }

  //----------------------------------------------------------------------------
  // End files
  //----------------------------------------------------------------------------
  if (incStdLib && incStartFiles) {
    std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
    CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
  }

  std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
  C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
}
// Hexagon tools end.

/// getARMCPUForMArch - Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting
//
// FIXME: tblgen this.
const char *arm::getARMCPUForMArch(const ArgList &Args,
                                   const llvm::Triple &Triple) {
  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();
  } else {
    // Otherwise, use the Arch from the triple.
    MArch = Triple.getArchName();
  }

  // Handle -march=native.
  if (MArch == "native") {
    std::string CPU = llvm::sys::getHostCPUName();
    if (CPU != "generic") {
      // Translate the native cpu into the architecture. The switch below will
      // then chose the minimum cpu for that arch.
      MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
    }
  }

  if (Triple.getOS() == llvm::Triple::NetBSD) {
    if (MArch == "armv6")
      return "arm1176jzf-s";
  }

  const char *result = llvm::StringSwitch<const char *>(MArch)
    .Cases("armv2", "armv2a","arm2")
    .Case("armv3", "arm6")
    .Case("armv3m", "arm7m")
    .Case("armv4", "strongarm")
    .Case("armv4t", "arm7tdmi")
    .Case("thumbv4t", "arm7tdmi")
    .Cases("armv5", "armv5t", "arm10tdmi")
    .Cases("thumbv5", "thumbv5t", "arm10tdmi")
    .Cases("armv5e", "armv5te", "arm1022e")
    .Cases("thumbv5e", "thumbv5te", "arm1022e")
    .Case("armv5tej", "arm926ej-s")
    .Case("thumbv5tej", "arm926ej-s")
    .Cases("armv6", "armv6k", "arm1136jf-s")
    .Cases("thumbv6", "thumbv6k", "arm1136jf-s")
    .Case("armv6j", "arm1136j-s")
    .Case("thumbv6j", "arm1136j-s")
    .Cases("armv6z", "armv6zk", "arm1176jzf-s")
    .Cases("thumbv6z", "thumbv6zk", "arm1176jzf-s")
    .Case("armv6t2", "arm1156t2-s")
    .Case("thumbv6t2", "arm1156t2-s")
    .Cases("armv6m", "armv6-m", "cortex-m0")
    .Case("thumbv6m", "cortex-m0")
    .Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
    .Cases("thumbv7", "thumbv7a", "cortex-a8")
    .Cases("armv7l", "armv7-l", "cortex-a8")
    .Cases("armv7s", "armv7-s", "swift")
    .Cases("armv7r", "armv7-r", "cortex-r4")
    .Case("thumbv7r", "cortex-r4")
    .Cases("armv7m", "armv7-m", "cortex-m3")
    .Case("thumbv7m", "cortex-m3")
    .Cases("armv7em", "armv7e-m", "cortex-m4")
    .Cases("thumbv7em", "thumbv7e-m", "cortex-m4")
    .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
    .Cases("thumbv8", "thumbv8a", "cortex-a53")
    .Case("ep9312", "ep9312")
    .Case("iwmmxt", "iwmmxt")
    .Case("xscale", "xscale")
    // If all else failed, return the most base CPU with thumb interworking
    // supported by LLVM.
    .Default(0);

  if (result)
    return result;

  switch (Triple.getOS()) {
  case llvm::Triple::NetBSD:
    switch (Triple.getEnvironment()) {
    case llvm::Triple::GNUEABIHF:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::EABIHF:
    case llvm::Triple::EABI:
      return "arm926ej-s";
    default:
      return "strongarm";
    }
  default:
    switch (Triple.getEnvironment()) {
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      return "arm1176jzf-s";
    default:
      return "arm7tdmi";
    }
  }
}

/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
StringRef arm::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)) {
    StringRef MCPU = A->getValue();
    // Handle -mcpu=native.
    if (MCPU == "native")
      return llvm::sys::getHostCPUName();
    else
      return MCPU;
  }

  return getARMCPUForMArch(Args, Triple);
}

/// 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!
const char *arm::getLLVMArchSuffixForARM(StringRef CPU) {
  return llvm::StringSwitch<const char *>(CPU)
    .Case("strongarm", "v4")
    .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
    .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
    .Cases("arm920", "arm920t", "arm922t", "v4t")
    .Cases("arm940t", "ep9312","v4t")
    .Cases("arm10tdmi",  "arm1020t", "v5")
    .Cases("arm9e",  "arm926ej-s",  "arm946e-s", "v5e")
    .Cases("arm966e-s",  "arm968e-s",  "arm10e", "v5e")
    .Cases("arm1020e",  "arm1022e",  "xscale", "iwmmxt", "v5e")
    .Cases("arm1136j-s",  "arm1136jf-s",  "arm1176jz-s", "v6")
    .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")
    .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")
    .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7")
    .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7")
    .Cases("cortex-r4", "cortex-r5", "v7r")
    .Case("cortex-m0", "v6m")
    .Case("cortex-m3", "v7m")
    .Case("cortex-m4", "v7em")
    .Case("swift", "v7s")
    .Cases("cortex-a53", "cortex-a57", "v8")
    .Default("");
}

bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
  return A && (A->getValue() == StringRef(Value));
}

llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
    .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
    .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
    .Case("ppc64", llvm::Triple::ppc64)
    .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
    .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
           llvm::Triple::x86)
    .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
    // This is derived from the driver driver.
    .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
    .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
    .Cases("armv7s", "xscale", llvm::Triple::arm)
    .Case("r600", llvm::Triple::r600)
    .Case("nvptx", llvm::Triple::nvptx)
    .Case("nvptx64", llvm::Triple::nvptx64)
    .Case("amdil", llvm::Triple::amdil)
    .Case("spir", llvm::Triple::spir)
    .Default(llvm::Triple::UnknownArch);
}

void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
  llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
  T.setArch(Arch);

  if (Str == "x86_64h")
    T.setArchName(Str);
  else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
    T.setOS(llvm::Triple::UnknownOS);
    T.setEnvironment(llvm::Triple::MachO);
  }
}

const char *Clang::getBaseInputName(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  return Args.MakeArgString(
    llvm::sys::path::filename(Inputs[0].getBaseInput()));
}

const char *Clang::getBaseInputStem(const ArgList &Args,
                                    const InputInfoList &Inputs) {
  const char *Str = getBaseInputName(Args, Inputs);

  if (const char *End = strrchr(Str, '.'))
    return Args.MakeArgString(std::string(Str, End));

  return Str;
}

const char *Clang::getDependencyFileName(const ArgList &Args,
                                         const InputInfoList &Inputs) {
  // FIXME: Think about this more.
  std::string Res;

  if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
    std::string Str(OutputOpt->getValue());
    Res = Str.substr(0, Str.rfind('.'));
  } else {
    Res = getBaseInputStem(Args, Inputs);
  }
  return Args.MakeArgString(Res + ".d");
}

void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // If -fno_integrated_as is used add -Q to the darwin assember driver to make
  // sure it runs its system assembler not clang's integrated assembler.
  // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
  // FIXME: at run-time detect assembler capabilities or rely on version
  // information forwarded by -target-assembler-version (future)
  if (Args.hasArg(options::OPT_fno_integrated_as)) {
    const llvm::Triple &T(getToolChain().getTriple());
    if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
      CmdArgs.push_back("-Q");
  }

  // Forward -g, assuming we are dealing with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    if (Args.hasArg(options::OPT_gstabs))
      CmdArgs.push_back("--gstabs");
    else if (Args.hasArg(options::OPT_g_Group))
      CmdArgs.push_back("-g");
  }

  // Derived from asm spec.
  AddMachOArch(Args, CmdArgs);

  // Use -force_cpusubtype_ALL on x86 by default.
  if (getToolChain().getArch() == llvm::Triple::x86 ||
      getToolChain().getArch() == llvm::Triple::x86_64 ||
      Args.hasArg(options::OPT_force__cpusubtype__ALL))
    CmdArgs.push_back("-force_cpusubtype_ALL");

  if (getToolChain().getArch() != llvm::Triple::x86_64 &&
      (((Args.hasArg(options::OPT_mkernel) ||
         Args.hasArg(options::OPT_fapple_kext)) &&
        getMachOToolChain().isKernelStatic()) ||
       Args.hasArg(options::OPT_static)))
    CmdArgs.push_back("-static");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  // asm_final spec is empty.

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::MachOTool::anchor() {}

void darwin::MachOTool::AddMachOArch(const ArgList &Args,
                                     ArgStringList &CmdArgs) const {
  StringRef ArchName = getMachOToolChain().getMachOArchName(Args);

  // Derived from darwin_arch spec.
  CmdArgs.push_back("-arch");
  CmdArgs.push_back(Args.MakeArgString(ArchName));

  // FIXME: Is this needed anymore?
  if (ArchName == "arm")
    CmdArgs.push_back("-force_cpusubtype_ALL");
}

bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
  // We only need to generate a temp path for LTO if we aren't compiling object
  // files. When compiling source files, we run 'dsymutil' after linking. We
  // don't run 'dsymutil' when compiling object files.
  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it)
    if (it->getType() != types::TY_Object)
      return true;

  return false;
}

void darwin::Link::AddLinkArgs(Compilation &C,
                               const ArgList &Args,
                               ArgStringList &CmdArgs,
                               const InputInfoList &Inputs) const {
  const Driver &D = getToolChain().getDriver();
  const toolchains::MachO &MachOTC = getMachOToolChain();

  unsigned Version[3] = { 0, 0, 0 };
  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
    bool HadExtra;
    if (!Driver::GetReleaseVersion(A->getValue(), Version[0],
                                   Version[1], Version[2], HadExtra) ||
        HadExtra)
      D.Diag(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");

  if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
    CmdArgs.push_back("-export_dynamic");

  // If we are using LTO, then automatically create a temporary file path for
  // the linker to use, so that it's lifetime will extend past a possible
  // dsymutil step.
  if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
    const char *TmpPath = C.getArgs().MakeArgString(
      D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
    C.addTempFile(TmpPath);
    CmdArgs.push_back("-object_path_lto");
    CmdArgs.push_back(TmpPath);
  }

  // Derived from the "link" spec.
  Args.AddAllArgs(CmdArgs, options::OPT_static);
  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-dynamic");
  if (Args.hasArg(options::OPT_fgnu_runtime)) {
    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
    // here. How do we wish to handle such things?
  }

  if (!Args.hasArg(options::OPT_dynamiclib)) {
    AddMachOArch(Args, CmdArgs);
    // FIXME: Why do this only on this path?
    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);

    Args.AddLastArg(CmdArgs, options::OPT_bundle);
    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
    Args.AddAllArgs(CmdArgs, options::OPT_client__name);

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
        (A = Args.getLastArg(options::OPT_current__version)) ||
        (A = Args.getLastArg(options::OPT_install__name)))
      D.Diag(diag::err_drv_argument_only_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
  } else {
    CmdArgs.push_back("-dylib");

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_bundle)) ||
        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
        (A = Args.getLastArg(options::OPT_client__name)) ||
        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
        (A = Args.getLastArg(options::OPT_private__bundle)))
      D.Diag(diag::err_drv_argument_not_allowed_with)
        << A->getAsString(Args) << "-dynamiclib";

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
                              "-dylib_compatibility_version");
    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
                              "-dylib_current_version");

    AddMachOArch(Args, CmdArgs);

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
                              "-dylib_install_name");
  }

  Args.AddLastArg(CmdArgs, options::OPT_all__load);
  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
  if (MachOTC.isTargetIOSBased())
    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
  Args.AddAllArgs(CmdArgs, options::OPT_force__load);
  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
  Args.AddAllArgs(CmdArgs, options::OPT_init);

  // Add the deployment target.
  MachOTC.addMinVersionArgs(Args, CmdArgs);

  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
  Args.AddLastArg(CmdArgs, options::OPT_single__module);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);

  if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
                                     options::OPT_fno_pie,
                                     options::OPT_fno_PIE)) {
    if (A->getOption().matches(options::OPT_fpie) ||
        A->getOption().matches(options::OPT_fPIE))
      CmdArgs.push_back("-pie");
    else
      CmdArgs.push_back("-no_pie");
  }

  Args.AddLastArg(CmdArgs, options::OPT_prebind);
  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);

  // Give --sysroot= preference, over the Apple specific behavior to also use
  // --isysroot as the syslibroot.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
  } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_y);
  Args.AddLastArg(CmdArgs, options::OPT_w);
  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
  Args.AddLastArg(CmdArgs, options::OPT_whyload);
  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
  Args.AddLastArg(CmdArgs, options::OPT_Mach);
}

void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");

  // The logic here is derived from gcc's behavior; most of which
  // comes from specs (starting with link_command). Consult gcc for
  // more information.
  ArgStringList CmdArgs;

  /// Hack(tm) to ignore linking errors when we are doing ARC migration.
  if (Args.hasArg(options::OPT_ccc_arcmt_check,
                  options::OPT_ccc_arcmt_migrate)) {
    for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I)
      (*I)->claim();
    const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("touch"));
    CmdArgs.push_back(Output.getFilename());
    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
    return;
  }

  // I'm not sure why this particular decomposition exists in gcc, but
  // we follow suite for ease of comparison.
  AddLinkArgs(C, Args, CmdArgs, Inputs);

  Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_s);
  Args.AddAllArgs(CmdArgs, options::OPT_t);
  Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
  Args.AddLastArg(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
  // members of static archive libraries which implement Objective-C classes or
  // categories.
  if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
    CmdArgs.push_back("-ObjC");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles))
    getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  if (Args.hasArg(options::OPT_fopenmp))
    // This is more complicated in gcc...
    CmdArgs.push_back("-lgomp");

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
  
  if (isObjCRuntimeLinked(Args) &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // We use arclite library for both ARC and subscripting support.
    getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);

    CmdArgs.push_back("-framework");
    CmdArgs.push_back("Foundation");
    // Link libobj.
    CmdArgs.push_back("-lobjc");
  }

  if (LinkingOutput) {
    CmdArgs.push_back("-arch_multiple");
    CmdArgs.push_back("-final_output");
    CmdArgs.push_back(LinkingOutput);
  }

  if (Args.hasArg(options::OPT_fnested_functions))
    CmdArgs.push_back("-allow_stack_execute");

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);

    // link_ssp spec is empty.

    // Let the tool chain choose which runtime library to link.
    getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    // endfile_spec is empty.
  }

  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_F);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-create");
  assert(Output.isFilename() && "Unexpected lipo output.");

  CmdArgs.push_back("-output");
  CmdArgs.push_back(Output.getFilename());

  for (InputInfoList::const_iterator
         it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    const InputInfo &II = *it;
    assert(II.isFilename() && "Unexpected lipo input.");
    CmdArgs.push_back(II.getFilename());
  }
  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected dsymutil input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("--verify");
  CmdArgs.push_back("--debug-info");
  CmdArgs.push_back("--eh-frame");
  CmdArgs.push_back("--quiet");

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected verify input");

  // Grabbing the output of the earlier dsymutil run.
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  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 solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  // FIXME: Find a real GCC, don't hard-code versions here
  std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
  const llvm::Triple &T = getToolChain().getTriple();
  std::string LibPath = "/usr/lib/";
  llvm::Triple::ArchType Arch = T.getArch();
  switch (Arch) {
  case llvm::Triple::x86:
    GCCLibPath +=
        ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
    break;
  case llvm::Triple::x86_64:
    GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
    GCCLibPath += "/4.5.2/amd64/";
    LibPath += "amd64/";
    break;
  default:
    llvm_unreachable("Unsupported architecture");
  }

  ArgStringList CmdArgs;

  // Demangle C++ names in errors
  CmdArgs.push_back("-C");

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    } else {
      CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
      CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
      CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
    }
    if (getToolChain().getDriver().CCCIsCXX())
      CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
  }

  CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);
  Args.AddAllArgs(CmdArgs, options::OPT_r);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (getToolChain().getDriver().CCCIsCXX())
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
    CmdArgs.push_back("-lgcc_s");
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-lgcc");
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
  }
  CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      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");
  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("gas"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("_start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
    CmdArgs.push_back("-dn");
  } else {
//    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("--dynamic-linker");
      CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crti.o")));
    }
    CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtn.o")));
  }

  CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
                                       + getToolChain().getTripleString()
                                       + "/4.2.4"));

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: For some reason GCC passes -lgcc before adding
    // the default system libraries. Just mimic this for now.
    CmdArgs.push_back("-lgcc");

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-pthread");
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crtend.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  bool NeedsKPIC = false;

  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    // When building 32-bit code on OpenBSD/amd64, we have to explicitly
    // instruct as in the base system to assemble 32-bit code.
    CmdArgs.push_back("--32");
    break;

  case llvm::Triple::ppc:
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
    break;

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    NeedsKPIC = true;
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
    break;

  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    NeedsKPIC = true;
    break;
  }

  default:
    break;
  }

  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);

  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 openbsd::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;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (getToolChain().getArch() == llvm::Triple::mips64)
    CmdArgs.push_back("-EB");
  else if (getToolChain().getArch() == llvm::Triple::mips64el)
    CmdArgs.push_back("-EL");

  if ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Args.hasArg(options::OPT_nopie))
    CmdArgs.push_back("-nopie");

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))  
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  std::string Triple = getToolChain().getTripleString();
  if (Triple.substr(0, 6) == "x86_64")
    Triple.replace(0, 6, "amd64");
  CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
                                       "/4.2.1"));

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg)) 
        CmdArgs.push_back("-lm_p");
      else
        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");

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lpthread_p");
      else
         CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
         CmdArgs.push_back("-lc_p");
      else
         CmdArgs.push_back("-lc");
    }

    CmdArgs.push_back("-lgcc");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                    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");
  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 bitrig::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 ((!Args.hasArg(options::OPT_nostdlib)) &&
      (!Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-e");
    CmdArgs.push_back("__start");
  }

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    CmdArgs.push_back("-Bdynamic");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-shared");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld.so");
    }
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt0.o")));
      else
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (!Args.hasArg(options::OPT_shared) &&
          Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lc_p");
      else
        CmdArgs.push_back("-lc");
    }

    StringRef MyArch;
    switch (getToolChain().getTriple().getArch()) {
    case llvm::Triple::arm:
      MyArch = "arm";
      break;
    case llvm::Triple::x86:
      MyArch = "i386";
      break;
    case llvm::Triple::x86_64:
      MyArch = "amd64";
      break;
    default:
      llvm_unreachable("Unsupported architecture");
    }
    CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");
  else if (getToolChain().getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("-a32");
  else if (getToolChain().getArch() == llvm::Triple::mips ||
           getToolChain().getArch() == llvm::Triple::mipsel ||
           getToolChain().getArch() == llvm::Triple::mips64 ||
           getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    addAssemblerKPIC(Args, CmdArgs);
  } else if (getToolChain().getArch() == llvm::Triple::arm ||
             getToolChain().getArch() == llvm::Triple::thumb) {
    const Driver &D = getToolChain().getDriver();
    llvm::Triple Triple = getToolChain().getTriple();
    StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);

    if (FloatABI == "hard") {
      CmdArgs.push_back("-mfpu=vfp");
    } else {
      CmdArgs.push_back("-mfpu=softvfp");
    }

    switch(getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::GNUEABIHF:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::EABI:
      CmdArgs.push_back("-meabi=5");
      break;

    default:
      CmdArgs.push_back("-matpcs");
    }
  } else if (getToolChain().getArch() == llvm::Triple::sparc ||
             getToolChain().getArch() == llvm::Triple::sparcv9) {
    if (getToolChain().getArch() == llvm::Triple::sparc)
      CmdArgs.push_back("-Av8plusa");
    else
      CmdArgs.push_back("-Av9a");

    addAssemblerKPIC(Args, CmdArgs);
  }

  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 freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                 const InputInfo &Output,
                                 const InputInfoList &Inputs,
                                 const ArgList &Args,
                                 const char *LinkingOutput) const {
  const toolchains::FreeBSD& ToolChain = 
    static_cast<const toolchains::FreeBSD&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (IsPIE)
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld-elf.so.1");
    }
    if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
      llvm::Triple::ArchType Arch = ToolChain.getArch();
      if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
          Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
        CmdArgs.push_back("--hash-style=both");
      }
    }
    CmdArgs.push_back("--enable-new-dtags");
  }

  // When building 32-bit code on FreeBSD/amd64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (ToolChain.getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386_fbsd");
  }

  if (ToolChain.getArch() == llvm::Triple::ppc) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32ppc_fbsd");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    const char *crt1 = NULL;
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        crt1 = "gcrt1.o";
      else if (IsPIE)
        crt1 = "Scrt1.o";
      else
        crt1 = "crt1.o";
    }
    if (crt1)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));

    const char *crtbegin = NULL;
    if (Args.hasArg(options::OPT_static))
      crtbegin = "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared) || IsPIE)
      crtbegin = "crtbeginS.o";
    else
      crtbegin = "crtbegin.o";

    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  const ToolChain::path_list Paths = ToolChain.getFilePaths();
  for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
       i != e; ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
  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);

  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lm_p");
      else
        CmdArgs.push_back("-lm");
    }
    // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
    // the default system libraries. Just mimic this for now.
    if (Args.hasArg(options::OPT_pg))
      CmdArgs.push_back("-lgcc_p");
    else
      CmdArgs.push_back("-lgcc");
    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }

    if (Args.hasArg(options::OPT_pthread)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back("-lpthread_p");
      else
        CmdArgs.push_back("-lpthread");
    }

    if (Args.hasArg(options::OPT_pg)) {
      if (Args.hasArg(options::OPT_shared))
        CmdArgs.push_back("-lc");
      else
        CmdArgs.push_back("-lc_p");
      CmdArgs.push_back("-lgcc_p");
    } else {
      CmdArgs.push_back("-lc");
      CmdArgs.push_back("-lgcc");
    }

    if (Args.hasArg(options::OPT_static)) {
      CmdArgs.push_back("-lgcc_eh");
    } else if (Args.hasArg(options::OPT_pg)) {
      CmdArgs.push_back("-lgcc_eh_p");
    } else {
      CmdArgs.push_back("--as-needed");
      CmdArgs.push_back("-lgcc_s");
      CmdArgs.push_back("--no-as-needed");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || IsPIE)
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
  }

  addProfileRT(ToolChain, Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(ToolChain.GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // GNU as needs different flags for creating the correct output format
  // on architectures with different ABIs or optional feature sets.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    CmdArgs.push_back("--32");
    break;
  case llvm::Triple::arm:
  case llvm::Triple::thumb: {
    std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
    CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
    break;
  }

  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el: {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    addAssemblerKPIC(Args, CmdArgs);
    break;
  }

  case llvm::Triple::sparc:
    CmdArgs.push_back("-32");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9");
    addAssemblerKPIC(Args, CmdArgs);
    break;

  default:
    break;  
  }

  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 netbsd::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 (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    CmdArgs.push_back("--eh-frame-hdr");
    if (Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back("-Bshareable");
    } else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/libexec/ld.elf_so");
    }
  }

  // Many NetBSD architectures support more than one ABI.
  // Determine the correct emulation for ld.
  switch (getToolChain().getArch()) {
  case llvm::Triple::x86:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
    break;
  case llvm::Triple::arm:
  case llvm::Triple::thumb:
    CmdArgs.push_back("-m");
    switch (getToolChain().getTriple().getEnvironment()) {
    case llvm::Triple::EABI:
    case llvm::Triple::GNUEABI:
      CmdArgs.push_back("armelf_nbsd_eabi");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::GNUEABIHF:
      CmdArgs.push_back("armelf_nbsd_eabihf");
      break;
    default:
      CmdArgs.push_back("armelf_nbsd");
      break;
    }
    break;
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    if (mips::hasMipsAbiArg(Args, "32")) {
      CmdArgs.push_back("-m");
      if (getToolChain().getArch() == llvm::Triple::mips64)
        CmdArgs.push_back("elf32btsmip");
      else
        CmdArgs.push_back("elf32ltsmip");
   } else if (mips::hasMipsAbiArg(Args, "64")) {
     CmdArgs.push_back("-m");
     if (getToolChain().getArch() == llvm::Triple::mips64)
       CmdArgs.push_back("elf64btsmip");
     else
       CmdArgs.push_back("elf64ltsmip");
   }
   break;

  case llvm::Triple::sparc:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf32_sparc");
    break;

  case llvm::Triple::sparcv9:
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf64_sparc");
    break;

  default:
    break;
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crt0.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
    } else {
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    }
  }

  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);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  unsigned Major, Minor, Micro;
  getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
  bool useLibgcc = true;
  if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
    switch(getToolChain().getArch()) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      useLibgcc = false;
      break;
    default:
      break;
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");

    if (useLibgcc) {
      if (Args.hasArg(options::OPT_static)) {
        // libgcc_eh depends on libc, so resolve as much as possible,
        // pull in any new requirements from libc and then get the rest
        // of libgcc.
        CmdArgs.push_back("-lgcc_eh");
        CmdArgs.push_back("-lc");
        CmdArgs.push_back("-lgcc");
      } else {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("--as-needed");
        CmdArgs.push_back("-lgcc_s");
        CmdArgs.push_back("--no-as-needed");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared))
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                  "crtend.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                 "crtendS.o")));
    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
                                                                    "crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                      const InputInfo &Output,
                                      const InputInfoList &Inputs,
                                      const ArgList &Args,
                                      const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  bool NeedsKPIC = false;

  // 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::ppc) {
    CmdArgs.push_back("-a32");
    CmdArgs.push_back("-mppc");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
    CmdArgs.push_back("-a64");
    CmdArgs.push_back("-mppc64le");
    CmdArgs.push_back("-many");
  } else if (getToolChain().getArch() == llvm::Triple::sparc) {
    CmdArgs.push_back("-32");
    CmdArgs.push_back("-Av8plusa");
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
    CmdArgs.push_back("-64");
    CmdArgs.push_back("-Av9a");
    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::arm) {
    StringRef MArch = getToolChain().getArchName();
    if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
      CmdArgs.push_back("-mfpu=neon");
    if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a")
      CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");

    StringRef ARMFloatABI = tools::arm::getARMFloatABI(
        getToolChain().getDriver(), Args, getToolChain().getTriple());
    CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));

    Args.AddLastArg(CmdArgs, options::OPT_march_EQ);

    // FIXME: remove krait check when GNU tools support krait cpu
    // for now replace it with -march=armv7-a  to avoid a lower
    // march from being picked in the absence of a cpu flag.
    Arg *A;
    if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
      StringRef(A->getValue()) == "krait")
        CmdArgs.push_back("-march=armv7-a");
    else
      Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
    Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
  } else if (getToolChain().getArch() == llvm::Triple::mips ||
             getToolChain().getArch() == llvm::Triple::mipsel ||
             getToolChain().getArch() == llvm::Triple::mips64 ||
             getToolChain().getArch() == llvm::Triple::mips64el) {
    StringRef CPUName;
    StringRef ABIName;
    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);

    CmdArgs.push_back("-march");
    CmdArgs.push_back(CPUName.data());

    CmdArgs.push_back("-mabi");
    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());

    if (getToolChain().getArch() == llvm::Triple::mips ||
        getToolChain().getArch() == llvm::Triple::mips64)
      CmdArgs.push_back("-EB");
    else
      CmdArgs.push_back("-EL");

    if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
      if (StringRef(A->getValue()) == "2008")
        CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
    }

    Args.AddLastArg(CmdArgs, options::OPT_mfp32, options::OPT_mfp64);
    Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16);
    Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
                    options::OPT_mno_micromips);
    Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
    Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);

    if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
      // Do not use AddLastArg because not all versions of MIPS assembler
      // support -mmsa / -mno-msa options.
      if (A->getOption().matches(options::OPT_mmsa))
        CmdArgs.push_back(Args.MakeArgString("-mmsa"));
    }

    NeedsKPIC = true;
  } else if (getToolChain().getArch() == llvm::Triple::systemz) {
    // Always pass an -march option, since our default of z10 is later
    // than the GNU assembler's default.
    StringRef CPUName = getSystemZTargetCPU(Args);
    CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
  }

  if (NeedsKPIC)
    addAssemblerKPIC(Args, CmdArgs);

  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));

  // Handle the debug info splitting at object creation time if we're
  // creating an object.
  // TODO: Currently only works on linux with newer objcopy.
  if (Args.hasArg(options::OPT_gsplit_dwarf) &&
      getToolChain().getTriple().isOSLinux())
    SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
                   SplitDebugName(Args, Inputs));
}

static void AddLibgcc(llvm::Triple Triple, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
  bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
                      Args.hasArg(options::OPT_static);
  if (!D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  if (StaticLibgcc || isAndroid) {
    if (D.CCCIsCXX())
      CmdArgs.push_back("-lgcc");
  } else {
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--as-needed");
    CmdArgs.push_back("-lgcc_s");
    if (!D.CCCIsCXX())
      CmdArgs.push_back("--no-as-needed");
  }

  if (StaticLibgcc && !isAndroid)
    CmdArgs.push_back("-lgcc_eh");
  else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
    CmdArgs.push_back("-lgcc");

  // According to Android ABI, we have to link with libdl if we are
  // linking with non-static libgcc.
  //
  // NOTE: This fixes a link error on Android MIPS as well.  The non-static
  // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
  if (isAndroid && !StaticLibgcc)
    CmdArgs.push_back("-ldl");
}

static StringRef getLinuxDynamicLinker(const ArgList &Args,
                                       const toolchains::Linux &ToolChain) {
  if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
    if (ToolChain.getTriple().isArch64Bit())
      return "/system/bin/linker64";
    else
      return "/system/bin/linker";
  } else if (ToolChain.getArch() == llvm::Triple::x86 ||
             ToolChain.getArch() == llvm::Triple::sparc)
    return "/lib/ld-linux.so.2";
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    return "/lib/ld-linux-aarch64.so.1";
  else if (ToolChain.getArch() == llvm::Triple::arm ||
           ToolChain.getArch() == llvm::Triple::thumb) {
    if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
      return "/lib/ld-linux-armhf.so.3";
    else
      return "/lib/ld-linux.so.3";
  } else if (ToolChain.getArch() == llvm::Triple::mips ||
             ToolChain.getArch() == llvm::Triple::mipsel)
    return "/lib/ld.so.1";
  else if (ToolChain.getArch() == llvm::Triple::mips64 ||
           ToolChain.getArch() == llvm::Triple::mips64el) {
    if (mips::hasMipsAbiArg(Args, "n32"))
      return "/lib32/ld.so.1";
    else
      return "/lib64/ld.so.1";
  } else if (ToolChain.getArch() == llvm::Triple::ppc)
    return "/lib/ld.so.1";
  else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
           ToolChain.getArch() == llvm::Triple::ppc64le ||
           ToolChain.getArch() == llvm::Triple::systemz)
    return "/lib64/ld64.so.1";
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    return "/lib64/ld-linux.so.2";
  else
    return "/lib64/ld-linux-x86-64.so.2";
}

static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
                      ArgStringList &CmdArgs, const ArgList &Args) {
  // Make use of compiler-rt if --rtlib option is used
  ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);

  switch(RLT) {
  case ToolChain::RLT_CompilerRT:
    addClangRTLinux(TC, Args, CmdArgs);
    break;
  case ToolChain::RLT_Libgcc:
    AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
    break;
  }
}

void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  const toolchains::Linux& ToolChain =
    static_cast<const toolchains::Linux&>(getToolChain());
  const Driver &D = ToolChain.getDriver();
  const bool isAndroid =
    ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
  const bool IsPIE =
    !Args.hasArg(options::OPT_shared) &&
    (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());

  ArgStringList CmdArgs;

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  if (IsPIE)
    CmdArgs.push_back("-pie");

  if (Args.hasArg(options::OPT_rdynamic))
    CmdArgs.push_back("-export-dynamic");

  if (Args.hasArg(options::OPT_s))
    CmdArgs.push_back("-s");

  for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(),
         e = ToolChain.ExtraOpts.end();
       i != e; ++i)
    CmdArgs.push_back(i->c_str());

  if (!Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("--eh-frame-hdr");
  }

  CmdArgs.push_back("-m");
  if (ToolChain.getArch() == llvm::Triple::x86)
    CmdArgs.push_back("elf_i386");
  else if (ToolChain.getArch() == llvm::Triple::aarch64)
    CmdArgs.push_back("aarch64linux");
  else if (ToolChain.getArch() == llvm::Triple::arm
           ||  ToolChain.getArch() == llvm::Triple::thumb)
    CmdArgs.push_back("armelf_linux_eabi");
  else if (ToolChain.getArch() == llvm::Triple::ppc)
    CmdArgs.push_back("elf32ppclinux");
  else if (ToolChain.getArch() == llvm::Triple::ppc64)
    CmdArgs.push_back("elf64ppc");
  else if (ToolChain.getArch() == llvm::Triple::sparc)
    CmdArgs.push_back("elf32_sparc");
  else if (ToolChain.getArch() == llvm::Triple::sparcv9)
    CmdArgs.push_back("elf64_sparc");
  else if (ToolChain.getArch() == llvm::Triple::mips)
    CmdArgs.push_back("elf32btsmip");
  else if (ToolChain.getArch() == llvm::Triple::mipsel)
    CmdArgs.push_back("elf32ltsmip");
  else if (ToolChain.getArch() == llvm::Triple::mips64) {
    if (mips::hasMipsAbiArg(Args, "n32"))
      CmdArgs.push_back("elf32btsmipn32");
    else
      CmdArgs.push_back("elf64btsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::mips64el) {
    if (mips::hasMipsAbiArg(Args, "n32"))
      CmdArgs.push_back("elf32ltsmipn32");
    else
      CmdArgs.push_back("elf64ltsmip");
  }
  else if (ToolChain.getArch() == llvm::Triple::systemz)
    CmdArgs.push_back("elf64_s390");
  else
    CmdArgs.push_back("elf_x86_64");

  if (Args.hasArg(options::OPT_static)) {
    if (ToolChain.getArch() == llvm::Triple::arm ||
        ToolChain.getArch() == llvm::Triple::thumb)
      CmdArgs.push_back("-Bstatic");
    else
      CmdArgs.push_back("-static");
  } else if (Args.hasArg(options::OPT_shared)) {
    CmdArgs.push_back("-shared");
    if (isAndroid) {
      CmdArgs.push_back("-Bsymbolic");
    }
  }

  if (ToolChain.getArch() == llvm::Triple::arm ||
      ToolChain.getArch() == llvm::Triple::thumb ||
      (!Args.hasArg(options::OPT_static) &&
       !Args.hasArg(options::OPT_shared))) {
    CmdArgs.push_back("-dynamic-linker");
    CmdArgs.push_back(Args.MakeArgString(
        D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
  }

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!isAndroid) {
      const char *crt1 = NULL;
      if (!Args.hasArg(options::OPT_shared)){
        if (Args.hasArg(options::OPT_pg))
          crt1 = "gcrt1.o";
        else if (IsPIE)
          crt1 = "Scrt1.o";
        else
          crt1 = "crt1.o";
      }
      if (crt1)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
    }

    const char *crtbegin;
    if (Args.hasArg(options::OPT_static))
      crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
    else if (Args.hasArg(options::OPT_shared))
      crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
    else if (IsPIE)
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
    else
      crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));

    // Add crtfastmath.o if available and fast math is enabled.
    ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  const ToolChain::path_list Paths = ToolChain.getFilePaths();

  for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
       i != e; ++i)
    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));

  if (D.IsUsingLTO(Args))
    AddGoldPlugin(ToolChain, Args, CmdArgs);

  if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("--no-demangle");

  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);

  addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
  // The profile runtime also needs access to system libraries.
  addProfileRT(getToolChain(), Args, CmdArgs);

  if (D.CCCIsCXX() &&
      !Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
      !Args.hasArg(options::OPT_static);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bstatic");
    ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
    if (OnlyLibstdcxxStatic)
      CmdArgs.push_back("-Bdynamic");
    CmdArgs.push_back("-lm");
  }

  if (!Args.hasArg(options::OPT_nostdlib)) {
    if (!Args.hasArg(options::OPT_nodefaultlibs)) {
      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--start-group");

      bool OpenMP = Args.hasArg(options::OPT_fopenmp);
      if (OpenMP) {
        CmdArgs.push_back("-lgomp");

        // FIXME: Exclude this for platforms with libgomp that don't require
        // librt. Most modern Linux platforms require it, but some may not.
        CmdArgs.push_back("-lrt");
      }

      AddRunTimeLibs(ToolChain, D, CmdArgs, Args);

      if (Args.hasArg(options::OPT_pthread) ||
          Args.hasArg(options::OPT_pthreads) || OpenMP)
        CmdArgs.push_back("-lpthread");

      CmdArgs.push_back("-lc");

      if (Args.hasArg(options::OPT_static))
        CmdArgs.push_back("--end-group");
      else
        AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
    }

    if (!Args.hasArg(options::OPT_nostartfiles)) {
      const char *crtend;
      if (Args.hasArg(options::OPT_shared))
        crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
      else if (IsPIE)
        crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
      else
        crtend = isAndroid ? "crtend_android.o" : "crtend.o";

      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
      if (!isAndroid)
        CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
    }
  }

  C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}

void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                   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");
  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::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("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  addProfileRT(getToolChain(), Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");
    CmdArgs.push_back("-lc");
    CmdArgs.push_back("-lCompilerRT-Generic");
    CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
    CmdArgs.push_back(
         Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

/// DragonFly Tools

// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct as in the base system to assemble 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86)
    CmdArgs.push_back("--32");

  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 dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  bool UseGCC47 = false;
  const Driver &D = getToolChain().getDriver();
  ArgStringList CmdArgs;

  if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47))
    UseGCC47 = false;

  if (!D.SysRoot.empty())
    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));

  CmdArgs.push_back("--eh-frame-hdr");
  if (Args.hasArg(options::OPT_static)) {
    CmdArgs.push_back("-Bstatic");
  } else {
    if (Args.hasArg(options::OPT_rdynamic))
      CmdArgs.push_back("-export-dynamic");
    if (Args.hasArg(options::OPT_shared))
      CmdArgs.push_back("-Bshareable");
    else {
      CmdArgs.push_back("-dynamic-linker");
      CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
    }
    CmdArgs.push_back("--hash-style=both");
  }

  // When building 32-bit code on DragonFly/pc64, we have to explicitly
  // instruct ld in the base system to link 32-bit code.
  if (getToolChain().getArch() == llvm::Triple::x86) {
    CmdArgs.push_back("-m");
    CmdArgs.push_back("elf_i386");
  }

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (!Args.hasArg(options::OPT_shared)) {
      if (Args.hasArg(options::OPT_pg))
        CmdArgs.push_back(Args.MakeArgString(
                                getToolChain().GetFilePath("gcrt1.o")));
      else {
        if (Args.hasArg(options::OPT_pie))
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("Scrt1.o")));
        else
          CmdArgs.push_back(Args.MakeArgString(
                                  getToolChain().GetFilePath("crt1.o")));
      }
    }
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crti.o")));
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbeginS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtbegin.o")));
  }

  Args.AddAllArgs(CmdArgs, options::OPT_L);
  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_e);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nodefaultlibs)) {
    // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
    //         rpaths
    if (UseGCC47)
      CmdArgs.push_back("-L/usr/lib/gcc47");
    else
      CmdArgs.push_back("-L/usr/lib/gcc44");

    if (!Args.hasArg(options::OPT_static)) {
      if (UseGCC47) {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc47");
      } else {
        CmdArgs.push_back("-rpath");
        CmdArgs.push_back("/usr/lib/gcc44");
      }
    }

    if (D.CCCIsCXX()) {
      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
      CmdArgs.push_back("-lm");
    }

    if (Args.hasArg(options::OPT_pthread))
      CmdArgs.push_back("-lpthread");

    if (!Args.hasArg(options::OPT_nolibc)) {
      CmdArgs.push_back("-lc");
    }

    if (UseGCC47) {
      if (Args.hasArg(options::OPT_static) ||
          Args.hasArg(options::OPT_static_libgcc)) {
        CmdArgs.push_back("-lgcc");
        CmdArgs.push_back("-lgcc_eh");
      } else {
        if (Args.hasArg(options::OPT_shared_libgcc)) {
          CmdArgs.push_back("-lgcc_pic");
          if (!Args.hasArg(options::OPT_shared))
            CmdArgs.push_back("-lgcc");
        } else {
          CmdArgs.push_back("-lgcc");
          CmdArgs.push_back("--as-needed");
          CmdArgs.push_back("-lgcc_pic");
          CmdArgs.push_back("--no-as-needed");
        }
      }
    } else {
      if (Args.hasArg(options::OPT_shared)) {
        CmdArgs.push_back("-lgcc_pic");
      } else {
        CmdArgs.push_back("-lgcc");
      }
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib) &&
      !Args.hasArg(options::OPT_nostartfiles)) {
    if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtendS.o")));
    else
      CmdArgs.push_back(Args.MakeArgString(
                              getToolChain().GetFilePath("crtend.o")));
    CmdArgs.push_back(Args.MakeArgString(
                            getToolChain().GetFilePath("crtn.o")));
  }

  addProfileRT(getToolChain(), Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
  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 {
  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) &&
      !C.getDriver().IsCLMode()) {
    CmdArgs.push_back("-defaultlib:libcmt");
  }

  CmdArgs.push_back("-nologo");

  bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);

  if (DLL) {
    CmdArgs.push_back(Args.MakeArgString("-dll"));

    SmallString<128> ImplibName(Output.getFilename());
    llvm::sys::path::replace_extension(ImplibName, "lib");
    CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
                                         ImplibName.str()));
  }

  if (getToolChain().getSanitizerArgs().needsAsanRt()) {
    CmdArgs.push_back(Args.MakeArgString("-debug"));
    CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
    SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
    llvm::sys::path::append(LibSanitizer, "lib", "windows");
    if (DLL) {
      llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
    } else {
      llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
    }
    // FIXME: Handle 64-bit.
    CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
  }

  Args.AddAllArgValues(CmdArgs, options::OPT_l);
  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);

  // Add filenames immediately.
  for (InputInfoList::const_iterator
       it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
    if (it->isFilename())
      CmdArgs.push_back(it->getFilename());
    else
      it->getInputArg().renderAsInput(Args, CmdArgs);
  }

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
                                         const InputInfo &Output,
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
  C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}

// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
// If one cannot be found, return FallbackName.
// We do this special search to prevent clang-cl from falling back onto itself
// if it's available as cl.exe on the path.
static std::string FindFallback(const char *FallbackName,
                                const char *ClangProgramPath) {
  llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
  if (!OptPath.hasValue())
    return FallbackName;

#ifdef LLVM_ON_WIN32
  const StringRef PathSeparators = ";";
#else
  const StringRef PathSeparators = ":";
#endif

  SmallVector<StringRef, 8> PathSegments;
  llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators);

  for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
    const StringRef &PathSegment = PathSegments[i];
    if (PathSegment.empty())
      continue;

    SmallString<128> FilePath(PathSegment);
    llvm::sys::path::append(FilePath, FallbackName);
    if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
        !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
      return FilePath.str();
  }

  return FallbackName;
}

Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
                                           const InputInfo &Output,
                                           const InputInfoList &Inputs,
                                           const ArgList &Args,
                                           const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("/nologo");
  CmdArgs.push_back("/c"); // Compile only.
  CmdArgs.push_back("/W0"); // No warnings.

  // The goal is to be able to invoke this tool correctly based on
  // any flag accepted by clang-cl.

  // These are spelled the same way in clang and cl.exe,.
  Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
  Args.AddAllArgs(CmdArgs, options::OPT_I);

  // Optimization level.
  if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
    if (A->getOption().getID() == options::OPT_O0) {
      CmdArgs.push_back("/Od");
    } else {
      StringRef OptLevel = A->getValue();
      if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
        A->render(Args, CmdArgs);
      else if (OptLevel == "3")
        CmdArgs.push_back("/Ox");
    }
  }

  // Flags for which clang-cl have an alias.
  // FIXME: How can we ensure this stays in sync with relevant clang-cl options?

  if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti))
    CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR"
                                                                   : "/GR-");
  if (Args.hasArg(options::OPT_fsyntax_only))
    CmdArgs.push_back("/Zs");
  if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
    CmdArgs.push_back("/Z7");

  std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
  for (size_t I = 0, E = Includes.size(); I != E; ++I)
    CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I]));

  // Flags that can simply be passed through.
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);

  // The order of these flags is relevant, so pick the last one.
  if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
                               options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
    A->render(Args, CmdArgs);


  // Input filename.
  assert(Inputs.size() == 1);
  const InputInfo &II = Inputs[0];
  assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
  CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
  if (II.isFilename())
    CmdArgs.push_back(II.getFilename());
  else
    II.getInputArg().renderAsInput(Args, CmdArgs);

  // Output filename.
  assert(Output.getType() == types::TY_Object);
  const char *Fo = Args.MakeArgString(std::string("/Fo") +
                                      Output.getFilename());
  CmdArgs.push_back(Fo);

  const Driver &D = getToolChain().getDriver();
  std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());

  return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
}


/// XCore Tools
// We pass assemble and link construction to the xcc tool.

void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  CmdArgs.push_back("-c");

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  if (Args.hasArg(options::OPT_g_Group))
    CmdArgs.push_back("-g");

  if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
                   false))
    CmdArgs.push_back("-fverbose-asm");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
                       options::OPT_Xassembler);

  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("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}

void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
                                   const ArgList &Args,
                                   const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } else {
    assert(Output.isNothing() && "Invalid output.");
  }

  if (Args.hasArg(options::OPT_v))
    CmdArgs.push_back("-v");

  ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
  if (EH.ShouldUseExceptionTables)
    CmdArgs.push_back("-fexceptions");

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);

  const char *Exec =
    Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
  C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@


