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 aba1fe4..29713ed 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)); +} |