diff options
Diffstat (limited to 'lib/Driver/Tools.cpp')
| -rw-r--r-- | lib/Driver/Tools.cpp | 2230 | 
1 files changed, 1452 insertions, 778 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index aba1fe4d2d9e..29713ed1b4ce 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -7,43 +7,48 @@  //  //===----------------------------------------------------------------------===// -#include <sys/stat.h>  #include "Tools.h"  #include "InputInfo.h" -#include "SanitizerArgs.h"  #include "ToolChains.h"  #include "clang/Basic/ObjCRuntime.h"  #include "clang/Basic/Version.h"  #include "clang/Driver/Action.h" -#include "clang/Driver/Arg.h" -#include "clang/Driver/ArgList.h"  #include "clang/Driver/Compilation.h"  #include "clang/Driver/Driver.h"  #include "clang/Driver/DriverDiagnostic.h"  #include "clang/Driver/Job.h" -#include "clang/Driver/Option.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) +    if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP())        D.Diag(diag::err_drv_argument_only_allowed_with)          << A->getAsString(Args) << "-E";  } @@ -107,7 +112,7 @@ static void addDirectoryList(const ArgList &Args,      return;    StringRef::size_type Delim; -  while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { +  while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {      if (Delim == 0) { // Leading colon.        if (CombinedArg) {          CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + ".")); @@ -223,7 +228,9 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,  }  static bool forwardToGCC(const Option &O) { -  return !O.hasFlag(options::NoForward) && +  // 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);  } @@ -339,32 +346,28 @@ void Clang::AddPreprocessingOptions(Compilation &C,        bool FoundPTH = false;        bool FoundPCH = false; -      llvm::sys::Path P(A->getValue()); -      bool Exists; +      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) { -        P.appendSuffix("pch"); -        if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) +        llvm::sys::path::replace_extension(P, "pch"); +        if (llvm::sys::fs::exists(P.str()))            FoundPCH = true; -        else -          P.eraseSuffix();        }        if (!FoundPCH) { -        P.appendSuffix("pth"); -        if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) +        llvm::sys::path::replace_extension(P, "pth"); +        if (llvm::sys::fs::exists(P.str()))            FoundPTH = true; -        else -          P.eraseSuffix();        }        if (!FoundPCH && !FoundPTH) { -        P.appendSuffix("gch"); -        if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) { +        llvm::sys::path::replace_extension(P, "gch"); +        if (llvm::sys::fs::exists(P.str())) {            FoundPCH = UsePCH;            FoundPTH = !UsePCH;          } -        else -          P.eraseSuffix();        }        if (FoundPCH || FoundPTH) { @@ -446,6 +449,7 @@ void Clang::AddPreprocessingOptions(Compilation &C,  // 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") @@ -458,13 +462,14 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) {      .Cases("arm1176jzf-s",  "mpcorenovfp",  "mpcore", "v6")      .Cases("arm1156t2-s",  "arm1156t2f-s", "v6t2")      .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") -    .Cases("cortex-a9", "cortex-a15", "v7") -    .Case("cortex-r5", "v7r") +    .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("");  } @@ -494,6 +499,11 @@ static std::string getARMTargetCPU(const ArgList &Args,      MArch = Triple.getArchName();    } +  if (Triple.getOS() == llvm::Triple::NetBSD) { +    if (MArch == "armv6") +      return "arm1176jzf-s"; +  } +    // Handle -march=native.    std::string NativeMArch;    if (MArch == "native") { @@ -510,7 +520,8 @@ static std::string getARMTargetCPU(const ArgList &Args,      .Cases("armv2", "armv2a","arm2")      .Case("armv3", "arm6")      .Case("armv3m", "arm7m") -    .Cases("armv4", "armv4t", "arm7tdmi") +    .Case("armv4", "strongarm") +    .Case("armv4t", "arm7tdmi")      .Cases("armv5", "armv5t", "arm10tdmi")      .Cases("armv5e", "armv5te", "arm1022e")      .Case("armv5tej", "arm926ej-s") @@ -525,13 +536,35 @@ static std::string getARMTargetCPU(const ArgList &Args,      .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 LLVM supports. +    // 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()) { @@ -546,73 +579,117 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {        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 addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args, -                       ArgStringList &CmdArgs) { +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. -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-vfp2"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-vfp3"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neon"); +    Features.push_back("-vfp2"); +    Features.push_back("-vfp3"); +    Features.push_back("-neon");    } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+vfp3"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+d16"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neon"); +    Features.push_back("+vfp3"); +    Features.push_back("+d16"); +    Features.push_back("-neon");    } else if (FPU == "vfp") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+vfp2"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neon"); +    Features.push_back("+vfp2"); +    Features.push_back("-neon");    } else if (FPU == "vfp3" || FPU == "vfpv3") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+vfp3"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neon"); +    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") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+neon"); -  } else -    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - -// Handle -mfpmath=. -static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args, -                          ArgStringList &CmdArgs, StringRef CPU) { -  StringRef FPMath = A->getValue(); -   -  // Set the target features based on the FPMath. -  if (FPMath == "neon") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+neonfp"); -     -    if (CPU != "cortex-a5" && CPU != "cortex-a7" && -        CPU != "cortex-a8" && CPU != "cortex-a9" && -        CPU != "cortex-a9-mp" && CPU != "cortex-a15") -      D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU; -     -  } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" || -             FPMath == "vfp4") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neonfp"); - -    // FIXME: Add warnings when disabling a feature not present for a given CPU.     +    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);  } @@ -697,6 +774,41 @@ static StringRef getARMFloatABI(const Driver &D,    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, @@ -716,7 +828,8 @@ void Clang::AddARMTargetArgs(const ArgList &Args,    } else if (Triple.isOSDarwin()) {      // The backend is hardwired to assume AAPCS for M-class processors, ensure      // the frontend matches that. -    if (StringRef(CPUName).startswith("cortex-m")) { +    if (Triple.getEnvironment() == llvm::Triple::EABI || +        StringRef(CPUName).startswith("cortex-m")) {        ABIName = "aapcs";      } else {        ABIName = "apcs-gnu"; @@ -739,10 +852,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,    CmdArgs.push_back("-target-abi");    CmdArgs.push_back(ABIName); -  // Set the CPU based on -march= and -mcpu=. -  CmdArgs.push_back("-target-cpu"); -  CmdArgs.push_back(Args.MakeArgString(CPUName)); -    // Determine floating point ABI from the options & target defaults.    StringRef FloatABI = getARMFloatABI(D, Args, Triple);    if (FloatABI == "soft") { @@ -763,42 +872,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,      CmdArgs.push_back("hard");    } -  // Set appropriate target features for floating point mode. -  // -  // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these -  // yet (it uses the -mfloat-abi and -msoft-float options above), and it is -  // stripped out by the ARM target. - -  // Use software floating point operations? -  if (FloatABI == "soft") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+soft-float"); -  } - -  // Use software floating point argument passing? -  if (FloatABI != "hard") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+soft-float-abi"); -  } - -  // Honor -mfpu=. -  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) -    addFPUArgs(D, A, Args, CmdArgs); - -  // Honor -mfpmath=. -  if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) -    addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); - -  // Setting -msoft-float effectively disables NEON because of the GCC -  // implementation, although the same isn't true of VFP or VFP3. -  if (FloatABI == "soft") { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-neon"); -  } -    // Kernel code has more strict alignment requirements.    if (KernelOrKext) { -    if (Triple.getOS() != llvm::Triple::IOS || Triple.isOSVersionLT(6)) { +    if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {        CmdArgs.push_back("-backend-option");        CmdArgs.push_back("-arm-long-calls");      } @@ -808,7 +884,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,      // The kext linker doesn't know how to deal with movw/movt.      CmdArgs.push_back("-backend-option"); -    CmdArgs.push_back("-arm-darwin-use-movt=0"); +    CmdArgs.push_back("-arm-use-movt=0");    }    // Setting -mno-global-merge disables the codegen global merge pass. Setting  @@ -823,39 +899,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args,                      options::OPT_mno_implicit_float,                      true))      CmdArgs.push_back("-no-implicit-float"); -} -// Translate MIPS CPU name alias option to CPU name. -static StringRef getMipsCPUFromAlias(const Arg &A) { -  if (A.getOption().matches(options::OPT_mips32)) -    return "mips32"; -  if (A.getOption().matches(options::OPT_mips32r2)) -    return "mips32r2"; -  if (A.getOption().matches(options::OPT_mips64)) -    return "mips64"; -  if (A.getOption().matches(options::OPT_mips64r2)) -    return "mips64r2"; -  llvm_unreachable("Unexpected option"); -  return ""; +    // 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 ToolChain &TC, +                             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, -                               options::OPT_mips_CPUs_Group)) { -    if (A->getOption().matches(options::OPT_mips_CPUs_Group)) -      CPUName = getMipsCPUFromAlias(*A); -    else -      CPUName = A->getValue(); -  } +                               options::OPT_mcpu_EQ)) +    CPUName = A->getValue();    if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {      ABIName = A->getValue(); @@ -869,7 +934,7 @@ static void getMipsCPUAndABI(const ArgList &Args,    // Setup default CPU and ABI names.    if (CPUName.empty() && ABIName.empty()) { -    switch (TC.getTriple().getArch()) { +    switch (Triple.getArch()) {      default:        llvm_unreachable("Unexpected triple arch name");      case llvm::Triple::mips: @@ -941,28 +1006,56 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {  }  static void AddTargetFeature(const ArgList &Args, -                             ArgStringList &CmdArgs, -                             OptSpecifier OnOpt, -                             OptSpecifier OffOpt, +                             std::vector<const char *> &Features, +                             OptSpecifier OnOpt, OptSpecifier OffOpt,                               StringRef FeatureName) {    if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) { -    CmdArgs.push_back("-target-feature");      if (A->getOption().matches(OnOpt)) -      CmdArgs.push_back(Args.MakeArgString("+" + FeatureName)); +      Features.push_back(Args.MakeArgString("+" + FeatureName));      else -      CmdArgs.push_back(Args.MakeArgString("-" + FeatureName)); +      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; -  getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); - -  CmdArgs.push_back("-target-cpu"); -  CmdArgs.push_back(CPUName.data()); +  const llvm::Triple &Triple = getToolChain().getTriple(); +  getMipsCPUAndABI(Args, Triple, CPUName, ABIName);    CmdArgs.push_back("-target-abi");    CmdArgs.push_back(ABIName.data()); @@ -977,12 +1070,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,      CmdArgs.push_back("-mfloat-abi");      CmdArgs.push_back("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. -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+soft-float"); -      if (FloatABI == "hard" && IsMips16) {        CmdArgs.push_back("-mllvm");        CmdArgs.push_back("-mips16-hard-float"); @@ -995,22 +1082,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,      CmdArgs.push_back("hard");    } -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_msingle_float, options::OPT_mdouble_float, -                   "single-float"); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mips16, options::OPT_mno_mips16, -                   "mips16"); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mmicromips, options::OPT_mno_micromips, -                   "micromips"); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mdsp, options::OPT_mno_dsp, -                   "dsp"); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mdspr2, options::OPT_mno_dspr2, -                   "dspr2"); -    if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {      if (A->getOption().matches(options::OPT_mxgot)) {        CmdArgs.push_back("-mllvm"); @@ -1018,6 +1089,22 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,      }    } +  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"); @@ -1081,62 +1168,48 @@ static std::string getPPCTargetCPU(const ArgList &Args) {        .Case("pwr7", "pwr7")        .Case("powerpc", "ppc")        .Case("powerpc64", "ppc64") +      .Case("powerpc64le", "ppc64le")        .Default("");    }    return "";  } -void Clang::AddPPCTargetArgs(const ArgList &Args, -                             ArgStringList &CmdArgs) const { -  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) -  llvm::Triple Triple = getToolChain().getTriple(); -  if (TargetCPUName.empty() && !Triple.isOSDarwin()) { -    if (Triple.getArch() == llvm::Triple::ppc64) -      TargetCPUName = "ppc64"; -    else -      TargetCPUName = "ppc"; -  } - -  if (!TargetCPUName.empty()) { -    CmdArgs.push_back("-target-cpu"); -    CmdArgs.push_back(Args.MakeArgString(TargetCPUName.c_str())); -  } - -  // Allow override of the Altivec feature. -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_faltivec, options::OPT_fno_altivec, -                   "altivec"); +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(); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mfprnd, options::OPT_mno_fprnd, -                   "fprnd"); +    // Skip over "-m". +    assert(Name.startswith("m") && "Invalid feature name."); +    Name = Name.substr(1); -  // Note that gcc calls this mfcrf and LLVM calls this mfocrf. -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mmfcrf, options::OPT_mno_mfcrf, -                   "mfocrf"); +    bool IsNegative = Name.startswith("no-"); +    if (IsNegative) +      Name = Name.substr(3); -  AddTargetFeature(Args, CmdArgs, -                   options::OPT_mpopcntd, options::OPT_mno_popcntd, -                   "popcntd"); +    // 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"; -  // It is really only possible to turn qpx off because turning qpx on is tied -  // to using the a2q CPU. -  if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) { -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("-qpx"); +    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)) { -    std::string GPUName = A->getValue(); +    const char *GPUName = A->getValue();      return llvm::StringSwitch<const char *>(GPUName)        .Cases("rv630", "rv635", "r600")        .Cases("rv610", "rv620", "rs780", "rs880") @@ -1145,27 +1218,27 @@ static std::string getR600TargetGPU(const ArgList &Args) {        .Cases("sumo", "sumo2", "sumo")        .Case("hemlock", "cypress")        .Case("aruba", "cayman") -      .Default(GPUName.c_str()); +      .Default(GPUName);    }    return "";  } -void Clang::AddR600TargetArgs(const ArgList &Args, -                              ArgStringList &CmdArgs) const { -  std::string TargetGPUName = getR600TargetGPU(Args); -  CmdArgs.push_back("-target-cpu"); -  CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str())); +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(); -  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { -    CmdArgs.push_back("-target-cpu"); -    CmdArgs.push_back(A->getValue()); -  } -    // Select the float ABI as determined by -msoft-float, -mhard-float, and    StringRef FloatABI;    if (Arg *A = Args.getLastArg(options::OPT_msoft_float, @@ -1178,13 +1251,9 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,    // If unspecified, choose the default based on the platform.    if (FloatABI.empty()) { -    switch (getToolChain().getTriple().getOS()) { -    default: -      // Assume "soft", but warn the user we are guessing. -      FloatABI = "soft"; -      D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; -      break; -    } +    // Assume "soft", but warn the user we are guessing. +    FloatABI = "soft"; +    D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";    }    if (FloatABI == "soft") { @@ -1192,19 +1261,27 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,      //      // FIXME: This changes CPP defines, we need -target-soft-float.      CmdArgs.push_back("-msoft-float"); -    CmdArgs.push_back("-target-feature"); -    CmdArgs.push_back("+soft-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 (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. @@ -1225,30 +1302,128 @@ static const char *getX86TargetCPU(const ArgList &Args,    bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;    // FIXME: Need target hooks. -  if (Triple.isOSDarwin()) +  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"; -  if (Triple.getOSName().startswith("haiku")) -    return "i586"; -  if (Triple.getOSName().startswith("openbsd")) +  switch (Triple.getOS()) { +  case llvm::Triple::FreeBSD: +  case llvm::Triple::NetBSD: +  case llvm::Triple::OpenBSD:      return "i486"; -  if (Triple.getOSName().startswith("bitrig")) +  case llvm::Triple::Haiku: +    return "i586"; +  case llvm::Triple::Bitrig:      return "i686"; -  if (Triple.getOSName().startswith("freebsd")) -    return "i486"; -  if (Triple.getOSName().startswith("netbsd")) -    return "i486"; -  // 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"; +  default: +    // Fallback to p4. +    return "pentium4"; +  } +} + +static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { +  switch(T.getArch()) { +  default: +    return ""; -  // Fallback to p4. -  return "pentium4"; +  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, @@ -1274,45 +1449,6 @@ void Clang::AddX86TargetArgs(const ArgList &Args,    }    if (NoImplicitFloat)      CmdArgs.push_back("-no-implicit-float"); - -  if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) { -    CmdArgs.push_back("-target-cpu"); -    CmdArgs.push_back(CPUName); -  } - -  // The required algorithm here is slightly strange: the options are applied -  // in order (so -mno-sse -msse2 disables SSE3), but any option that gets -  // directly overridden later is ignored (so "-mno-sse -msse2 -mno-sse2 -msse" -  // is equivalent to "-mno-sse2 -msse"). The -cc1 handling deals with the -  // former correctly, but not the latter; handle directly-overridden -  // attributes here. -  llvm::StringMap<unsigned> PrevFeature; -  std::vector<const char*> Features; -  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); - -    unsigned& Prev = PrevFeature[Name]; -    if (Prev) -      Features[Prev - 1] = 0; -    Prev = Features.size() + 1; -    Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name)); -  } -  for (unsigned i = 0; i < Features.size(); i++) { -    if (Features[i]) { -      CmdArgs.push_back("-target-feature"); -      CmdArgs.push_back(Features[i]); -    } -  }  }  static inline bool HasPICArg(const ArgList &Args) { @@ -1339,12 +1475,6 @@ static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {  void Clang::AddHexagonTargetArgs(const ArgList &Args,                                   ArgStringList &CmdArgs) const { -  llvm::Triple Triple = getToolChain().getTriple(); - -  CmdArgs.push_back("-target-cpu"); -  CmdArgs.push_back(Args.MakeArgString( -                      "hexagon" -                      + toolchains::Hexagon_TC::GetTargetCPU(Args)));    CmdArgs.push_back("-fno-signed-char");    CmdArgs.push_back("-mqdsp6-compat");    CmdArgs.push_back("-Wreturn-type"); @@ -1366,6 +1496,70 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,    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) { @@ -1532,117 +1726,75 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {      RelaxDefault);  } -SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args) -    : Kind(0), BlacklistFile(""), MsanTrackOrigins(false), -      AsanZeroBaseShadow(false) { -  unsigned AllKinds = 0;  // All kinds of sanitizers that were turned on -                          // at least once (possibly, disabled further). -  const Driver &D = TC.getDriver(); -  for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { -    unsigned Add, Remove; -    if (!parse(D, Args, *I, Add, Remove, true)) -      continue; -    (*I)->claim(); -    Kind |= Add; -    Kind &= ~Remove; -    AllKinds |= Add; -  } +static void CollectArgsForIntegratedAssembler(Compilation &C, +                                              const ArgList &Args, +                                              ArgStringList &CmdArgs, +                                              const Driver &D) { +    if (UseRelaxAll(C, Args)) +      CmdArgs.push_back("-mrelax-all"); -  UbsanTrapOnError = -    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); +    // 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; -  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, true)) { -    D.Diag(diag::err_drv_argument_not_allowed_with) -      << "-fcatch-undefined-behavior" -      << "-fno-sanitize-undefined-trap-on-error"; -  } +    // 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(); -  // Warn about undefined sanitizer options that require runtime support. -  if (UbsanTrapOnError && notAllowedWithTrap()) { -    if (Args.hasArg(options::OPT_fcatch_undefined_behavior)) -      D.Diag(diag::err_drv_argument_not_allowed_with) -        << lastArgumentForKind(D, Args, NotAllowedWithTrap) -        << "-fcatch-undefined-behavior"; -    else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, -                          options::OPT_fno_sanitize_undefined_trap_on_error, -                          false)) -      D.Diag(diag::err_drv_argument_not_allowed_with) -        << lastArgumentForKind(D, Args, NotAllowedWithTrap) -        << "-fsanitize-undefined-trap-on-error"; -  } - -  // Only one runtime library can be used at once. -  bool NeedsAsan = needsAsanRt(); -  bool NeedsTsan = needsTsanRt(); -  bool NeedsMsan = needsMsanRt(); -  if (NeedsAsan && NeedsTsan) -    D.Diag(diag::err_drv_argument_not_allowed_with) -      << lastArgumentForKind(D, Args, NeedsAsanRt) -      << lastArgumentForKind(D, Args, NeedsTsanRt); -  if (NeedsAsan && NeedsMsan) -    D.Diag(diag::err_drv_argument_not_allowed_with) -      << lastArgumentForKind(D, Args, NeedsAsanRt) -      << lastArgumentForKind(D, Args, NeedsMsanRt); -  if (NeedsTsan && NeedsMsan) -    D.Diag(diag::err_drv_argument_not_allowed_with) -      << lastArgumentForKind(D, Args, NeedsTsanRt) -      << lastArgumentForKind(D, Args, NeedsMsanRt); - -  // If -fsanitize contains extra features of ASan, it should also -  // explicitly contain -fsanitize=address (probably, turned off later in the -  // command line). -  if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0) -    D.Diag(diag::warn_drv_unused_sanitizer) -     << lastArgumentForKind(D, Args, AddressFull) -     << "-fsanitize=address"; - -  // Parse -f(no-)sanitize-blacklist options. -  if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist, -                                   options::OPT_fno_sanitize_blacklist)) { -    if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) { -      std::string BLPath = BLArg->getValue(); -      bool BLExists = false; -      if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists) -        BlacklistFile = BLPath; -      else -        D.Diag(diag::err_drv_no_such_file) << BLPath; -    } -  } else { -    // If no -fsanitize-blacklist option is specified, try to look up for -    // blacklist in the resource directory. -    std::string BLPath; -    bool BLExists = false; -    if (getDefaultBlacklistForKind(D, Kind, BLPath) && -        !llvm::sys::fs::exists(BLPath, BLExists) && BLExists) -      BlacklistFile = BLPath; -  } - -  // Parse -f(no-)sanitize-memory-track-origins options. -  if (NeedsMsan) -    MsanTrackOrigins = -      Args.hasFlag(options::OPT_fsanitize_memory_track_origins, -                   options::OPT_fno_sanitize_memory_track_origins, -                   /* Default */false); - -  // Parse -f(no-)sanitize-address-zero-base-shadow options. -  if (NeedsAsan) { -    bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android); -    bool ZeroBaseShadowDefault = IsAndroid; -    AsanZeroBaseShadow = -        Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow, -                     options::OPT_fno_sanitize_address_zero_base_shadow, -                     ZeroBaseShadowDefault); -    // Zero-base shadow is a requirement on Android. -    if (IsAndroid && !AsanZeroBaseShadow) { -      D.Diag(diag::err_drv_argument_not_allowed_with) -          << "-fno-sanitize-address-zero-base-shadow" -          << lastArgumentForKind(D, Args, Address); +      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( @@ -1673,6 +1825,7 @@ static void addSanitizerRTLinkFlagsLinux(    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 @@ -1690,16 +1843,15 @@ static void addSanitizerRTLinkFlagsLinux(  /// 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) { +  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)) { +    if (!Args.hasArg(options::OPT_shared))        addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); -    }    }  } @@ -1707,18 +1859,24 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,  /// 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)) { +  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)) { +  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 @@ -1726,9 +1884,6 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,  static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,                              ArgStringList &CmdArgs, bool IsCXX,                              bool HasOtherSanitizerRt) { -  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) @@ -1742,22 +1897,42 @@ static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,      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); -  // Don't use a frame pointer on linux x86 and x86_64 if optimizing. -  if ((Triple.getArch() == llvm::Triple::x86_64 || -       Triple.getArch() == llvm::Triple::x86) && -      Triple.getOS() == llvm::Triple::Linux) { -    if (Arg *A = Args.getLastArg(options::OPT_O_Group)) -      if (!A->getOption().matches(options::OPT_O0)) -        return false; -  } - -  return true; +  return shouldUseFramePointerForTarget(Args, Triple);  }  static bool shouldUseLeafFramePointer(const ArgList &Args, @@ -1766,38 +1941,11 @@ static bool shouldUseLeafFramePointer(const ArgList &Args,                                 options::OPT_momit_leaf_frame_pointer))      return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); -  // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing. -  if ((Triple.getArch() == llvm::Triple::x86_64 || -       Triple.getArch() == llvm::Triple::x86) && -      Triple.getOS() == llvm::Triple::Linux) { -    if (Arg *A = Args.getLastArg(options::OPT_O_Group)) -      if (!A->getOption().matches(options::OPT_O0)) -        return false; -  } - -  return true; +  return shouldUseFramePointerForTarget(Args, Triple);  } -/// If the PWD environment variable is set, add a CC1 option to specify the -/// debug compilation directory. +/// Add a CC1 option to specify the debug compilation directory.  static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { -  struct stat StatPWDBuf, StatDotBuf; - -  const char *pwd = ::getenv("PWD"); -  if (!pwd) -    return; - -  if (llvm::sys::path::is_absolute(pwd) && -      stat(pwd, &StatPWDBuf) == 0 && -      stat(".", &StatDotBuf) == 0 && -      StatPWDBuf.st_ino == StatDotBuf.st_ino && -      StatPWDBuf.st_dev == StatDotBuf.st_dev) { -    CmdArgs.push_back("-fdebug-compilation-dir"); -    CmdArgs.push_back(Args.MakeArgString(pwd)); -    return; -  } - -  // Fall back to using getcwd.    SmallString<128> cwd;    if (!llvm::sys::fs::current_path(cwd)) {      CmdArgs.push_back("-fdebug-compilation-dir"); @@ -1854,6 +2002,37 @@ static bool isOptimizationLevelFast(const ArgList &Args) {    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, @@ -1896,35 +2075,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    } else if (isa<AssembleJobAction>(JA)) {      CmdArgs.push_back("-emit-obj"); -    if (UseRelaxAll(C, Args)) -      CmdArgs.push_back("-mrelax-all"); - -    // 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 (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 { -          D.Diag(diag::err_drv_unsupported_option_argument) -            << A->getOption().getName() << Value; -        } -      } -    } +    CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);      // Also ignore explicit -force_cpusubtype_ALL option.      (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); @@ -2071,7 +2222,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      }    } -  // Inroduce a Darwin-specific hack. If the default is PIC but the flags +  // 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). @@ -2082,8 +2233,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // PIC or PIE options above, if these show up, PIC is disabled.    llvm::Triple Triple(TripleStr);    if (KernelOrKext && -      (Triple.getOS() != llvm::Triple::IOS || -       Triple.isOSVersionLT(6))) +      (!Triple.isiOS() || Triple.isOSVersionLT(6)))      PIC = PIE = false;    if (Args.hasArg(options::OPT_static))      PIC = PIE = false; @@ -2134,6 +2284,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      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"); @@ -2149,11 +2312,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :      options::OPT_fstrict_aliasing;    if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption, -                    options::OPT_fno_strict_aliasing, -                    getToolChain().IsStrictAliasingDefault())) +                    options::OPT_fno_strict_aliasing, true))      CmdArgs.push_back("-relaxed-aliasing"); -  if (Args.hasArg(options::OPT_fstruct_path_tbaa)) -    CmdArgs.push_back("-struct-path-tbaa"); +  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"); @@ -2201,8 +2364,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,                                 options::OPT_fno_fast_math,                                 options::OPT_fmath_errno, -                               options::OPT_fno_math_errno)) -    MathErrno = A->getOption().getID() == 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"); @@ -2349,8 +2521,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      CmdArgs.push_back(A->getValue());    } -  // Add target specific cpu and features flags. -  switch(getToolChain().getTriple().getArch()) { +  // 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; @@ -2366,15 +2555,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      AddMIPSTargetArgs(Args, CmdArgs);      break; -  case llvm::Triple::ppc: -  case llvm::Triple::ppc64: -    AddPPCTargetArgs(Args, CmdArgs); -    break; - -  case llvm::Triple::r600: -    AddR600TargetArgs(Args, CmdArgs); -    break; -    case llvm::Triple::sparc:      AddSparcTargetArgs(Args, CmdArgs);      break; @@ -2389,7 +2569,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      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)) { @@ -2407,7 +2589,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      Arg *Unsupported;      if (types::isCXX(InputType) &&          getToolChain().getTriple().isOSDarwin() && -        getToolChain().getTriple().getArch() == llvm::Triple::x86) { +        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) @@ -2437,9 +2619,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    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)) -      CmdArgs.push_back("-g"); +             !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. @@ -2447,16 +2640,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    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().getOS() == llvm::Triple::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); @@ -2475,12 +2677,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,        CmdArgs.push_back("-coverage-file");        SmallString<128> CoverageFilename(Output.getFilename());        if (llvm::sys::path::is_relative(CoverageFilename.str())) { -        if (const char *pwd = ::getenv("PWD")) { -          if (llvm::sys::path::is_absolute(pwd)) { -            SmallString<128> Pwd(pwd); -            llvm::sys::path::append(Pwd, CoverageFilename.str()); -            CoverageFilename.swap(Pwd); -          } +        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)); @@ -2505,7 +2705,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    Args.AddLastArg(CmdArgs, options::OPT_working_directory);    bool ARCMTEnabled = false; -  if (!Args.hasArg(options::OPT_fno_objc_arc)) { +  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)) { @@ -2529,6 +2729,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,          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)) { @@ -2540,14 +2744,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      CmdArgs.push_back(A->getValue());      if (!Args.hasArg(options::OPT_objcmt_migrate_literals, -                     options::OPT_objcmt_migrate_subscripting)) { +                     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 @@ -2563,16 +2785,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // preprocessed inputs and configure concludes that -fPIC is not supported.    Args.ClaimAllArgs(options::OPT_D); -  // Manually translate -O to -O2 and -O4 to -O3; let clang reject -  // others. +  // 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)) +    if (A->getOption().matches(options::OPT_O4)) {        CmdArgs.push_back("-O3"); -    else if (A->getOption().matches(options::OPT_O) && -             A->getValue()[0] == '\0') -      CmdArgs.push_back("-O2"); -    else +      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 @@ -2586,7 +2806,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    Args.AddLastArg(CmdArgs, options::OPT_w);    // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} -  // (-ansi is equivalent to -std=c89). +  // (-ansi is equivalent to -std=c89 or -std=c++98).    //    // If a std is supplied, only add -trigraphs if it follows the    // option. @@ -2619,13 +2839,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      Args.AddLastArg(CmdArgs, options::OPT_trigraphs);    } -  // Map the bizarre '-Wwrite-strings' flag to a more sensible -  // '-fconst-strings'; this better indicates its actual behavior. -  if (Args.hasFlag(options::OPT_Wwrite_strings, options::OPT_Wno_write_strings, -                   false)) { -    // For perfect compatibility with GCC, we do this even in the presence of -    // '-w'. This flag names something other than a warning for GCC. -    CmdArgs.push_back("-fconst-strings"); +  // 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 @@ -2663,11 +2890,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      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()); @@ -2758,11 +2995,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    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); -  Args.AddLastArg(CmdArgs, options::OPT_faltivec); +  // 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); -  SanitizerArgs Sanitize(getToolChain(), Args); +  const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();    Sanitize.addArgs(Args, CmdArgs);    if (!Args.hasFlag(options::OPT_fsanitize_recover, @@ -2777,10 +3017,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // Report an error for -faltivec on anything other than PowerPC.    if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) -    if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || -          getToolChain().getTriple().getArch() == llvm::Triple::ppc64)) +    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"; +        << A->getAsString(Args) << "ppc/ppc64/ppc64le";    if (getToolChain().SupportsProfiling())      Args.AddLastArg(CmdArgs, options::OPT_pg); @@ -2821,8 +3062,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      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); +  Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, +                  options::OPT_fno_unroll_loops);    Args.AddLastArg(CmdArgs, options::OPT_pthread); @@ -2875,13 +3123,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));    }    // -mkernel implies -mstrict-align; don't add the redundant option. -  if (Args.hasArg(options::OPT_mstrict_align) && !KernelOrKext) { -    CmdArgs.push_back("-backend-option"); -    CmdArgs.push_back("-arm-strict-align"); +  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)) @@ -2925,6 +3199,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      }    } +  // -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)) { @@ -2980,7 +3283,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // -fshort-enums=0 is default for all architectures except Hexagon.    if (Args.hasFlag(options::OPT_fshort_enums,                     options::OPT_fno_short_enums, -                   getToolChain().getTriple().getArch() == +                   getToolChain().getArch() ==                     llvm::Triple::hexagon))      CmdArgs.push_back("-fshort-enums"); @@ -2995,11 +3298,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      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().getTriple().getArch() != llvm::Triple::hexagon) || +  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"); @@ -3017,13 +3321,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,                                   true))))      CmdArgs.push_back("-fms-compatibility"); -  // -fmsc-version=1300 is default. +  // -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=1300"); +      CmdArgs.push_back("-fmsc-version=1700");      else        CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));    } @@ -3061,12 +3365,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);    // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and -  // legacy is the default. -  if (objcRuntime.isNonFragile()) { +  // 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().getTriple().getArch()))) { +                        getToolChain().getArch()))) {        if (getToolChain().UseObjCMixedDispatch())          CmdArgs.push_back("-fobjc-dispatch-method=mixed");        else @@ -3074,12 +3379,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      }    } -  // -fobjc-default-synthesize-properties=1 is default. This only has an effect -  // if the nonfragile objc abi is used. -  if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) { -    CmdArgs.push_back("-fobjc-default-synthesize-properties"); -  } - +  // 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"); @@ -3159,16 +3468,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))      A->render(Args, CmdArgs); -  // -fno-pascal-strings is default, only pass non-default. If the tool chain -  // happened to translate to -mpascal-strings, we want to back translate here. -  // -  // FIXME: This is gross; that translation should be pulled from the -  // tool chain. +  // -fno-pascal-strings is default, only pass non-default.    if (Args.hasFlag(options::OPT_fpascal_strings,                     options::OPT_fno_pascal_strings, -                   false) || -      Args.hasFlag(options::OPT_mpascal_strings, -                   options::OPT_mno_pascal_strings,                     false))      CmdArgs.push_back("-fpascal-strings"); @@ -3183,7 +3485,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      CmdArgs.push_back("-fpack-struct=1");    } -  if (KernelOrKext) { +  if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {      if (!Args.hasArg(options::OPT_fcommon))        CmdArgs.push_back("-fno-common");      Args.ClaimAllArgs(options::OPT_fno_common); @@ -3283,6 +3585,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,        (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"); @@ -3302,31 +3607,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,                     false))      CmdArgs.push_back("-fasm-blocks"); -  // If -Ofast is the optimization level, then -fvectorize should be enabled. -  // This alias option is being used to simplify the hasFlag logic. -  OptSpecifier VectorizeAliasOption = OFastEnabled ? options::OPT_Ofast : +  // 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; - -  // -fvectorize is default.    if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption, -                   options::OPT_fno_vectorize, true)) { -    CmdArgs.push_back("-backend-option"); +                   options::OPT_fno_vectorize, EnableVec))      CmdArgs.push_back("-vectorize-loops"); -  } -  // -fno-slp-vectorize is default. +  // -fslp-vectorize is default.    if (Args.hasFlag(options::OPT_fslp_vectorize, -                   options::OPT_fno_slp_vectorize, false)) { -    CmdArgs.push_back("-backend-option"); +                   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("-backend-option"); +                   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); @@ -3353,13 +3652,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,                     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().getTriple().getArch() == llvm::Triple::arm || -       getToolChain().getTriple().getArch() == llvm::Triple::thumb)) { +      (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)) @@ -3456,7 +3762,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // 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().getOS() == llvm::Triple::Linux) && +    getToolChain().getTriple().isOSLinux() &&      (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));    const char *SplitDwarfOut;    if (SplitDwarf) { @@ -3466,7 +3772,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    }    // Finally add the compile command to the compilation. -  C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +  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. @@ -3491,38 +3805,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);    Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group); -  // Disable warnings for clang -E -use-gold-plugin -emit-llvm foo.c -  Args.ClaimAllArgs(options::OPT_use_gold_plugin); +  // Disable warnings for clang -E -emit-llvm foo.c    Args.ClaimAllArgs(options::OPT_emit_llvm);  } -void ClangAs::AddARMTargetArgs(const ArgList &Args, -                               ArgStringList &CmdArgs) const { -  const Driver &D = getToolChain().getDriver(); -  llvm::Triple Triple = getToolChain().getTriple(); - -  // Set the CPU based on -march= and -mcpu=. -  CmdArgs.push_back("-target-cpu"); -  CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple))); - -  // Honor -mfpu=. -  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) -    addFPUArgs(D, A, Args, CmdArgs); - -  // Honor -mfpmath=. -  if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) -    addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); -} - -void ClangAs::AddX86TargetArgs(const ArgList &Args, -                               ArgStringList &CmdArgs) const { -  // Set the CPU based on -march=. -  if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) { -    CmdArgs.push_back("-target-cpu"); -    CmdArgs.push_back(CPUName); -  } -} -  /// Add options related to the Objective-C runtime/ABI.  ///  /// Returns true if the runtime is non-fragile. @@ -3648,6 +3934,67 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,    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, @@ -3662,8 +4009,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,    Args.ClaimAllArgs(options::OPT_w);    // and "clang -emit-llvm -c foo.s"    Args.ClaimAllArgs(options::OPT_emit_llvm); -  // and "clang -use-gold-plugin -c foo.s" -  Args.ClaimAllArgs(options::OPT_use_gold_plugin);    // Invoke ourselves in -cc1as mode.    // @@ -3686,25 +4031,18 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,    CmdArgs.push_back("-main-file-name");    CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs)); -  if (UseRelaxAll(C, Args)) -    CmdArgs.push_back("-relax-all"); - -  // Add target specific cpu and features flags. -  switch(getToolChain().getTriple().getArch()) { -  default: -    break; - -  case llvm::Triple::arm: -  case llvm::Triple::thumb: -    AddARMTargetArgs(Args, CmdArgs); -    break; - -  case llvm::Triple::x86: -  case llvm::Triple::x86_64: -    AddX86TargetArgs(Args, CmdArgs); -    break; +  // 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); @@ -3754,8 +4092,9 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,    // FIXME: Add -static support, once we have it. -  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, -                       options::OPT_Xassembler); +  CollectArgsForIntegratedAssembler(C, Args, CmdArgs, +                                    getToolChain().getDriver()); +    Args.AddAllArgs(CmdArgs, options::OPT_mllvm);    assert(Output.isFilename() && "Unexpected lipo output."); @@ -3772,7 +4111,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,    // creating an object.    // TODO: Currently only works on linux with newer objcopy.    if (Args.hasArg(options::OPT_gsplit_dwarf) && -      (getToolChain().getTriple().getOS() == llvm::Triple::Linux)) +      getToolChain().getTriple().isOSLinux())      SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,                     SplitDebugName(Args, Inputs));  } @@ -3794,6 +4133,11 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &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 @@ -3815,6 +4159,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,        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()));    } @@ -3826,7 +4172,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,    // 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) +  else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 || +           Arch == llvm::Triple::ppc64le)      CmdArgs.push_back("-m64");    if (Output.isFilename()) { @@ -3889,7 +4236,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,    const char *GCCName;    if (!customGCCName.empty())      GCCName = customGCCName.c_str(); -  else if (D.CCCIsCXX) { +  else if (D.CCCIsCXX()) {      GCCName = "g++";    } else      GCCName = "gcc"; @@ -4151,7 +4498,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,    // Libraries    //----------------------------------------------------------------------------    if (incStdLib && incDefLibs) { -    if (D.CCCIsCXX) { +    if (D.CCCIsCXX()) {        ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);        CmdArgs.push_back("-lm");      } @@ -4178,10 +4525,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,    }    std::string Linker = ToolChain.GetProgramPath("hexagon-ld"); -  C.addCommand( -    new Command( -      JA, *this, -      Args.MakeArgString(Linker), CmdArgs)); +  C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));  }  // Hexagon tools end. @@ -4205,7 +4549,7 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {      .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)      .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",             llvm::Triple::x86) -    .Case("x86_64", llvm::Triple::x86_64) +    .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) @@ -4265,6 +4609,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,      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) { @@ -4278,12 +4627,12 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,    AddDarwinArch(Args, CmdArgs);    // Use -force_cpusubtype_ALL on x86 by default. -  if (getToolChain().getTriple().getArch() == llvm::Triple::x86 || -      getToolChain().getTriple().getArch() == llvm::Triple::x86_64 || +  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().getTriple().getArch() != llvm::Triple::x86_64 && +  if (getToolChain().getArch() != llvm::Triple::x86_64 &&        (((Args.hasArg(options::OPT_mkernel) ||           Args.hasArg(options::OPT_fapple_kext)) &&          (!getDarwinToolChain().isTargetIPhoneOS() || @@ -4374,6 +4723,9 @@ void darwin::Link::AddLinkArgs(Compilation &C,        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. @@ -4572,7 +4924,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,    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_m_Separate);    Args.AddAllArgs(CmdArgs, options::OPT_r);    // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading @@ -4581,9 +4932,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))      CmdArgs.push_back("-ObjC"); -  if (Args.hasArg(options::OPT_rdynamic)) -    CmdArgs.push_back("-export_dynamic"); -    CmdArgs.push_back("-o");    CmdArgs.push_back(Output.getFilename()); @@ -4680,19 +5028,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,    Args.AddAllArgs(CmdArgs, options::OPT_L); -  SanitizerArgs Sanitize(getToolChain(), Args); -  // If we're building a dynamic lib with -fsanitize=address, -  // unresolved symbols may appear. Mark all -  // of them as dynamic_lookup. Linking executables is handled in -  // lib/Driver/ToolChains.cpp. -  if (Sanitize.needsAsanRt()) { -    if (Args.hasArg(options::OPT_dynamiclib) || -        Args.hasArg(options::OPT_bundle)) { -      CmdArgs.push_back("-undefined"); -      CmdArgs.push_back("dynamic_lookup"); -    } -  } -    if (Args.hasArg(options::OPT_fopenmp))      // This is more complicated in gcc...      CmdArgs.push_back("-lgomp"); @@ -4732,7 +5067,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nodefaultlibs)) { -    if (getToolChain().getDriver().CCCIsCXX) +    if (getToolChain().getDriver().CCCIsCXX())        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);      // link_ssp spec is empty. @@ -4857,18 +5192,17 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,    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: -          assert(0 && "Unsupported architecture"); +  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; @@ -4914,7 +5248,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,        CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));        CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));      } -    if (getToolChain().getDriver().CCCIsCXX) +    if (getToolChain().getDriver().CCCIsCXX())        CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));    } @@ -4929,7 +5263,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nodefaultlibs)) { -    if (getToolChain().getDriver().CCCIsCXX) +    if (getToolChain().getDriver().CCCIsCXX())        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);      CmdArgs.push_back("-lgcc_s");      if (!Args.hasArg(options::OPT_shared)) { @@ -5071,6 +5405,40 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,                                       const char *LinkingOutput) const {    ArgStringList CmdArgs; +  // 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"); +    } +  } +    Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,                         options::OPT_Xassembler); @@ -5104,6 +5472,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,    // 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"); @@ -5125,6 +5498,9 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,      }    } +  if (Args.hasArg(options::OPT_nopie)) +    CmdArgs.push_back("-nopie"); +    if (Output.isFilename()) {      CmdArgs.push_back("-o");      CmdArgs.push_back(Output.getFilename()); @@ -5167,7 +5543,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nodefaultlibs)) { -    if (D.CCCIsCXX) { +    if (D.CCCIsCXX()) {        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);        if (Args.hasArg(options::OPT_pg))           CmdArgs.push_back("-lm_p"); @@ -5297,7 +5673,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nodefaultlibs)) { -    if (D.CCCIsCXX) { +    if (D.CCCIsCXX()) {        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);        if (Args.hasArg(options::OPT_pg))          CmdArgs.push_back("-lm_p"); @@ -5320,23 +5696,21 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,          CmdArgs.push_back("-lc");      } -    std::string myarch = "-lclang_rt."; -    const llvm::Triple &T = getToolChain().getTriple(); -    llvm::Triple::ArchType Arch = T.getArch(); -    switch (Arch) { -          case llvm::Triple::arm: -            myarch += ("arm"); -            break; -          case llvm::Triple::x86: -            myarch += ("i386"); -            break; -          case llvm::Triple::x86_64: -            myarch += ("amd64"); -            break; -          default: -            assert(0 && "Unsupported architecture"); -     } -     CmdArgs.push_back(Args.MakeArgString(myarch)); +    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) && @@ -5373,7 +5747,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,             getToolChain().getArch() == llvm::Triple::mips64el) {      StringRef CPUName;      StringRef ABIName; -    getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); +    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);      CmdArgs.push_back("-march");      CmdArgs.push_back(CPUName.data()); @@ -5533,11 +5907,31 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,    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) { +    if (D.CCCIsCXX()) {        ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);        if (Args.hasArg(options::OPT_pg))          CmdArgs.push_back("-lm_p"); @@ -5617,11 +6011,45 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,    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"); +  // 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)); +  } + +  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"); +    } +  }    Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,                         options::OPT_Xassembler); @@ -5705,34 +6133,39 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,    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) { +    if (D.CCCIsCXX()) {        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);        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_static)) { -      CmdArgs.push_back("-lgcc_eh"); -    } else { -      CmdArgs.push_back("--as-needed"); -      CmdArgs.push_back("-lgcc_s"); -      CmdArgs.push_back("--no-as-needed"); -    } -    CmdArgs.push_back("-lgcc"); -      if (Args.hasArg(options::OPT_pthread))        CmdArgs.push_back("-lpthread");      CmdArgs.push_back("-lc"); -    CmdArgs.push_back("-lgcc"); -    if (Args.hasArg(options::OPT_static)) { -      CmdArgs.push_back("-lgcc_eh"); -    } else { -      CmdArgs.push_back("--as-needed"); -      CmdArgs.push_back("-lgcc_s"); -      CmdArgs.push_back("--no-as-needed"); +    if (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"); +      }      }    } @@ -5775,10 +6208,16 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,      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()); @@ -5793,7 +6232,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,               getToolChain().getArch() == llvm::Triple::mips64el) {      StringRef CPUName;      StringRef ABIName; -    getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); +    getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);      CmdArgs.push_back("-march");      CmdArgs.push_back(CPUName.data()); @@ -5807,12 +6246,31 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,      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")); +    } + +    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")); +    } +      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")); +    } +      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, @@ -5825,8 +6283,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,        CmdArgs.push_back("-KPIC");      }    } else if (getToolChain().getArch() == llvm::Triple::systemz) { -    // At the moment we always produce z10 code. -    CmdArgs.push_back("-march=z10"); +    // 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, @@ -5844,6 +6304,14 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,    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, @@ -5851,23 +6319,23 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D,    bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;    bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||                        Args.hasArg(options::OPT_static); -  if (!D.CCCIsCXX) +  if (!D.CCCIsCXX())      CmdArgs.push_back("-lgcc");    if (StaticLibgcc || isAndroid) { -    if (D.CCCIsCXX) +    if (D.CCCIsCXX())        CmdArgs.push_back("-lgcc");    } else { -    if (!D.CCCIsCXX) +    if (!D.CCCIsCXX())        CmdArgs.push_back("--as-needed");      CmdArgs.push_back("-lgcc_s"); -    if (!D.CCCIsCXX) +    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) +  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 @@ -5884,6 +6352,39 @@ static bool hasMipsN32ABIArg(const ArgList &Args) {    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, @@ -5894,7 +6395,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,    const Driver &D = ToolChain.getDriver();    const bool isAndroid =      ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; -  SanitizerArgs Sanitize(getToolChain(), Args); +  const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs();    const bool IsPIE =      !Args.hasArg(options::OPT_shared) &&      (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow()); @@ -5981,36 +6482,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,        (!Args.hasArg(options::OPT_static) &&         !Args.hasArg(options::OPT_shared))) {      CmdArgs.push_back("-dynamic-linker"); -    if (isAndroid) -      CmdArgs.push_back("/system/bin/linker"); -    else if (ToolChain.getArch() == llvm::Triple::x86) -      CmdArgs.push_back("/lib/ld-linux.so.2"); -    else if (ToolChain.getArch() == llvm::Triple::aarch64) -      CmdArgs.push_back("/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) -        CmdArgs.push_back("/lib/ld-linux-armhf.so.3"); -      else -        CmdArgs.push_back("/lib/ld-linux.so.3"); -    } -    else if (ToolChain.getArch() == llvm::Triple::mips || -             ToolChain.getArch() == llvm::Triple::mipsel) -      CmdArgs.push_back("/lib/ld.so.1"); -    else if (ToolChain.getArch() == llvm::Triple::mips64 || -             ToolChain.getArch() == llvm::Triple::mips64el) { -      if (hasMipsN32ABIArg(Args)) -        CmdArgs.push_back("/lib32/ld.so.1"); -      else -        CmdArgs.push_back("/lib64/ld.so.1"); -    } -    else if (ToolChain.getArch() == llvm::Triple::ppc) -      CmdArgs.push_back("/lib/ld.so.1"); -    else if (ToolChain.getArch() == llvm::Triple::ppc64 || -	     ToolChain.getArch() == llvm::Triple::systemz) -      CmdArgs.push_back("/lib64/ld64.so.1"); -    else -      CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2"); +    CmdArgs.push_back(Args.MakeArgString( +        D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));    }    CmdArgs.push_back("-o"); @@ -6021,7 +6494,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,      if (!isAndroid) {        const char *crt1 = NULL;        if (!Args.hasArg(options::OPT_shared)){ -        if (IsPIE) +        if (Args.hasArg(options::OPT_pg)) +          crt1 = "gcrt1.o"; +        else if (IsPIE)            crt1 = "Scrt1.o";          else            crt1 = "crt1.o"; @@ -6058,7 +6533,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,    // 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) || Args.hasArg(options::OPT_use_gold_plugin)) { +  if (D.IsUsingLTO(Args)) {      CmdArgs.push_back("-plugin");      std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";      CmdArgs.push_back(Args.MakeArgString(Plugin)); @@ -6066,20 +6541,13 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,      // Try to pass driver level flags relevant to LTO code generation down to      // the plugin. -    // Handle architecture-specific flags for selecting CPU variants. -    if (ToolChain.getArch() == llvm::Triple::x86 || -        ToolChain.getArch() == llvm::Triple::x86_64) +    // 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=") + -                             getX86TargetCPU(Args, ToolChain.getTriple()))); -    else if (ToolChain.getArch() == llvm::Triple::arm || -             ToolChain.getArch() == llvm::Triple::thumb) -      CmdArgs.push_back( -          Args.MakeArgString(Twine("-plugin-opt=mcpu=") + -                             getARMTargetCPU(Args, ToolChain.getTriple()))); - -    // FIXME: Factor out logic for MIPS, PPC, and other targets to support this -    // as well. +                        Args.MakeArgString(Twine("-plugin-opt=mcpu=") + +                                           CPU)); +    }    } @@ -6090,17 +6558,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,    // Call these before we add the C++ ABI library.    if (Sanitize.needsUbsanRt()) -    addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX, +    addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(),                      Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || -                    Sanitize.needsMsanRt()); +                    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); -  if (D.CCCIsCXX && +  // 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) && @@ -6156,8 +6631,6 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,      }    } -  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); -    C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));  } @@ -6218,7 +6691,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nodefaultlibs)) { -    if (D.CCCIsCXX) { +    if (D.CCCIsCXX()) {        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);        CmdArgs.push_back("-lm");      } @@ -6366,7 +6839,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,        }      } -    if (D.CCCIsCXX) { +    if (D.CCCIsCXX()) {        getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);        CmdArgs.push_back("-lm");      } @@ -6438,22 +6911,223 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,    }    if (!Args.hasArg(options::OPT_nostdlib) && -    !Args.hasArg(options::OPT_nostartfiles)) { +      !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)); +}  | 
