diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Tools.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 2848 |
1 files changed, 1835 insertions, 1013 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 525a9f0..89db52e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -10,6 +10,7 @@ #include "Tools.h" #include "InputInfo.h" #include "ToolChains.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" #include "clang/Driver/Action.h" @@ -21,7 +22,6 @@ #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" @@ -29,28 +29,47 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" -#include "llvm/Support/Program.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include <sys/stat.h> using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) { + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, + options::OPT_fpie, options::OPT_fno_pie); + if (!LastPICArg) + return; + if (LastPICArg->getOption().matches(options::OPT_fPIC) || + LastPICArg->getOption().matches(options::OPT_fpic) || + LastPICArg->getOption().matches(options::OPT_fPIE) || + LastPICArg->getOption().matches(options::OPT_fpie)) { + CmdArgs.push_back("-KPIC"); + } +} + /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { - if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) - if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP()) + if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) { + if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) && + !Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) { D.Diag(diag::err_drv_argument_only_allowed_with) - << A->getAsString(Args) << "-E"; + << A->getBaseArg().getAsString(Args) + << (D.IsCLMode() ? "/E, /P or /EP" : "-E"); + } + } } /// CheckCodeGenerationOptions - Perform some validation of code generation @@ -157,10 +176,7 @@ static void AddLinkerInputs(const ToolChain &TC, // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + for (const auto &II : Inputs) { if (!TC.HasNativeLLVMSupport()) { // Don't try to pass LLVM inputs unless we have native support. if (II.getType() == types::TY_LLVM_IR || @@ -181,16 +197,23 @@ static void AddLinkerInputs(const ToolChain &TC, const Arg &A = II.getInputArg(); // Handle reserved library options. - if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { + if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) TC.AddCXXStdlibLibArgs(Args, CmdArgs); - } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) { + else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) TC.AddCCKextLibArgs(Args, CmdArgs); - } else - A.renderAsInput(Args, CmdArgs); + else if (A.getOption().matches(options::OPT_z)) { + // Pass -z prefix for gcc linker compatibility. + A.claim(); + A.render(Args, CmdArgs); + } else { + A.renderAsInput(Args, CmdArgs); + } } // LIBRARY_PATH - included following the user specified library paths. - addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + // and only supported on native toolchains. + if (!TC.isCrossCompiling()) + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); } /// \brief Determine whether Objective-C automated reference counting is @@ -208,25 +231,6 @@ static bool isObjCRuntimeLinked(const ArgList &Args) { return Args.hasArg(options::OPT_fobjc_link_runtime); } -static void addProfileRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, - llvm::Triple Triple) { - if (!(Args.hasArg(options::OPT_fprofile_arcs) || - Args.hasArg(options::OPT_fprofile_generate) || - Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_coverage))) - return; - - // GCC links libgcov.a by adding -L<inst>/gcc/lib/gcc/<triple>/<ver> -lgcov to - // the link line. We cannot do the same thing because unlike gcov there is a - // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is - // not supported by old linkers. - std::string ProfileRT = - std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a"; - - CmdArgs.push_back(Args.MakeArgString(ProfileRT)); -} - static bool forwardToGCC(const Option &O) { // Don't forward inputs from the original command line. They are added from // InputInfoList. @@ -297,6 +301,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); + + if (isa<PrecompileJobAction>(JA)) + CmdArgs.push_back("-module-file-deps"); } if (Args.hasArg(options::OPT_MG)) { @@ -442,130 +449,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs); } -/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular -/// CPU. -// -// FIXME: This is redundant with -mcpu, why does LLVM use this. -// FIXME: tblgen this, or kill it! -static const char *getLLVMArchSuffixForARM(StringRef CPU) { - return llvm::StringSwitch<const char *>(CPU) - .Case("strongarm", "v4") - .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") - .Cases("arm720t", "arm9", "arm9tdmi", "v4t") - .Cases("arm920", "arm920t", "arm922t", "v4t") - .Cases("arm940t", "ep9312","v4t") - .Cases("arm10tdmi", "arm1020t", "v5") - .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") - .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") - .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") - .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") - .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") - .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") - .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7") - .Cases("cortex-r4", "cortex-r5", "v7r") - .Case("cortex-m0", "v6m") - .Case("cortex-m3", "v7m") - .Case("cortex-m4", "v7em") - .Case("cortex-a9-mp", "v7f") - .Case("swift", "v7s") - .Cases("cortex-a53", "cortex-a57", "v8") - .Default(""); -} - -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. -// -// FIXME: tblgen this. -static std::string getARMTargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { - // FIXME: Warn on inconsistent use of -mcpu and -march. - - // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef MCPU = A->getValue(); - // Handle -mcpu=native. - if (MCPU == "native") - return llvm::sys::getHostCPUName(); - else - return MCPU; - } - - StringRef MArch; - if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - // Otherwise, if we have -march= choose the base CPU for that arch. - MArch = A->getValue(); - } else { - // Otherwise, use the Arch from the triple. - MArch = Triple.getArchName(); - } - - if (Triple.getOS() == llvm::Triple::NetBSD || - Triple.getOS() == llvm::Triple::FreeBSD) { - if (MArch == "armv6") - return "arm1176jzf-s"; - } - - // Handle -march=native. - std::string NativeMArch; - if (MArch == "native") { - std::string CPU = llvm::sys::getHostCPUName(); - if (CPU != "generic") { - // Translate the native cpu into the architecture. The switch below will - // then chose the minimum cpu for that arch. - NativeMArch = std::string("arm") + getLLVMArchSuffixForARM(CPU); - MArch = NativeMArch; - } - } - - return llvm::StringSwitch<const char *>(MArch) - .Cases("armv2", "armv2a","arm2") - .Case("armv3", "arm6") - .Case("armv3m", "arm7m") - .Case("armv4", "strongarm") - .Case("armv4t", "arm7tdmi") - .Cases("armv5", "armv5t", "arm10tdmi") - .Cases("armv5e", "armv5te", "arm1022e") - .Case("armv5tej", "arm926ej-s") - .Cases("armv6", "armv6k", "arm1136jf-s") - .Case("armv6j", "arm1136j-s") - .Cases("armv6z", "armv6zk", "arm1176jzf-s") - .Case("armv6t2", "arm1156t2-s") - .Cases("armv6m", "armv6-m", "cortex-m0") - .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") - .Cases("armv7em", "armv7e-m", "cortex-m4") - .Cases("armv7f", "armv7-f", "cortex-a9-mp") - .Cases("armv7s", "armv7-s", "swift") - .Cases("armv7r", "armv7-r", "cortex-r4") - .Cases("armv7m", "armv7-m", "cortex-m3") - .Cases("armv8", "armv8a", "armv8-a", "cortex-a53") - .Case("ep9312", "ep9312") - .Case("iwmmxt", "iwmmxt") - .Case("xscale", "xscale") - // If all else failed, return the most base CPU with thumb interworking - // supported by LLVM. - .Default("arm7tdmi"); -} - -/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting. -// -// FIXME: tblgen this. -static std::string getAArch64TargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { - // FIXME: Warn on inconsistent use of -mcpu and -march. - - // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef MCPU = A->getValue(); - // Handle -mcpu=native. - if (MCPU == "native") - return llvm::sys::getHostCPUName(); - else - return MCPU; - } - - return "generic"; -} - // FIXME: Move to target hook. static bool isSignedCharDefault(const llvm::Triple &Triple) { switch (Triple.getArch()) { @@ -573,7 +456,15 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { return true; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64: + case llvm::Triple::arm64_be: case llvm::Triple::arm: + case llvm::Triple::armeb: + if (Triple.isOSDarwin() || Triple.isOSWindows()) + return true; + return false; + case llvm::Triple::ppc: case llvm::Triple::ppc64: if (Triple.isOSDarwin()) @@ -597,33 +488,6 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { } } -// 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, @@ -660,16 +524,28 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, Features.push_back("-vfp2"); Features.push_back("-vfp3"); Features.push_back("-neon"); + } else if (FPU == "vfp") { + Features.push_back("+vfp2"); + Features.push_back("-neon"); } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { Features.push_back("+vfp3"); Features.push_back("+d16"); Features.push_back("-neon"); - } else if (FPU == "vfp") { - Features.push_back("+vfp2"); - Features.push_back("-neon"); } else if (FPU == "vfp3" || FPU == "vfpv3") { Features.push_back("+vfp3"); Features.push_back("-neon"); + } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") { + Features.push_back("+vfp4"); + Features.push_back("+d16"); + Features.push_back("-neon"); + } else if (FPU == "vfp4" || FPU == "vfpv4") { + Features.push_back("+vfp4"); + Features.push_back("-neon"); + } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") { + Features.push_back("+vfp4"); + Features.push_back("+d16"); + Features.push_back("+fp-only-sp"); + Features.push_back("-neon"); } else if (FPU == "fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("-neon"); @@ -697,9 +573,8 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. -static StringRef getARMFloatABI(const Driver &D, - const ArgList &Args, - const llvm::Triple &Triple) { +StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args, + const llvm::Triple &Triple) { StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -728,7 +603,7 @@ static StringRef getARMFloatABI(const Driver &D, // // FIXME: Factor out an ARM class so we can cache the arch somewhere. std::string ArchName = - getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v6") || StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; @@ -737,6 +612,11 @@ static StringRef getARMFloatABI(const Driver &D, break; } + // FIXME: this is invalid for WindowsCE + case llvm::Triple::Win32: + FloatABI = "hard"; + break; + case llvm::Triple::FreeBSD: switch(Triple.getEnvironment()) { case llvm::Triple::GNUEABIHF: @@ -757,13 +637,16 @@ static StringRef getARMFloatABI(const Driver &D, case llvm::Triple::GNUEABI: FloatABI = "softfp"; break; + case llvm::Triple::EABIHF: + FloatABI = "hard"; + break; case llvm::Triple::EABI: // EABI is always AAPCS, and if it was not marked 'hard', it's softfp FloatABI = "softfp"; break; case llvm::Triple::Android: { std::string ArchName = - getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; else @@ -773,7 +656,9 @@ static StringRef getARMFloatABI(const Driver &D, default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + if (Triple.getOS() != llvm::Triple::UnknownOS || + !Triple.isOSBinFormatMachO()) + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; break; } } @@ -784,18 +669,30 @@ static StringRef getARMFloatABI(const Driver &D, 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"); + std::vector<const char *> &Features, + bool ForAS) { + StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple); + if (!ForAS) { + // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these + // yet (it uses the -mfloat-abi and -msoft-float options), and it is + // stripped out by the ARM target. We should probably pass this a new + // -target-option, which is handled by the -cc1/-cc1as invocation. + // + // FIXME2: For consistency, it would be ideal if we set up the target + // machine state the same when using the frontend or the assembler. We don't + // currently do that for the assembler, we pass the options directly to the + // backend and never even instantiate the frontend TargetInfo. If we did, + // and used its handleTargetFeatures hook, then we could ensure the + // assembler and the frontend behave the same. - // Use software floating point argument passing? - if (FloatABI != "hard") - Features.push_back("+soft-float-abi"); + // 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)) @@ -805,8 +702,11 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &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") + if (FloatABI == "soft") { Features.push_back("-neon"); + // Also need to explicitly disable features which imply NEON. + Features.push_back("-crypto"); + } // En/disable crc if (Arg *A = Args.getLastArg(options::OPT_mcrc, @@ -825,23 +725,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Get the effective triple, which takes into account the deployment target. std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); llvm::Triple Triple(TripleStr); - std::string CPUName = getARMTargetCPU(Args, Triple); + std::string CPUName = arm::getARMTargetCPU(Args, Triple); // Select the ABI to use. // // FIXME: Support -meabi. - const char *ABIName = 0; + const char *ABIName = nullptr; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); - } else if (Triple.isOSDarwin()) { + } else if (Triple.isOSBinFormatMachO()) { // The backend is hardwired to assume AAPCS for M-class processors, ensure // the frontend matches that. if (Triple.getEnvironment() == llvm::Triple::EABI || + (Triple.getOS() == llvm::Triple::UnknownOS && + Triple.getObjectFormat() == llvm::Triple::MachO) || StringRef(CPUName).startswith("cortex-m")) { ABIName = "aapcs"; } else { ABIName = "apcs-gnu"; } + } else if (Triple.isOSWindows()) { + // FIXME: this is invalid for WindowsCE + ABIName = "aapcs"; } else { // Select the default based on the platform. switch(Triple.getEnvironment()) { @@ -850,6 +755,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, case llvm::Triple::GNUEABIHF: ABIName = "aapcs-linux"; break; + case llvm::Triple::EABIHF: case llvm::Triple::EABI: ABIName = "aapcs"; break; @@ -861,7 +767,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back(ABIName); // Determine floating point ABI from the options & target defaults. - StringRef FloatABI = getARMFloatABI(D, Args, Triple); + StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple); if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // @@ -908,23 +814,97 @@ void Clang::AddARMTargetArgs(const ArgList &Args, true)) CmdArgs.push_back("-no-implicit-float"); - // llvm does not support reserving registers in general. There is support - // for reserving r9 on ARM though (defined as a platform-specific register - // in ARM EABI). - if (Args.hasArg(options::OPT_ffixed_r9)) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-reserve-r9"); - } + // llvm does not support reserving registers in general. There is support + // for reserving r9 on ARM though (defined as a platform-specific register + // in ARM EABI). + if (Args.hasArg(options::OPT_ffixed_r9)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-reserve-r9"); + } +} + +/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are +/// targeting. +static std::string getAArch64TargetCPU(const ArgList &Args) { + Arg *A; + std::string CPU; + // If we have -mtune or -mcpu, use that. + if ((A = Args.getLastArg(options::OPT_mtune_EQ))) { + CPU = A->getValue(); + } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) { + StringRef Mcpu = A->getValue(); + CPU = Mcpu.split("+").first; + } + + // Handle CPU name is 'native'. + if (CPU == "native") + return llvm::sys::getHostCPUName(); + else if (CPU.size()) + return CPU; + + // Make sure we pick "cyclone" if -arch is used. + // FIXME: Should this be picked by checking the target triple instead? + if (Args.getLastArg(options::OPT_arch)) + return "cyclone"; + + return "generic"; +} + +void Clang::AddAArch64TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); + llvm::Triple Triple(TripleStr); + + if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || + Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) + CmdArgs.push_back("-disable-red-zone"); + + if (!Args.hasFlag(options::OPT_mimplicit_float, + options::OPT_mno_implicit_float, true)) + CmdArgs.push_back("-no-implicit-float"); + + const char *ABIName = nullptr; + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) + ABIName = A->getValue(); + else if (Triple.isOSDarwin()) + ABIName = "darwinpcs"; + else + ABIName = "aapcs"; + + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName); + + if (Args.hasArg(options::OPT_mstrict_align)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-aarch64-strict-align"); + } + + // Setting -mno-global-merge disables the codegen global merge pass. Setting + // -mglobal-merge has no effect as the pass is enabled by default. + if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, + options::OPT_mno_global_merge)) { + if (A->getOption().matches(options::OPT_mno_global_merge)) + CmdArgs.push_back("-mno-global-merge"); + } } // Get CPU and ABI names. They are not independent // so we have to calculate them together. -static void getMipsCPUAndABI(const ArgList &Args, - const llvm::Triple &Triple, - StringRef &CPUName, - StringRef &ABIName) { - const char *DefMips32CPU = "mips32"; - const char *DefMips64CPU = "mips64"; +void mips::getMipsCPUAndABI(const ArgList &Args, + const llvm::Triple &Triple, + StringRef &CPUName, + StringRef &ABIName) { + const char *DefMips32CPU = "mips32r2"; + const char *DefMips64CPU = "mips64r2"; + + // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the + // default for mips64(el)?-img-linux-gnu. + if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && + Triple.getEnvironment() == llvm::Triple::GNU) { + DefMips32CPU = "mips32r6"; + DefMips64CPU = "mips64r6"; + } if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ)) @@ -956,22 +936,22 @@ static void getMipsCPUAndABI(const ArgList &Args, } } - if (!ABIName.empty()) { + if (ABIName.empty()) { + // Deduce ABI name from the target triple. + if (Triple.getArch() == llvm::Triple::mips || + Triple.getArch() == llvm::Triple::mipsel) + ABIName = "o32"; + else + ABIName = "n64"; + } + + if (CPUName.empty()) { // Deduce CPU name from ABI name. CPUName = llvm::StringSwitch<const char *>(ABIName) - .Cases("32", "o32", "eabi", DefMips32CPU) - .Cases("n32", "n64", "64", DefMips64CPU) + .Cases("o32", "eabi", DefMips32CPU) + .Cases("n32", "n64", DefMips64CPU) .Default(""); } - else if (!CPUName.empty()) { - // Deduce ABI name from CPU name. - ABIName = llvm::StringSwitch<const char *>(CPUName) - .Cases("mips32", "mips32r2", "o32") - .Cases("mips64", "mips64r2", "n64") - .Default(""); - } - - // FIXME: Warn on inconsistent cpu and abi usage. } // Convert ABI name to the GNU tools acceptable variant. @@ -1025,11 +1005,27 @@ static void AddTargetFeature(const ArgList &Args, } } -static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, +static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, std::vector<const char *> &Features) { + StringRef CPUName; + StringRef ABIName; + mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + ABIName = getGnuCompatibleMipsABIName(ABIName); + + // Always override the backend's default ABI. + std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName) + .Case("32", "+o32") + .Case("n32", "+n32") + .Case("64", "+n64") + .Case("eabi", "+eabi") + .Default(("+" + ABIName).str()); + Features.push_back("-o32"); + Features.push_back("-n64"); + Features.push_back(Args.MakeArgString(ABIFeature)); + StringRef FloatABI = getMipsFloatABI(D, Args); - bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; - if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { + if (FloatABI == "soft") { // FIXME: Note, this is a hack. We need to pass the selected float // mode to the MipsTargetInfoBase to define appropriate macros there. // Now it is the only method. @@ -1037,8 +1033,14 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, } if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { - if (StringRef(A->getValue()) == "2008") + StringRef Val = StringRef(A->getValue()); + if (Val == "2008") Features.push_back("+nan2008"); + else if (Val == "legacy") + Features.push_back("-nan2008"); + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; } AddTargetFeature(Args, Features, options::OPT_msingle_float, @@ -1053,8 +1055,25 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, "dspr2"); AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, "msa"); - AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32, - "fp64"); + + // Add the last -mfp32/-mfpxx/-mfp64 or if none are given and the ABI is O32 + // pass -mfpxx + if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, + options::OPT_mfp64)) { + if (A->getOption().matches(options::OPT_mfp32)) + Features.push_back(Args.MakeArgString("-fp64")); + else if (A->getOption().matches(options::OPT_mfpxx)) { + Features.push_back(Args.MakeArgString("+fpxx")); + Features.push_back(Args.MakeArgString("+nooddspreg")); + } else + Features.push_back(Args.MakeArgString("+fp64")); + } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) { + Features.push_back(Args.MakeArgString("+fpxx")); + Features.push_back(Args.MakeArgString("+nooddspreg")); + } + + AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, + options::OPT_modd_spreg, "nooddspreg"); } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -1063,25 +1082,18 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, StringRef CPUName; StringRef ABIName; const llvm::Triple &Triple = getToolChain().getTriple(); - getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); StringRef FloatABI = getMipsFloatABI(D, Args); - bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; - - if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { + if (FloatABI == "soft") { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("soft"); - - if (FloatABI == "hard" && IsMips16) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-mips16-hard-float"); - } } else { // Floating point operations and argument passing are hard. @@ -1167,6 +1179,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("power6", "pwr6") .Case("power6x", "pwr6x") .Case("power7", "pwr7") + .Case("power8", "pwr8") .Case("pwr3", "pwr3") .Case("pwr4", "pwr4") .Case("pwr5", "pwr5") @@ -1174,6 +1187,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("pwr6", "pwr6") .Case("pwr6x", "pwr6x") .Case("pwr7", "pwr7") + .Case("pwr8", "pwr8") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Case("powerpc64le", "ppc64le") @@ -1247,7 +1261,7 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); - // Select the float ABI as determined by -msoft-float, -mhard-float, and + // Select the float ABI as determined by -msoft-float and -mhard-float. StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { @@ -1305,7 +1319,7 @@ static const char *getX86TargetCPU(const ArgList &Args, if (Triple.getArch() != llvm::Triple::x86_64 && Triple.getArch() != llvm::Triple::x86) - return 0; // This routine is only handling x86 targets. + return nullptr; // This routine is only handling x86 targets. bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; @@ -1316,10 +1330,9 @@ static const char *getX86TargetCPU(const ArgList &Args, return Is64Bit ? "core2" : "yonah"; } - // All x86 devices running Android have core2 as their common - // denominator. This makes a better choice than pentium4. + // On Android use targets compatible with gcc if (Triple.getEnvironment() == llvm::Triple::Android) - return "core2"; + return Is64Bit ? "x86-64" : "i686"; // Everything else goes to x86-64 in 64-bit mode. if (Is64Bit) @@ -1346,11 +1359,16 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { return ""; case llvm::Triple::aarch64: - return getAArch64TargetCPU(Args, T); + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64: + case llvm::Triple::arm64_be: + return getAArch64TargetCPU(Args); case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::thumb: - return getARMTargetCPU(Args, T); + case llvm::Triple::thumbeb: + return arm::getARMTargetCPU(Args, T); case llvm::Triple::mips: case llvm::Triple::mipsel: @@ -1358,7 +1376,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, T, CPUName, ABIName); + mips::getMipsCPUAndABI(Args, T, CPUName, ABIName); return CPUName; } @@ -1401,7 +1419,26 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { } } -static void getX86TargetFeatures(const llvm::Triple &Triple, +static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, + ArgStringList &CmdArgs) { + // Tell the linker to load the plugin. This has to come before AddLinkerInputs + // as gold requires -plugin to come before any -plugin-opt that -Wl might + // forward. + CmdArgs.push_back("-plugin"); + std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; + CmdArgs.push_back(Args.MakeArgString(Plugin)); + + // Try to pass driver level flags relevant to LTO code generation down to + // the plugin. + + // Handle flags for selecting CPU variants. + std::string CPU = getCPUName(Args, ToolChain.getTriple()); + if (!CPU.empty()) + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); +} + +static void getX86TargetFeatures(const Driver & D, + const llvm::Triple &Triple, const ArgList &Args, std::vector<const char *> &Features) { if (Triple.getArchName() == "x86_64h") { @@ -1415,6 +1452,40 @@ static void getX86TargetFeatures(const llvm::Triple &Triple, Features.push_back("-fsgsbase"); } + // Add features to comply with gcc on Android + if (Triple.getEnvironment() == llvm::Triple::Android) { + if (Triple.getArch() == llvm::Triple::x86_64) { + Features.push_back("+sse4.2"); + Features.push_back("+popcnt"); + } else + Features.push_back("+ssse3"); + } + + // Set features according to the -arch flag on MSVC + if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { + StringRef Arch = A->getValue(); + bool ArchUsed = false; + // First, look for flags that are shared in x86 and x86-64. + if (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::x86) { + if (Arch == "AVX" || Arch == "AVX2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + // Then, look for x86-specific flags. + if (Triple.getArch() == llvm::Triple::x86) { + if (Arch == "IA32") { + ArchUsed = true; + } else if (Arch == "SSE" || Arch == "SSE2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + if (!ArchUsed) + D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args); + } + // Now add any that the user explicitly requested on the command line, // which may override the defaults. for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group), @@ -1458,6 +1529,17 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } if (NoImplicitFloat) CmdArgs.push_back("-no-implicit-float"); + + if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) { + StringRef Value = A->getValue(); + if (Value == "intel" || Value == "att") { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value)); + } else { + getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Value; + } + } } static inline bool HasPICArg(const ArgList &Args) { @@ -1505,15 +1587,146 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, CmdArgs.push_back ("-machine-sink-split=0"); } +// Decode AArch64 features from string like +[no]featureA+[no]featureB+... +static bool DecodeAArch64Features(const Driver &D, const StringRef &text, + std::vector<const char *> &Features) { + SmallVector<StringRef, 8> Split; + text.split(Split, StringRef("+"), -1, false); + + for (unsigned I = 0, E = Split.size(); I != E; ++I) { + const char *result = llvm::StringSwitch<const char *>(Split[I]) + .Case("fp", "+fp-armv8") + .Case("simd", "+neon") + .Case("crc", "+crc") + .Case("crypto", "+crypto") + .Case("nofp", "-fp-armv8") + .Case("nosimd", "-neon") + .Case("nocrc", "-crc") + .Case("nocrypto", "-crypto") + .Default(nullptr); + if (result) + Features.push_back(result); + else if (Split[I] == "neon" || Split[I] == "noneon") + D.Diag(diag::err_drv_no_neon_modifier); + else + return false; + } + return true; +} + +// Check if the CPU name and feature modifiers in -mcpu are legal. If yes, +// decode CPU and feature. +static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, + std::vector<const char *> &Features) { + std::pair<StringRef, StringRef> Split = Mcpu.split("+"); + CPU = Split.first; + if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") { + Features.push_back("+neon"); + Features.push_back("+crc"); + Features.push_back("+crypto"); + } else if (CPU == "generic") { + Features.push_back("+neon"); + } else { + return false; + } + + if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) + return false; + + return true; +} + +static bool +getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, + const ArgList &Args, + std::vector<const char *> &Features) { + std::pair<StringRef, StringRef> Split = March.split("+"); + if (Split.first != "armv8-a") + return false; + + if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) + return false; + + return true; +} + +static bool +getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, + const ArgList &Args, + std::vector<const char *> &Features) { + StringRef CPU; + if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features)) + return false; + + return true; +} + +static bool +getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune, + const ArgList &Args, + std::vector<const char *> &Features) { + // Handle CPU name is 'native'. + if (Mtune == "native") + Mtune = llvm::sys::getHostCPUName(); + if (Mtune == "cyclone") { + Features.push_back("+zcm"); + Features.push_back("+zcz"); + } + return true; +} + +static bool +getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, + const ArgList &Args, + std::vector<const char *> &Features) { + StringRef CPU; + std::vector<const char *> DecodedFeature; + if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature)) + return false; + + return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features); +} + static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, std::vector<const char *> &Features) { - // Honor -mfpu=. - if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) - getAArch64FPUFeatures(D, A, Args, Features); + Arg *A; + bool success = true; + // Enable NEON by default. + Features.push_back("+neon"); + if ((A = Args.getLastArg(options::OPT_march_EQ))) + success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); + else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) + success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + + if (success && (A = Args.getLastArg(options::OPT_mtune_EQ))) + success = + getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features); + else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) + success = + getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + + if (!success) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + + if (Args.getLastArg(options::OPT_mgeneral_regs_only)) { + Features.push_back("-fp-armv8"); + Features.push_back("-crypto"); + Features.push_back("-neon"); + } + + // En/disable crc + if (Arg *A = Args.getLastArg(options::OPT_mcrc, + options::OPT_mnocrc)) { + if (A->getOption().matches(options::OPT_mcrc)) + Features.push_back("+crc"); + else + Features.push_back("-crc"); + } } static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args, ArgStringList &CmdArgs) { + const ArgList &Args, ArgStringList &CmdArgs, + bool ForAS) { std::vector<const char *> Features; switch (Triple.getArch()) { default: @@ -1522,12 +1735,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: - getMIPSTargetFeatures(D, Args, Features); + getMIPSTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::thumb: - getARMTargetFeatures(D, Triple, Args, Features); + case llvm::Triple::thumbeb: + getARMTargetFeatures(D, Triple, Args, Features, ForAS); break; case llvm::Triple::ppc: @@ -1539,11 +1754,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, getSparcTargetFeatures(Args, Features); break; case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64: + case llvm::Triple::arm64_be: getAArch64TargetFeatures(D, Args, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - getX86TargetFeatures(Triple, Args, Features); + getX86TargetFeatures(D, Triple, Args, Features); break; } @@ -1578,7 +1796,7 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, if (runtime.isNonFragile()) return true; - if (!Triple.isOSDarwin()) + if (!Triple.isMacOSX()) return false; return (!Triple.isMacOSXVersionLT(10,5) && @@ -1586,6 +1804,45 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, Triple.getArch() == llvm::Triple::arm)); } +namespace { + struct ExceptionSettings { + bool ExceptionsEnabled; + bool ShouldUseExceptionTables; + ExceptionSettings() : ExceptionsEnabled(false), + ShouldUseExceptionTables(false) {} + }; +} // end anonymous namespace. + +// exceptionSettings() exists to share the logic between -cc1 and linker +// invocations. +static ExceptionSettings exceptionSettings(const ArgList &Args, + const llvm::Triple &Triple) { + ExceptionSettings ES; + + // Are exceptions enabled by default? + ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore); + + // This keeps track of whether exceptions were explicitly turned on or off. + bool DidHaveExplicitExceptionFlag = false; + + if (Arg *A = Args.getLastArg(options::OPT_fexceptions, + options::OPT_fno_exceptions)) { + if (A->getOption().matches(options::OPT_fexceptions)) + ES.ExceptionsEnabled = true; + else + ES.ExceptionsEnabled = false; + + DidHaveExplicitExceptionFlag = true; + } + + // Exception tables and cleanups can be enabled with -fexceptions even if the + // language itself doesn't support exceptions. + if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag) + ES.ShouldUseExceptionTables = true; + + return ES; +} + /// addExceptionArgs - Adds exception related arguments to the driver command /// arguments. There's a master flag, -fexceptions and also language specific /// flags to enable/disable C++ and Objective-C exceptions. @@ -1608,28 +1865,8 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, return; } - // Exceptions are enabled by default. - bool ExceptionsEnabled = true; - - // This keeps track of whether exceptions were explicitly turned on or off. - bool DidHaveExplicitExceptionFlag = false; - - if (Arg *A = Args.getLastArg(options::OPT_fexceptions, - options::OPT_fno_exceptions)) { - if (A->getOption().matches(options::OPT_fexceptions)) - ExceptionsEnabled = true; - else - ExceptionsEnabled = false; - - DidHaveExplicitExceptionFlag = true; - } - - bool ShouldUseExceptionTables = false; - - // Exception tables and cleanups can be enabled with -fexceptions even if the - // language itself doesn't support exceptions. - if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) - ShouldUseExceptionTables = true; + // Gather the exception settings from the command line arguments. + ExceptionSettings ES = exceptionSettings(Args, Triple); // Obj-C exceptions are enabled by default, regardless of -fexceptions. This // is not necessarily sensible, but follows GCC. @@ -1639,12 +1876,12 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, true)) { CmdArgs.push_back("-fobjc-exceptions"); - ShouldUseExceptionTables |= + ES.ShouldUseExceptionTables |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); } if (types::isCXX(InputType)) { - bool CXXExceptionsEnabled = ExceptionsEnabled; + bool CXXExceptionsEnabled = ES.ExceptionsEnabled; if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, @@ -1659,11 +1896,11 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, if (CXXExceptionsEnabled) { CmdArgs.push_back("-fcxx-exceptions"); - ShouldUseExceptionTables = true; + ES.ShouldUseExceptionTables = true; } } - if (ShouldUseExceptionTables) + if (ES.ShouldUseExceptionTables) CmdArgs.push_back("-fexceptions"); } @@ -1679,19 +1916,6 @@ static bool ShouldDisableAutolink(const ArgList &Args, Default); } -static bool ShouldDisableCFI(const ArgList &Args, - const ToolChain &TC) { - bool Default = true; - if (TC.getTriple().isOSDarwin()) { - // The native darwin assembler doesn't support cfi directives, so - // we disable them if we think the .s file will be passed to it. - Default = TC.useIntegratedAs(); - } - return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, - options::OPT_fno_dwarf2_cfi_asm, - Default); -} - static bool ShouldDisableDwarfDirectory(const ArgList &Args, const ToolChain &TC) { bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm, @@ -1705,8 +1929,8 @@ static bool ContainsCompileAction(const Action *A) { if (isa<CompileJobAction>(A)) return true; - for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it) - if (ContainsCompileAction(*it)) + for (const auto &Act : *A) + if (ContainsCompileAction(Act)) return true; return false; @@ -1722,9 +1946,8 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { if (RelaxDefault) { RelaxDefault = false; - for (ActionList::const_iterator it = C.getActions().begin(), - ie = C.getActions().end(); it != ie; ++it) { - if (ContainsCompileAction(*it)) { + for (const auto &Act : C.getActions()) { + if (ContainsCompileAction(Act)) { RelaxDefault = true; break; } @@ -1751,6 +1974,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // When using an integrated assembler, translate -Wa, and -Xassembler // options. + bool CompressDebugSections = false; for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA, options::OPT_Xassembler), ie = Args.filtered_end(); it != ie; ++it) { @@ -1774,48 +1998,116 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-fatal-assembler-warnings"); } else if (Value == "--noexecstack") { CmdArgs.push_back("-mnoexecstack"); + } else if (Value == "-compress-debug-sections" || + Value == "--compress-debug-sections") { + CompressDebugSections = true; + } else if (Value == "-nocompress-debug-sections" || + Value == "--nocompress-debug-sections") { + CompressDebugSections = false; } else if (Value.startswith("-I")) { CmdArgs.push_back(Value.data()); // We need to consume the next argument if the current arg is a plain // -I. The next arg will be the include directory. if (Value == "-I") TakeNextArg = true; + } else if (Value.startswith("-gdwarf-")) { + CmdArgs.push_back(Value.data()); } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; } } } + if (CompressDebugSections) { + if (llvm::zlib::isAvailable()) + CmdArgs.push_back("-compress-debug-sections"); + else + D.Diag(diag::warn_debug_compression_unavailable); + } +} + +// Until ARM libraries are build separately, we have them all in one library +static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) { + if (TC.getArch() == llvm::Triple::arm || + TC.getArch() == llvm::Triple::armeb) + return "arm"; + else + return TC.getArchName(); } -static void addProfileRTLinux( +static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) { + // The runtimes are located in the OS-specific resource directory. + SmallString<128> Res(TC.getDriver().ResourceDir); + const llvm::Triple &Triple = TC.getTriple(); + // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected. + StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ? + "freebsd" : TC.getOS(); + llvm::sys::path::append(Res, "lib", OSLibName); + return Res; +} + +// This adds the static libclang_rt.builtins-arch.a directly to the command line +// FIXME: Make sure we can also emit shared objects if they're requested +// and available, check for possible errors, etc. +static void addClangRTLinux( + const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { + SmallString<128> LibClangRT = getCompilerRTLibDir(TC); + llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") + + getArchNameForCompilerRTLib(TC) + + ".a"); + + CmdArgs.push_back(Args.MakeArgString(LibClangRT)); + CmdArgs.push_back("-lgcc_s"); + if (TC.getDriver().CCCIsCXX()) + CmdArgs.push_back("-lgcc_eh"); +} + +static void addProfileRT( const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!(Args.hasArg(options::OPT_fprofile_arcs) || Args.hasArg(options::OPT_fprofile_generate) || + Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fcreate_profile) || Args.hasArg(options::OPT_coverage))) return; - // 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"); + // -fprofile-instr-generate requires position-independent code to build with + // shared objects. Link against the right archive. + const char *Lib = "libclang_rt.profile-"; + if (Args.hasArg(options::OPT_fprofile_instr_generate) && + Args.hasArg(options::OPT_shared)) + Lib = "libclang_rt.profile-pic-"; + + SmallString<128> LibProfile = getCompilerRTLibDir(TC); + llvm::sys::path::append(LibProfile, + Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a"); CmdArgs.push_back(Args.MakeArgString(LibProfile)); } -static void addSanitizerRTLinkFlagsLinux( - const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, - const StringRef Sanitizer, bool BeforeLibStdCXX, - bool ExportSymbols = true) { - // Sanitizer runtime is located in the Linux library directory and - // has name "libclang_rt.<Sanitizer>-<ArchName>.a". - SmallString<128> LibSanitizer(TC.getDriver().ResourceDir); - llvm::sys::path::append( - LibSanitizer, "lib", "linux", - (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a")); +static SmallString<128> getSanitizerRTLibName(const ToolChain &TC, + const StringRef Sanitizer, + bool Shared) { + // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}" + // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android) + const char *EnvSuffix = + TC.getTriple().getEnvironment() == llvm::Triple::Android ? "-android" : ""; + SmallString<128> LibSanitizer = getCompilerRTLibDir(TC); + llvm::sys::path::append(LibSanitizer, + Twine("libclang_rt.") + Sanitizer + "-" + + getArchNameForCompilerRTLib(TC) + EnvSuffix + + (Shared ? ".so" : ".a")); + return LibSanitizer; +} + +static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, + const StringRef Sanitizer, + bool BeforeLibStdCXX, + bool ExportSymbols = true, + bool LinkDeps = true) { + SmallString<128> LibSanitizer = + getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false); // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a, // etc.) so that the linker picks custom versions of the global 'operator @@ -1831,10 +2123,15 @@ static void addSanitizerRTLinkFlagsLinux( CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(), LibSanitizerArgs.begin(), LibSanitizerArgs.end()); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-lrt"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-lm"); + if (LinkDeps) { + // Link sanitizer dependencies explicitly + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-lrt"); + CmdArgs.push_back("-lm"); + // There's no libdl on FreeBSD. + if (TC.getTriple().getOS() != llvm::Triple::FreeBSD) + CmdArgs.push_back("-ldl"); + } // If possible, use a dynamic symbols file to export the symbols from the // runtime library. If we can't do so, use -export-dynamic instead to export @@ -1850,66 +2147,102 @@ static void addSanitizerRTLinkFlagsLinux( /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). -static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (TC.getTriple().getEnvironment() == llvm::Triple::Android) { - SmallString<128> LibAsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibAsan, "lib", "linux", - (Twine("libclang_rt.asan-") + - TC.getArchName() + "-android.so")); - CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan)); +static void addAsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, bool Shared, bool IsCXX) { + if (Shared) { + // Link dynamic runtime if necessary. + SmallString<128> LibSanitizer = + getSanitizerRTLibName(TC, "asan", Shared); + CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer)); + } + + // Do not link static runtime to DSOs or if compiling for Android. + if (Args.hasArg(options::OPT_shared) || + (TC.getTriple().getEnvironment() == llvm::Triple::Android)) + return; + + if (Shared) { + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit", + /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false, + /*LinkDeps*/ false); } else { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true); + if (IsCXX) + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true); } } /// If ThreadSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). -static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addTsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true); } /// If MemorySanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). -static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addMsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true); } /// If LeakSanitizer is enabled, add appropriate linker flags (Linux). /// This needs to be called before we add the C run-time (malloc, etc). -static void addLsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addLsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true); } /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags /// (Linux). -static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, bool IsCXX, - bool HasOtherSanitizerRt) { +static void addUbsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, bool IsCXX, + bool HasOtherSanitizerRt) { + // Do not link runtime into shared libraries. + if (Args.hasArg(options::OPT_shared)) + return; + // Need a copy of sanitizer_common. This could come from another sanitizer // runtime; if we're not including one, include our own copy. if (!HasOtherSanitizerRt) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false); - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true); // Only include the bits of the runtime which need a C++ ABI library if // we're linking in C++ mode. if (IsCXX) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true); } -static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addDfsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true); +} + +// Should be called before we add C++ ABI library. +static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + const Driver &D = TC.getDriver(); + if (Sanitize.needsUbsanRt()) + addUbsanRT(TC, Args, CmdArgs, D.CCCIsCXX(), + Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || + Sanitize.needsMsanRt() || Sanitize.needsLsanRt()); + if (Sanitize.needsAsanRt()) + addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX()); + if (Sanitize.needsTsanRt()) + addTsanRT(TC, Args, CmdArgs); + if (Sanitize.needsMsanRt()) + addMsanRT(TC, Args, CmdArgs); + if (Sanitize.needsLsanRt()) + addLsanRT(TC, Args, CmdArgs); + if (Sanitize.needsDfsanRt()) + addDfsanRT(TC, Args, CmdArgs); } static bool shouldUseFramePointerForTarget(const ArgList &Args, @@ -1971,7 +2304,8 @@ static const char *SplitDebugName(const ArgList &Args, return Args.MakeArgString(T); } else { // Use the compilation dir. - SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); + SmallString<128> T( + Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput())); llvm::sys::path::replace_extension(F, "dwo"); T += F; @@ -2005,7 +2339,8 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, } /// \brief Vectorize at all optimization levels greater than 1 except for -Oz. -static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { +/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled. +static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) { if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O4) || A->getOption().matches(options::OPT_Ofast)) @@ -2021,9 +2356,9 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { if (S == "s") return true; - // Don't vectorize -Oz. + // Don't vectorize -Oz, unless it's the slp vectorizer. if (S == "z") - return false; + return isSlpVec; unsigned OptLevel = 0; if (S.getAsInteger(10, OptLevel)) @@ -2035,6 +2370,41 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { return false; } +/// Add -x lang to \p CmdArgs for \p Input. +static void addDashXForInput(const ArgList &Args, const InputInfo &Input, + ArgStringList &CmdArgs) { + // When using -verify-pch, we don't want to provide the type + // 'precompiled-header' if it was inferred from the file extension + if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH) + return; + + CmdArgs.push_back("-x"); + if (Args.hasArg(options::OPT_rewrite_objc)) + CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); + else + CmdArgs.push_back(types::getTypeName(Input.getType())); +} + +static std::string getMSCompatibilityVersion(const char *VersionStr) { + unsigned Version; + if (StringRef(VersionStr).getAsInteger(10, Version)) + return "0"; + + if (Version < 100) + return llvm::utostr_32(Version) + ".0"; + + if (Version < 10000) + return llvm::utostr_32(Version / 100) + "." + + llvm::utostr_32(Version % 100); + + unsigned Build = 0, Factor = 1; + for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10) + Build = Build + (Version % 10) * Factor; + return llvm::utostr_32(Version / 100) + "." + + llvm::utostr_32(Version % 100) + "." + + llvm::utostr_32(Build); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2045,6 +2415,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment(); + bool IsWindowsCygnus = + getToolChain().getTriple().isWindowsCygwinEnvironment(); + bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment(); + assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); // Invoke ourselves in -cc1 mode. @@ -2057,6 +2432,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); CmdArgs.push_back(Args.MakeArgString(TripleStr)); + const llvm::Triple TT(TripleStr); + if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm || + TT.getArch() == llvm::Triple::thumb)) { + unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6; + unsigned Version; + TT.getArchName().substr(Offset).getAsInteger(10, Version); + if (Version < 7) + D.Diag(diag::err_target_unsupported_arch) << TT.getArchName() + << TripleStr; + } + + // Push all default warning arguments that are specific to + // the given target. These come before user provided warning options + // are provided. + getToolChain().addClangWarningOptions(CmdArgs); + // Select the appropriate action. RewriteKind rewriteKind = RK_None; @@ -2091,6 +2482,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-emit-pch"); else CmdArgs.push_back("-emit-pth"); + } else if (isa<VerifyPCHJobAction>(JA)) { + CmdArgs.push_back("-verify-pch"); } else { assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool."); @@ -2120,8 +2513,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // The make clang go fast button. - CmdArgs.push_back("-disable-free"); + // We normally speed up the clang process a bit by skipping destructors at + // exit, but when we're generating diagnostics we can rely on some of the + // cleanup. + if (!C.isForDiagnostics()) + CmdArgs.push_back("-disable-free"); // Disable the verification pass in -asserts builds. #ifdef NDEBUG @@ -2151,7 +2547,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); - if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) + if (!IsWindowsMSVC) CmdArgs.push_back("-analyzer-checker=unix"); if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) @@ -2162,8 +2558,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (types::isCXX(Inputs[0].getType())) CmdArgs.push_back("-analyzer-checker=cplusplus"); - // Enable the following experimental checkers for testing. - CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn"); + // Enable the following experimental checkers for testing. + CmdArgs.push_back( + "-analyzer-checker=security.insecureAPI.UncheckedReturn"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); @@ -2194,6 +2591,54 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool PIC = PIE || getToolChain().isPICDefault(); bool IsPICLevelTwo = PIC; + // Android-specific defaults for PIC/PIE + if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) { + switch (getToolChain().getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + case llvm::Triple::aarch64: + case llvm::Triple::arm64: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + PIC = true; // "-fpic" + break; + + case llvm::Triple::x86: + case llvm::Triple::x86_64: + PIC = true; // "-fPIC" + IsPICLevelTwo = true; + break; + + default: + break; + } + } + + // OpenBSD-specific defaults for PIE + if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) { + switch (getToolChain().getTriple().getArch()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::sparc: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + IsPICLevelTwo = false; // "-fpie" + break; + + case llvm::Triple::ppc: + case llvm::Triple::sparcv9: + IsPICLevelTwo = true; // "-fPIE" + break; + + default: + break; + } + } + // For the PIC and PIE flag options, this logic is different from the // legacy logic in very old versions of GCC, as that logic was just // a bug no one had ever fixed. This logic is both more rational and @@ -2234,8 +2679,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Note that these flags are trump-cards. Regardless of the order w.r.t. the // PIC or PIE options above, if these show up, PIC is disabled. llvm::Triple Triple(TripleStr); - if (KernelOrKext && - (!Triple.isiOS() || Triple.isOSVersionLT(6))) + if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) || + Triple.getArch() == llvm::Triple::arm64 || + Triple.getArch() == llvm::Triple::aarch64)) PIC = PIE = false; if (Args.hasArg(options::OPT_static)) PIC = PIE = false; @@ -2281,6 +2727,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // LLVM Code Generator Options. + if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) { + StringRef v = A->getValue(); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v)); + A->claim(); + } + if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) { CmdArgs.push_back("-mregparm"); CmdArgs.push_back(A->getValue()); @@ -2313,8 +2766,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // enabled. This alias option is being used to simplify the hasFlag logic. OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing; + // We turn strict aliasing off by default if we're in CL mode, since MSVC + // doesn't do any TBAA. + bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode(); if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption, - options::OPT_fno_strict_aliasing, true)) + options::OPT_fno_strict_aliasing, TBAAOnByDefault)) CmdArgs.push_back("-relaxed-aliasing"); if (!Args.hasFlag(options::OPT_fstruct_path_tbaa, options::OPT_fno_struct_path_tbaa)) @@ -2461,18 +2917,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_fast_math)) if (!A->getOption().matches(options::OPT_fno_fast_math)) CmdArgs.push_back("-ffast-math"); - if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math)) + if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, + options::OPT_fno_fast_math)) if (A->getOption().matches(options::OPT_ffinite_math_only)) CmdArgs.push_back("-ffinite-math-only"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. - bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault(); + bool IsIntegratedAssemblerDefault = + getToolChain().IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, - IsVerboseAsmDefault) || + IsIntegratedAssemblerDefault) || Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); + if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as, + IsIntegratedAssemblerDefault)) + CmdArgs.push_back("-no-integrated-as"); + if (Args.hasArg(options::OPT_fdebug_pass_structure)) { CmdArgs.push_back("-mdebug-pass"); CmdArgs.push_back("Structure"); @@ -2500,10 +2962,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more // complicated ways. bool AsynchronousUnwindTables = - Args.hasFlag(options::OPT_fasynchronous_unwind_tables, - options::OPT_fno_asynchronous_unwind_tables, - getToolChain().IsUnwindTablesDefault() && - !KernelOrKext); + Args.hasFlag(options::OPT_fasynchronous_unwind_tables, + options::OPT_fno_asynchronous_unwind_tables, + (getToolChain().IsUnwindTablesDefault() || + getToolChain().getSanitizerArgs().needsUnwindTables()) && + !KernelOrKext); if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); @@ -2538,7 +3001,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Add the target features - getTargetFeatures(D, ETriple, Args, CmdArgs); + getTargetFeatures(D, ETriple, Args, CmdArgs, false); // Add target specific flags. switch(getToolChain().getArch()) { @@ -2546,10 +3009,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::thumb: + case llvm::Triple::thumbeb: AddARMTargetArgs(Args, CmdArgs, KernelOrKext); break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm64: + case llvm::Triple::arm64_be: + AddAArch64TargetArgs(Args, CmdArgs); + break; + case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -2558,6 +3030,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::sparc: + case llvm::Triple::sparcv9: AddSparcTargetArgs(Args, CmdArgs); break; @@ -2615,13 +3088,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.CCLogDiagnosticsFilename : "-"); } - // Use the last option from "-g" group. "-gline-tables-only" - // is preserved, all other debug options are substituted with "-g". + // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x" + // are preserved, all other debug options are substituted with "-g". Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) { - if (A->getOption().matches(options::OPT_gline_tables_only)) + if (A->getOption().matches(options::OPT_gline_tables_only)) { + // FIXME: we should support specifying dwarf version with + // -gline-tables-only. CmdArgs.push_back("-gline-tables-only"); - else if (A->getOption().matches(options::OPT_gdwarf_2)) + // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD. + const llvm::Triple &Triple = getToolChain().getTriple(); + if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD || + Triple.getOS() == llvm::Triple::FreeBSD) + CmdArgs.push_back("-gdwarf-2"); + } else if (A->getOption().matches(options::OPT_gdwarf_2)) CmdArgs.push_back("-gdwarf-2"); else if (A->getOption().matches(options::OPT_gdwarf_3)) CmdArgs.push_back("-gdwarf-3"); @@ -2629,9 +3109,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-gdwarf-4"); else if (!A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_ggdb0)) { - // Default is dwarf-2 for darwin and FreeBSD. + // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD. const llvm::Triple &Triple = getToolChain().getTriple(); - if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::FreeBSD) + if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD || + Triple.getOS() == llvm::Triple::FreeBSD) CmdArgs.push_back("-gdwarf-2"); else CmdArgs.push_back("-g"); @@ -2640,7 +3121,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. Args.ClaimAllArgs(options::OPT_g_flags_Group); - if (Args.hasArg(options::OPT_gcolumn_info)) + if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info, + /*Default*/ true)) CmdArgs.push_back("-dwarf-column-info"); // FIXME: Move backend command line options to the module. @@ -2660,13 +3142,44 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-generate-gnu-dwarf-pub-sections"); } - Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section); + // -gdwarf-aranges turns on the emission of the aranges section in the + // backend. + if (Args.hasArg(options::OPT_gdwarf_aranges)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-generate-arange-section"); + } - Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); - Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); + if (Args.hasFlag(options::OPT_fdebug_types_section, + options::OPT_fno_debug_types_section, false)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-generate-type-units"); + } + + if (Args.hasFlag(options::OPT_ffunction_sections, + options::OPT_fno_function_sections, false)) { + CmdArgs.push_back("-ffunction-sections"); + } + + if (Args.hasFlag(options::OPT_fdata_sections, + options::OPT_fno_data_sections, false)) { + CmdArgs.push_back("-fdata-sections"); + } Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); + if (Args.hasArg(options::OPT_fprofile_instr_generate) && + (Args.hasArg(options::OPT_fprofile_instr_use) || + Args.hasArg(options::OPT_fprofile_instr_use_EQ))) + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fprofile-instr-generate" << "-fprofile-instr-use"; + + Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate); + + if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ)) + A->render(Args, CmdArgs); + else if (Args.hasArg(options::OPT_fprofile_instr_use)) + CmdArgs.push_back("-fprofile-instr-use=pgo-data"); + if (Args.hasArg(options::OPT_ftest_coverage) || Args.hasArg(options::OPT_coverage)) CmdArgs.push_back("-femit-coverage-notes"); @@ -2772,7 +3285,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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); + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init); + Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path); } // Add preprocessing options like -I, -D, etc. if we are using the @@ -2798,10 +3312,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + // Warn about ignored options to clang. + for (arg_iterator it = Args.filtered_begin( + options::OPT_clang_ignored_gcc_optimization_f_Group), + ie = Args.filtered_end(); it != ie; ++it) { + D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args); + } + // Don't warn about unused -flto. This can happen when we're preprocessing or // precompiling. Args.ClaimAllArgs(options::OPT_flto); + Args.AddAllArgs(CmdArgs, options::OPT_R_Group); Args.AddAllArgs(CmdArgs, options::OPT_W_Group); if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false)) CmdArgs.push_back("-pedantic"); @@ -2836,7 +3358,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!types::isCXX(InputType)) Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=", /*Joined=*/true); - else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32) + else if (IsWindowsMSVC) CmdArgs.push_back("-std=c++11"); Args.AddLastArg(CmdArgs, options::OPT_trigraphs); @@ -2852,9 +3374,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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) + // FIXME: This should behave just like a warning flag, and thus should also + // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on. + Arg *WriteStrings = + Args.getLastArg(options::OPT_Wwrite_strings, + options::OPT_Wno_write_strings, options::OPT_w); + if (WriteStrings && + WriteStrings->getOption().matches(options::OPT_Wwrite_strings)) CmdArgs.push_back("-fconst-strings"); } @@ -2875,9 +3401,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } - if (ShouldDisableCFI(Args, getToolChain())) - CmdArgs.push_back("-fno-dwarf2-cfi-asm"); - if (ShouldDisableDwarfDirectory(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf-directory-asm"); @@ -3014,8 +3537,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, true)) CmdArgs.push_back("-fno-sanitize-recover"); - if (Args.hasArg(options::OPT_fcatch_undefined_behavior) || - Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, options::OPT_fno_sanitize_undefined_trap_on_error, false)) CmdArgs.push_back("-fsanitize-undefined-trap-on-error"); @@ -3038,10 +3560,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.getLastArg(options::OPT_fapple_kext)) CmdArgs.push_back("-fapple-kext"); - if (Args.hasFlag(options::OPT_frewrite_includes, - options::OPT_fno_rewrite_includes, false)) - CmdArgs.push_back("-frewrite-includes"); - Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); @@ -3083,11 +3601,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, unsigned StackProtectorLevel = 0; if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, options::OPT_fstack_protector_all, + options::OPT_fstack_protector_strong, options::OPT_fstack_protector)) { - if (A->getOption().matches(options::OPT_fstack_protector)) - StackProtectorLevel = 1; + if (A->getOption().matches(options::OPT_fstack_protector)) { + StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn, + getToolChain().GetDefaultStackProtectorLevel(KernelOrKext)); + } else if (A->getOption().matches(options::OPT_fstack_protector_strong)) + StackProtectorLevel = LangOptions::SSPStrong; else if (A->getOption().matches(options::OPT_fstack_protector_all)) - StackProtectorLevel = 2; + StackProtectorLevel = LangOptions::SSPReq; } else { StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel(KernelOrKext); @@ -3132,10 +3654,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_munaligned_access)) { if (A->getOption().matches(options::OPT_mno_unaligned_access)) { CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-strict-align"); + if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || + getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be || + getToolChain().getTriple().getArch() == llvm::Triple::arm64 || + getToolChain().getTriple().getArch() == llvm::Triple::arm64_be) + CmdArgs.push_back("-aarch64-strict-align"); + else + CmdArgs.push_back("-arm-strict-align"); } else { CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-no-strict-align"); + if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || + getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be || + getToolChain().getTriple().getArch() == llvm::Triple::arm64 || + getToolChain().getTriple().getArch() == llvm::Triple::arm64_be) + CmdArgs.push_back("-aarch64-no-strict-align"); + else + CmdArgs.push_back("-arm-no-strict-align"); } } } @@ -3149,6 +3683,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-no-restrict-it"); } + } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm || + TT.getArch() == llvm::Triple::thumb)) { + // Windows on ARM expects restricted IT blocks + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-restrict-it"); + } + + if (TT.getArch() == llvm::Triple::arm || + TT.getArch() == llvm::Triple::thumb) { + if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, + options::OPT_mno_long_calls)) { + if (A->getOption().matches(options::OPT_mlong_calls)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-long-calls"); + } + } } // Forward -f options with positive and negative forms; we translate @@ -3218,44 +3768,78 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fmodules-decluse"); } + // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that + // all #included headers are part of modules. + if (Args.hasFlag(options::OPT_fmodules_strict_decluse, + options::OPT_fno_modules_strict_decluse, + false)) { + CmdArgs.push_back("-fmodules-strict-decluse"); + } + // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). - if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) { - A->claim(); + if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) A->render(Args, CmdArgs); - } // -fmodule-map-file can be used to specify a file containing module // definitions. - if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) { - A->claim(); + if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) A->render(Args, CmdArgs); - } - // If a module path was provided, pass it along. Otherwise, use a temporary - // directory. - if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) { - A->claim(); - if (HaveModules) { - A->render(Args, CmdArgs); + // -fmodule-cache-path specifies where our module files should be written. + SmallString<128> ModuleCachePath; + if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) + ModuleCachePath = A->getValue(); + if (HaveModules) { + if (C.isForDiagnostics()) { + // When generating crash reports, we want to emit the modules along with + // the reproduction sources, so we ignore any provided module path. + ModuleCachePath = Output.getFilename(); + llvm::sys::path::replace_extension(ModuleCachePath, ".cache"); + llvm::sys::path::append(ModuleCachePath, "modules"); + } else if (ModuleCachePath.empty()) { + // No module path was provided: use the default. + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, + ModuleCachePath); + llvm::sys::path::append(ModuleCachePath, "org.llvm.clang"); + llvm::sys::path::append(ModuleCachePath, "ModuleCache"); } - } else if (HaveModules) { - SmallString<128> DefaultModuleCache; - llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, - DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); - llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); const char Arg[] = "-fmodules-cache-path="; - DefaultModuleCache.insert(DefaultModuleCache.begin(), - Arg, Arg + strlen(Arg)); - CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); + ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg)); + CmdArgs.push_back(Args.MakeArgString(ModuleCachePath)); } + // When building modules and generating crashdumps, we need to dump a module + // dependency VFS alongside the output. + if (HaveModules && C.isForDiagnostics()) { + SmallString<128> VFSDir(Output.getFilename()); + llvm::sys::path::replace_extension(VFSDir, ".cache"); + llvm::sys::path::append(VFSDir, "vfs"); + CmdArgs.push_back("-module-dependency-dir"); + CmdArgs.push_back(Args.MakeArgString(VFSDir)); + } + + if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path)) + if (HaveModules) + A->render(Args, CmdArgs); + // Pass through all -fmodules-ignore-macro arguments. Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval); Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after); + Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp); + + if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) { + if (!Args.getLastArg(options::OPT_fbuild_session_timestamp)) + D.Diag(diag::err_drv_modules_validate_once_requires_timestamp); + + Args.AddLastArg(CmdArgs, + options::OPT_fmodules_validate_once_per_build_session); + } + + Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers); + // -faccess-control is default. if (Args.hasFlag(options::OPT_fno_access_control, options::OPT_faccess_control, @@ -3302,41 +3886,52 @@ 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().getArch() != llvm::Triple::hexagon && - getToolChain().getArch() != llvm::Triple::xcore) || + if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, + options::OPT_fno_use_cxa_atexit, + !IsWindowsCygnus && !IsWindowsGNU && + getToolChain().getArch() != llvm::Triple::hexagon && + getToolChain().getArch() != llvm::Triple::xcore) || KernelOrKext) CmdArgs.push_back("-fno-use-cxa-atexit"); // -fms-extensions=0 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + IsWindowsMSVC)) CmdArgs.push_back("-fms-extensions"); // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, - (getToolChain().getTriple().getOS() == llvm::Triple::Win32 && - Args.hasFlag(options::OPT_fms_extensions, - options::OPT_fno_ms_extensions, - true)))) + (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, + true)))) CmdArgs.push_back("-fms-compatibility"); - // -fmsc-version=1700 is default. + // -fms-compatibility-version=17.00 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - getToolChain().getTriple().getOS() == llvm::Triple::Win32) || - Args.hasArg(options::OPT_fmsc_version)) { - StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); - if (msc_ver.empty()) - CmdArgs.push_back("-fmsc-version=1700"); + IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) || + Args.hasArg(options::OPT_fms_compatibility_version)) { + const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); + const Arg *MSCompatibilityVersion = + Args.getLastArg(options::OPT_fms_compatibility_version); + + if (MSCVersion && MSCompatibilityVersion) + D.Diag(diag::err_drv_argument_not_allowed_with) + << MSCVersion->getAsString(Args) + << MSCompatibilityVersion->getAsString(Args); + + std::string Ver; + if (MSCompatibilityVersion) + Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version); + else if (MSCVersion) + Ver = getMSCompatibilityVersion(MSCVersion->getValue()); + + if (Ver.empty()) + CmdArgs.push_back("-fms-compatibility-version=17.00"); else - CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver)); + CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver)); } - // -fno-borland-extensions is default. if (Args.hasFlag(options::OPT_fborland_extensions, options::OPT_fno_borland_extensions, false)) @@ -3345,8 +3940,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fno-delayed-template-parsing is default, except for Windows where MSVC STL // needs it. if (Args.hasFlag(options::OPT_fdelayed_template_parsing, - options::OPT_fno_delayed_template_parsing, - getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + options::OPT_fno_delayed_template_parsing, IsWindowsMSVC)) CmdArgs.push_back("-fdelayed-template-parsing"); // -fgnu-keywords default varies depending on language; only pass if @@ -3369,9 +3963,10 @@ 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. Next runtime is always legacy dispatch and - // -fno-objc-legacy-dispatch gets ignored silently. - if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) { + // legacy is the default. Except for deployment taget of 10.5, + // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch + // gets ignored silently. + if (objcRuntime.isNonFragile()) { if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, options::OPT_fno_objc_legacy_dispatch, objcRuntime.isLegacyDispatchDefaultForArch( @@ -3447,9 +4042,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // Add exception args. - addExceptionArgs(Args, InputType, getToolChain().getTriple(), - KernelOrKext, objcRuntime, CmdArgs); + // Handle GCC-style exception args. + if (!C.getDriver().IsCLMode()) + addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext, + objcRuntime, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -3469,7 +4065,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fshort-wchar default varies depending on platform; only // pass if specified. - if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) + if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar, + options::OPT_fno_short_wchar)) A->render(Args, CmdArgs); // -fno-pascal-strings is default, only pass non-default. @@ -3512,6 +4109,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::err_drv_clang_unsupported) << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args); + // -finput_charset=UTF-8 is default. Reject others + if (Arg *inputCharset = Args.getLastArg( + options::OPT_finput_charset_EQ)) { + StringRef value = inputCharset->getValue(); + if (value != "UTF-8") + D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value; + } + // -fcaret-diagnostics is default. if (!Args.hasFlag(options::OPT_fcaret_diagnostics, options::OPT_fno_caret_diagnostics, true)) @@ -3554,9 +4159,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Support both clang's -f[no-]color-diagnostics and gcc's // -f[no-]diagnostics-colors[=never|always|auto]. enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto; - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it) { - const Option &O = (*it)->getOption(); + for (const auto &Arg : Args) { + const Option &O = Arg->getOption(); if (!O.matches(options::OPT_fcolor_diagnostics) && !O.matches(options::OPT_fdiagnostics_color) && !O.matches(options::OPT_fno_color_diagnostics) && @@ -3564,7 +4168,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !O.matches(options::OPT_fdiagnostics_color_EQ)) continue; - (*it)->claim(); + Arg->claim(); if (O.matches(options::OPT_fcolor_diagnostics) || O.matches(options::OPT_fdiagnostics_color)) { ShowColors = Colors_On; @@ -3573,7 +4177,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ShowColors = Colors_Off; } else { assert(O.matches(options::OPT_fdiagnostics_color_EQ)); - StringRef value((*it)->getValue()); + StringRef value(Arg->getValue()); if (value == "always") ShowColors = Colors_On; else if (value == "never") @@ -3614,16 +4218,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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); + bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false); OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group : options::OPT_fvectorize; if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption, options::OPT_fno_vectorize, EnableVec)) CmdArgs.push_back("-vectorize-loops"); - // -fslp-vectorize is default. - if (Args.hasFlag(options::OPT_fslp_vectorize, - options::OPT_fno_slp_vectorize, true)) + // -fslp-vectorize is enabled based on the optimization level selected. + bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true); + OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group : + options::OPT_fslp_vectorize; + if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption, + options::OPT_fno_slp_vectorize, EnableSLPVec)) CmdArgs.push_back("-vectorize-slp"); // -fno-slp-vectorize-aggressive is default. @@ -3677,6 +4284,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } #endif + // Enable rewrite includes if the user's asked for it or if we're generating + // diagnostics. + // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be + // nice to enable this when doing a crashdump for modules as well. + if (Args.hasFlag(options::OPT_frewrite_includes, + options::OPT_fno_rewrite_includes, false) || + (C.isForDiagnostics() && !HaveModules)) + CmdArgs.push_back("-frewrite-includes"); + // Only allow -traditional or -traditional-cpp outside in preprocessing modes. if (Arg *A = Args.getLastArg(options::OPT_traditional, options::OPT_traditional_cpp)) { @@ -3727,14 +4343,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, assert(Output.isNothing() && "Invalid output."); } - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - CmdArgs.push_back("-x"); - if (Args.hasArg(options::OPT_rewrite_objc)) - CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX)); - else - CmdArgs.push_back(types::getTypeName(II.getType())); + for (const auto &II : Inputs) { + addDashXForInput(Args, II, CmdArgs); + if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else @@ -3749,9 +4360,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) - (*it)->render(Args, OriginalArgs); + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); SmallString<256> Flags; Flags += Exec; @@ -3776,10 +4386,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Finally add the compile command to the compilation. - if (Args.hasArg(options::OPT__SLASH_fallback)) { - tools::visualstudio::Compile CL(getToolChain()); - Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args, - LinkingOutput); + if (Args.hasArg(options::OPT__SLASH_fallback) && + Output.getType() == types::TY_Object && + (InputType == types::TY_C || InputType == types::TY_CXX)) { + Command *CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs, + Args, LinkingOutput); C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand)); } else { C.addCommand(new Command(JA, *this, Exec, CmdArgs)); @@ -3938,6 +4549,45 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, return runtime; } +static bool maybeConsumeDash(const std::string &EH, size_t &I) { + bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-'); + I += HaveDash; + return !HaveDash; +} + +struct EHFlags { + EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {} + bool Synch; + bool Asynch; + bool NoExceptC; +}; + +/// /EH controls whether to run destructor cleanups when exceptions are +/// thrown. There are three modifiers: +/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions. +/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions. +/// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR. +/// - c: Assume that extern "C" functions are implicitly noexcept. This +/// modifier is an optimization, so we ignore it for now. +/// The default is /EHs-c-, meaning cleanups are disabled. +static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) { + EHFlags EH; + std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH); + for (auto EHVal : EHArgs) { + for (size_t I = 0, E = EHVal.size(); I != E; ++I) { + switch (EHVal[I]) { + case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue; + case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue; + case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue; + default: break; + } + D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal; + break; + } + } + return EH; +} + void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { unsigned RTOptionID = options::OPT__SLASH_MT; @@ -3983,11 +4633,58 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // 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"); + // Both /showIncludes and /E (and /EP) write to stdout. Allowing both + // would produce interleaved output, so ignore /showIncludes in such cases. + if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP)) + if (Arg *A = Args.getLastArg(options::OPT_show_includes)) + A->render(Args, CmdArgs); + + // This controls whether or not we emit RTTI data for polymorphic types. + if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, + /*default=*/false)) + CmdArgs.push_back("-fno-rtti-data"); + + const Driver &D = getToolChain().getDriver(); + EHFlags EH = parseClangCLEHFlags(D, Args); + // FIXME: Do something with NoExceptC. + if (EH.Synch || EH.Asynch) { + CmdArgs.push_back("-fexceptions"); + CmdArgs.push_back("-fcxx-exceptions"); + } + + // /EP should expand to -E -P. + if (Args.hasArg(options::OPT__SLASH_EP)) { + CmdArgs.push_back("-E"); + CmdArgs.push_back("-P"); + } + + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); + Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); + if (MostGeneralArg && BestCaseArg) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args); + + if (MostGeneralArg) { + Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms); + Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm); + Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv); + + Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg; + Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg; + if (FirstConflict && SecondConflict && FirstConflict != SecondConflict) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << FirstConflict->getAsString(Args) + << SecondConflict->getAsString(Args); + + if (SingleArg) + CmdArgs.push_back("-fms-memptr-rep=single"); + else if (MultipleArg) + CmdArgs.push_back("-fms-memptr-rep=multiple"); + else + CmdArgs.push_back("-fms-memptr-rep=virtual"); + } - if (Arg *A = Args.getLastArg(options::OPT_show_includes)) + if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ)) A->render(Args, CmdArgs); if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) { @@ -3999,6 +4696,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { } } +visualstudio::Compile *Clang::getCLFallback() const { + if (!CLFallback) + CLFallback.reset(new visualstudio::Compile(getToolChain())); + return CLFallback.get(); +} + void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4045,7 +4748,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Add the target features const Driver &D = getToolChain().getDriver(); - getTargetFeatures(D, Triple, Args, CmdArgs); + getTargetFeatures(D, Triple, Args, CmdArgs, true); // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); @@ -4066,6 +4769,13 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, if (!A->getOption().matches(options::OPT_g0)) CmdArgs.push_back("-g"); + if (Args.hasArg(options::OPT_gdwarf_2)) + CmdArgs.push_back("-gdwarf-2"); + if (Args.hasArg(options::OPT_gdwarf_3)) + CmdArgs.push_back("-gdwarf-3"); + if (Args.hasArg(options::OPT_gdwarf_4)) + CmdArgs.push_back("-gdwarf-4"); + // Add the -fdebug-compilation-dir flag if needed. addDebugCompDirArg(Args, CmdArgs); @@ -4079,9 +4789,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) - (*it)->render(Args, OriginalArgs); + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); @@ -4096,6 +4805,16 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // FIXME: Add -static support, once we have it. + // Consume all the warning flags. Usually this would be handled more + // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as + // doesn't handle that so rather than warning about unused flags that are + // actually used, we'll lie by omission instead. + // FIXME: Stop lying and consume only the appropriate driver flags + for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group), + ie = Args.filtered_end(); + it != ie; ++it) + (*it)->claim(); + CollectArgsForIntegratedAssembler(C, Args, CmdArgs, getToolChain().getDriver()); @@ -4128,9 +4847,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; - for (ArgList::const_iterator - it = Args.begin(), ie = Args.end(); it != ie; ++it) { - Arg *A = *it; + for (const auto &A : Args) { if (forwardToGCC(A->getOption())) { // Don't forward any -g arguments to assembly steps. if (isa<AssembleJobAction>(JA) && @@ -4199,10 +4916,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + for (const auto &II : Inputs) { // Don't try to pass LLVM or AST inputs to a generic gcc. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) @@ -4255,11 +4969,6 @@ void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA, CmdArgs.push_back("-E"); } -void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA, - ArgStringList &CmdArgs) const { - // The type is good enough. -} - void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -4277,11 +4986,6 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, } } -void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA, - ArgStringList &CmdArgs) const { - CmdArgs.push_back("-c"); -} - void gcc::Link::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The types are (hopefully) good enough. @@ -4331,10 +5035,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + for (const auto &II : Inputs) { // Don't try to pass LLVM or AST inputs to a generic gcc. if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) @@ -4355,11 +5056,10 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } const char *GCCName = "hexagon-as"; - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); - } + void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The types are (hopefully) good enough. @@ -4401,10 +5101,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- - for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), - e = ToolChain.ExtraOpts.end(); - i != e; ++i) - CmdArgs.push_back(i->c_str()); + for (const auto &Opt : ToolChain.ExtraOpts) + CmdArgs.push_back(Opt.c_str()); std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString("-m" + MarchString)); @@ -4480,12 +5178,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, // Library Search Paths //---------------------------------------------------------------------------- const ToolChain::path_list &LibPaths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator - i = LibPaths.begin(), - e = LibPaths.end(); - i != e; - ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + for (const auto &LibPath : LibPaths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); //---------------------------------------------------------------------------- // @@ -4533,7 +5227,116 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Hexagon tools end. -llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { +/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. +const char *arm::getARMCPUForMArch(const ArgList &Args, + const llvm::Triple &Triple) { + StringRef MArch; + if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + // Otherwise, if we have -march= choose the base CPU for that arch. + MArch = A->getValue(); + } else { + // Otherwise, use the Arch from the triple. + MArch = Triple.getArchName(); + } + + // Handle -march=native. + if (MArch == "native") { + std::string CPU = llvm::sys::getHostCPUName(); + if (CPU != "generic") { + // Translate the native cpu into the architecture. The switch below will + // then chose the minimum cpu for that arch. + MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU); + } + } + + return Triple.getARMCPUForArch(MArch); +} + +/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. +StringRef arm::getARMTargetCPU(const ArgList &Args, + const llvm::Triple &Triple) { + // FIXME: Warn on inconsistent use of -mcpu and -march. + // If we have -mcpu=, use that. + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + StringRef MCPU = A->getValue(); + // Handle -mcpu=native. + if (MCPU == "native") + return llvm::sys::getHostCPUName(); + else + return MCPU; + } + + return getARMCPUForMArch(Args, Triple); +} + +/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular +/// CPU. +// +// FIXME: This is redundant with -mcpu, why does LLVM use this. +// FIXME: tblgen this, or kill it! +const char *arm::getLLVMArchSuffixForARM(StringRef CPU) { + return llvm::StringSwitch<const char *>(CPU) + .Case("strongarm", "v4") + .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") + .Cases("arm720t", "arm9", "arm9tdmi", "v4t") + .Cases("arm920", "arm920t", "arm922t", "v4t") + .Cases("arm940t", "ep9312","v4t") + .Cases("arm10tdmi", "arm1020t", "v5") + .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") + .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") + .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") + .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") + .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") + .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7") + .Cases("cortex-r4", "cortex-r5", "v7r") + .Case("cortex-m0", "v6m") + .Case("cortex-m3", "v7m") + .Case("cortex-m4", "v7em") + .Case("swift", "v7s") + .Case("cyclone", "v8") + .Cases("cortex-a53", "cortex-a57", "v8") + .Default(""); +} + +bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + +bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) { + if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) + return llvm::StringSwitch<bool>(NaNArg->getValue()) + .Case("2008", true) + .Case("legacy", false) + .Default(false); + + // NaN2008 is the default for MIPS32r6/MIPS64r6. + return llvm::StringSwitch<bool>(getCPUName(Args, Triple)) + .Cases("mips32r6", "mips64r6", true) + .Default(false); + + return false; +} + +bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, + StringRef ABIName) { + if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && + Triple.getVendor() != llvm::Triple::MipsTechnologies) + return false; + + if (ABIName != "32") + return false; + + return llvm::StringSwitch<bool>(CPUName) + .Cases("mips2", "mips3", "mips4", "mips5", true) + .Cases("mips32", "mips32r2", true) + .Cases("mips64", "mips64r2", true) + .Default(false); +} + +llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for // archs which Darwin doesn't use. @@ -4556,8 +5359,9 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .Cases("x86_64", "x86_64h", llvm::Triple::x86_64) // This is derived from the driver driver. .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) - .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm) + .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm) .Cases("armv7s", "xscale", llvm::Triple::arm) + .Case("arm64", llvm::Triple::arm64) .Case("r600", llvm::Triple::r600) .Case("nvptx", llvm::Triple::nvptx) .Case("nvptx64", llvm::Triple::nvptx64) @@ -4566,6 +5370,18 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .Default(llvm::Triple::UnknownArch); } +void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) { + llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str); + T.setArch(Arch); + + if (Str == "x86_64h") + T.setArchName(Str); + else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") { + T.setOS(llvm::Triple::UnknownOS); + T.setObjectFormat(llvm::Triple::MachO); + } +} + const char *Clang::getBaseInputName(const ArgList &Args, const InputInfoList &Inputs) { return Args.MakeArgString( @@ -4613,14 +5429,14 @@ 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 + // If -fno_integrated_as is used add -Q to the darwin assember driver to make // sure it runs its system assembler not clang's integrated assembler. // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as. // FIXME: at run-time detect assembler capabilities or rely on version // information forwarded by -target-assembler-version (future) - if (Args.hasArg(options::OPT_no_integrated_as)) { - const llvm::Triple& t(getToolChain().getTriple()); - if (!(t.isMacOSX() && t.isMacOSXVersionLT(10, 7))) + if (Args.hasArg(options::OPT_fno_integrated_as)) { + const llvm::Triple &T(getToolChain().getTriple()); + if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7))) CmdArgs.push_back("-Q"); } @@ -4634,7 +5450,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } // Derived from asm spec. - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); // Use -force_cpusubtype_ALL on x86 by default. if (getToolChain().getArch() == llvm::Triple::x86 || @@ -4645,8 +5461,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() != llvm::Triple::x86_64 && (((Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)) && - (!getDarwinToolChain().isTargetIPhoneOS() || - getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) || + getMachOToolChain().isKernelStatic()) || Args.hasArg(options::OPT_static))) CmdArgs.push_back("-static"); @@ -4667,11 +5482,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } -void darwin::DarwinTool::anchor() {} +void darwin::MachOTool::anchor() {} -void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, - ArgStringList &CmdArgs) const { - StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); +void darwin::MachOTool::AddMachOArch(const ArgList &Args, + ArgStringList &CmdArgs) const { + StringRef ArchName = getMachOToolChain().getMachOArchName(Args); // Derived from darwin_arch spec. CmdArgs.push_back("-arch"); @@ -4686,9 +5501,8 @@ bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const { // We only need to generate a temp path for LTO if we aren't compiling object // files. When compiling source files, we run 'dsymutil' after linking. We // don't run 'dsymutil' when compiling object files. - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) - if (it->getType() != types::TY_Object) + for (const auto &Input : Inputs) + if (Input.getType() != types::TY_Object) return true; return false; @@ -4699,7 +5513,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, ArgStringList &CmdArgs, const InputInfoList &Inputs) const { const Driver &D = getToolChain().getDriver(); - const toolchains::Darwin &DarwinTC = getDarwinToolChain(); + const toolchains::MachO &MachOTC = getMachOToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { @@ -4711,27 +5525,10 @@ void darwin::Link::AddLinkArgs(Compilation &C, << A->getAsString(Args); } - // Newer linkers support -demangle, pass it if supported and not disabled by + // Newer linkers support -demangle. Pass it if supported and not disabled by // the user. - if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) { - // Don't pass -demangle to ld_classic. - // - // FIXME: This is a temporary workaround, ld should be handling this. - bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 && - Args.hasArg(options::OPT_static)); - if (getToolChain().getArch() == llvm::Triple::x86) { - for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker, - options::OPT_Wl_COMMA), - ie = Args.filtered_end(); it != ie; ++it) { - const Arg *A = *it; - for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - if (StringRef(A->getValue(i)) == "-kext") - UsesLdClassic = true; - } - } - if (!UsesLdClassic) - CmdArgs.push_back("-demangle"); - } + if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("-demangle"); if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137) CmdArgs.push_back("-export_dynamic"); @@ -4757,7 +5554,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, } if (!Args.hasArg(options::OPT_dynamiclib)) { - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); // FIXME: Why do this only on this path? Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL); @@ -4793,7 +5590,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version, "-dylib_current_version"); - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name, "-dylib_install_name"); @@ -4802,7 +5599,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_all__load); Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); - if (DarwinTC.isTargetIPhoneOS()) + if (MachOTC.isTargetIOSBased()) Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); Args.AddLastArg(CmdArgs, options::OPT_dead__strip); Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); @@ -4816,22 +5613,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_init); // Add the deployment target. - VersionTuple TargetVersion = DarwinTC.getTargetVersion(); - - // If we had an explicit -mios-simulator-version-min argument, honor that, - // otherwise use the traditional deployment targets. We can't just check the - // is-sim attribute because existing code follows this path, and the linker - // may not handle the argument. - // - // FIXME: We may be able to remove this, once we can verify no one depends on - // it. - if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) - CmdArgs.push_back("-ios_simulator_version_min"); - else if (DarwinTC.isTargetIPhoneOS()) - CmdArgs.push_back("-iphoneos_version_min"); - else - CmdArgs.push_back("-macosx_version_min"); - CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); + MachOTC.addMinVersionArgs(Args, CmdArgs); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); @@ -4900,6 +5682,12 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_Mach); } +enum LibOpenMP { + LibUnknown, + LibGOMP, + LibIOMP5 +}; + void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4915,8 +5703,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, /// Hack(tm) to ignore linking errors when we are doing ARC migration. if (Args.hasArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_migrate)) { - for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) - (*I)->claim(); + for (const auto &Arg : Args) + Arg->claim(); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); @@ -4946,120 +5734,42 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) { - // Derived from startfile spec. - if (Args.hasArg(options::OPT_dynamiclib)) { - // Derived from darwin_dylib1 spec. - if (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-ldylib1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-ldylib1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-ldylib1.o"); - else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-ldylib1.10.5.o"); - } - } else { - if (Args.hasArg(options::OPT_bundle)) { - if (!Args.hasArg(options::OPT_static)) { - // Derived from darwin_bundle1 spec. - if (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-lbundle1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-lbundle1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lbundle1.o"); - } - } - } else { - if (Args.hasArg(options::OPT_pg) && - getToolChain().SupportsProfiling()) { - if (Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_object) || - Args.hasArg(options::OPT_preload)) { - CmdArgs.push_back("-lgcrt0.o"); - } else { - CmdArgs.push_back("-lgcrt1.o"); - - // darwin_crt2 spec is empty. - } - // By default on OS X 10.8 and later, we don't link with a crt1.o - // file and the linker knows to use _main as the entry point. But, - // when compiling with -pg, we need to link with the gcrt1.o file, - // so pass the -no_new_main option to tell the linker to use the - // "start" symbol as the entry point. - if (getDarwinToolChain().isTargetMacOS() && - !getDarwinToolChain().isMacosxVersionLT(10, 8)) - CmdArgs.push_back("-no_new_main"); - } else { - if (Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_object) || - Args.hasArg(options::OPT_preload)) { - CmdArgs.push_back("-lcrt0.o"); - } else { - // Derived from darwin_crt1 spec. - if (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-lcrt1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-lcrt1.o"); - else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0)) - CmdArgs.push_back("-lcrt1.3.1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lcrt1.o"); - else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lcrt1.10.5.o"); - else if (getDarwinToolChain().isMacosxVersionLT(10, 8)) - CmdArgs.push_back("-lcrt1.10.6.o"); - - // darwin_crt2 spec is empty. - } - } - } - } - } - - if (!getDarwinToolChain().isTargetIPhoneOS() && - Args.hasArg(options::OPT_shared_libgcc) && - getDarwinToolChain().isMacosxVersionLT(10, 5)) { - const char *Str = - Args.MakeArgString(getToolChain().GetFilePath("crt3.o")); - CmdArgs.push_back(Str); - } - } + !Args.hasArg(options::OPT_nostartfiles)) + getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_L); - if (Args.hasArg(options::OPT_fopenmp)) - // This is more complicated in gcc... + LibOpenMP UsedOpenMPLib = LibUnknown; + if (Args.hasArg(options::OPT_fopenmp)) { + UsedOpenMPLib = LibGOMP; + } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { + UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue()) + .Case("libgomp", LibGOMP) + .Case("libiomp5", LibIOMP5) + .Default(LibUnknown); + if (UsedOpenMPLib == LibUnknown) + getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(); + } + switch (UsedOpenMPLib) { + case LibGOMP: CmdArgs.push_back("-lgomp"); + break; + case LibIOMP5: + CmdArgs.push_back("-liomp5"); + break; + case LibUnknown: + break; + } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { - // Avoid linking compatibility stubs on i386 mac. - if (!getDarwinToolChain().isTargetMacOS() || - getDarwinToolChain().getArch() != llvm::Triple::x86) { - // If we don't have ARC or subscripting runtime support, link in the - // runtime stubs. We have to do this *before* adding any of the normal - // linker inputs so that its initializer gets run first. - ObjCRuntime runtime = - getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true); - // We use arclite library for both ARC and subscripting support. - if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) || - !runtime.hasSubscripting()) - getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); - } + // We use arclite library for both ARC and subscripting support. + getMachOToolChain().AddLinkARCArgs(Args, CmdArgs); + CmdArgs.push_back("-framework"); CmdArgs.push_back("Foundation"); // Link libobj. @@ -5083,7 +5793,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // link_ssp spec is empty. // Let the tool chain choose which runtime library to link. - getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs); + getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs); } if (!Args.hasArg(options::OPT_nostdlib) && @@ -5095,7 +5805,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_F); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5112,14 +5822,12 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-output"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) { assert(II.isFilename() && "Unexpected lipo input."); CmdArgs.push_back(II.getFilename()); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("lipo")); + + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5179,18 +5887,13 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } - void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5289,10 +5992,10 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o")); - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5309,14 +6012,10 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("gas")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5401,10 +6100,10 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().GetFilePath("crtend.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5414,19 +6113,36 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; + bool NeedsKPIC = false; - // 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) + switch (getToolChain().getArch()) { + case llvm::Triple::x86: + // When building 32-bit code on OpenBSD/amd64, we have to explicitly + // instruct as in the base system to assemble 32-bit code. CmdArgs.push_back("--32"); - else if (getToolChain().getArch() == llvm::Triple::ppc) { + break; + + case llvm::Triple::ppc: CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); - } else if (getToolChain().getArch() == llvm::Triple::mips64 || - getToolChain().getArch() == llvm::Triple::mips64el) { + break; + + case llvm::Triple::sparc: + CmdArgs.push_back("-32"); + NeedsKPIC = true; + break; + + case llvm::Triple::sparcv9: + CmdArgs.push_back("-64"); + CmdArgs.push_back("-Av9a"); + NeedsKPIC = true; + break; + + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); @@ -5436,30 +6152,25 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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"); - } + NeedsKPIC = true; + break; } + default: + break; + } + + if (NeedsKPIC) + addAssemblerKPIC(Args, CmdArgs); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); @@ -5594,7 +6305,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5611,14 +6322,10 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5734,7 +6441,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5757,7 +6464,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); @@ -5771,22 +6478,14 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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"); - } + addAssemblerKPIC(Args, CmdArgs); } else if (getToolChain().getArch() == llvm::Triple::arm || - getToolChain().getArch() == llvm::Triple::thumb) { + getToolChain().getArch() == llvm::Triple::armeb || + getToolChain().getArch() == llvm::Triple::thumb || + getToolChain().getArch() == llvm::Triple::thumbeb) { const Driver &D = getToolChain().getDriver(); - llvm::Triple Triple = getToolChain().getTriple(); - StringRef FloatABI = getARMFloatABI(D, Args, Triple); + const llvm::Triple &Triple = getToolChain().getTriple(); + StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple); if (FloatABI == "hard") { CmdArgs.push_back("-mfpu=vfp"); @@ -5811,17 +6510,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-Av9a"); - 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"); - } + addAssemblerKPIC(Args, CmdArgs); } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -5830,14 +6519,10 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5849,6 +6534,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const toolchains::FreeBSD& ToolChain = static_cast<const toolchains::FreeBSD&>(getToolChain()); const Driver &D = ToolChain.getDriver(); + const bool IsPIE = + !Args.hasArg(options::OPT_shared) && + (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" @@ -5862,7 +6550,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); - if (Args.hasArg(options::OPT_pie)) + if (IsPIE) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_static)) { @@ -5908,11 +6596,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - const char *crt1 = NULL; + const char *crt1 = nullptr; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; - else if (Args.hasArg(options::OPT_pie)) + else if (IsPIE) crt1 = "Scrt1.o"; else crt1 = "crt1.o"; @@ -5922,10 +6610,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); - const char *crtbegin = NULL; + const char *crtbegin = nullptr; if (Args.hasArg(options::OPT_static)) crtbegin = "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + else if (Args.hasArg(options::OPT_shared) || IsPIE) crtbegin = "crtbeginS.o"; else crtbegin = "crtbegin.o"; @@ -5935,9 +6623,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); - i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -5945,25 +6632,8 @@ 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)); - } - } + if (D.IsUsingLTO(Args)) + AddGoldPlugin(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); @@ -6023,17 +6693,19 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + if (Args.hasArg(options::OPT_shared) || IsPIE) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); else CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple()); + addSanitizerRuntimes(getToolChain(), Args, CmdArgs); + + addProfileRT(ToolChain, Args, CmdArgs); const char *Exec = - Args.MakeArgString(ToolChain.GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6044,25 +6716,28 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; - // When building 32-bit code on NetBSD/amd64, we have to explicitly - // instruct as in the base system to assemble 32-bit code. - if (getToolChain().getArch() == llvm::Triple::x86) + // GNU as needs different flags for creating the correct output format + // on architectures with different ABIs or optional feature sets. + switch (getToolChain().getArch()) { + case llvm::Triple::x86: CmdArgs.push_back("--32"); - - // 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())); + break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: { + std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple())); CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch)); + break; } - if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mipsel || - getToolChain().getArch() == llvm::Triple::mips64 || - getToolChain().getArch() == llvm::Triple::mips64el) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); @@ -6076,17 +6751,23 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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"); - } + addAssemblerKPIC(Args, CmdArgs); + break; + } + + case llvm::Triple::sparc: + CmdArgs.push_back("-32"); + addAssemblerKPIC(Args, CmdArgs); + break; + + case llvm::Triple::sparcv9: + CmdArgs.push_back("-64"); + CmdArgs.push_back("-Av9"); + addAssemblerKPIC(Args, CmdArgs); + break; + + default: + break; } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -6095,11 +6776,8 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); @@ -6116,12 +6794,12 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); - CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { @@ -6130,11 +6808,61 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } } - // When building 32-bit code on NetBSD/amd64, we have to explicitly - // instruct ld in the base system to link 32-bit code. - if (getToolChain().getArch() == llvm::Triple::x86) { + // Many NetBSD architectures support more than one ABI. + // Determine the correct emulation for ld. + switch (getToolChain().getArch()) { + case llvm::Triple::x86: CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); + break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + CmdArgs.push_back("-m"); + switch (getToolChain().getTriple().getEnvironment()) { + case llvm::Triple::EABI: + case llvm::Triple::GNUEABI: + CmdArgs.push_back("armelf_nbsd_eabi"); + break; + case llvm::Triple::EABIHF: + case llvm::Triple::GNUEABIHF: + CmdArgs.push_back("armelf_nbsd_eabihf"); + break; + default: + CmdArgs.push_back("armelf_nbsd"); + break; + } + break; + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + if (mips::hasMipsAbiArg(Args, "32")) { + CmdArgs.push_back("-m"); + if (getToolChain().getArch() == llvm::Triple::mips64) + CmdArgs.push_back("elf32btsmip"); + else + CmdArgs.push_back("elf32ltsmip"); + } else if (mips::hasMipsAbiArg(Args, "64")) { + CmdArgs.push_back("-m"); + if (getToolChain().getArch() == llvm::Triple::mips64) + CmdArgs.push_back("elf64btsmip"); + else + CmdArgs.push_back("elf64ltsmip"); + } + break; + + case llvm::Triple::sparc: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32_sparc"); + break; + + case llvm::Triple::sparcv9: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64_sparc"); + break; + + default: + break; } if (Output.isFilename()) { @@ -6174,10 +6902,19 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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) + if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) { + switch(getToolChain().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + case llvm::Triple::x86: + case llvm::Triple::x86_64: useLibgcc = false; + break; + default: + break; + } } if (!Args.hasArg(options::OPT_nostdlib) && @@ -6219,9 +6956,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, "crtn.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6238,7 +6975,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("--32"); } else if (getToolChain().getArch() == llvm::Triple::x86_64) { - CmdArgs.push_back("--64"); + if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32) + CmdArgs.push_back("--x32"); + else + CmdArgs.push_back("--64"); } else if (getToolChain().getArch() == llvm::Triple::ppc) { CmdArgs.push_back("-a32"); CmdArgs.push_back("-mppc"); @@ -6249,8 +6989,9 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::ppc64le) { CmdArgs.push_back("-a64"); - CmdArgs.push_back("-mppc64le"); + CmdArgs.push_back("-mppc64"); CmdArgs.push_back("-many"); + CmdArgs.push_back("-mlittle-endian"); } else if (getToolChain().getArch() == llvm::Triple::sparc) { CmdArgs.push_back("-32"); CmdArgs.push_back("-Av8plusa"); @@ -6259,19 +7000,30 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-64"); CmdArgs.push_back("-Av9a"); NeedsKPIC = true; - } else if (getToolChain().getArch() == llvm::Triple::arm) { + } else if (getToolChain().getArch() == llvm::Triple::arm || + getToolChain().getArch() == llvm::Triple::armeb) { StringRef MArch = getToolChain().getArchName(); if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") CmdArgs.push_back("-mfpu=neon"); - if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a") + if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" || + MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a") CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8"); - StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args, - getToolChain().getTriple()); + StringRef ARMFloatABI = tools::arm::getARMFloatABI( + getToolChain().getDriver(), Args, getToolChain().getTriple()); CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI)); Args.AddLastArg(CmdArgs, options::OPT_march_EQ); - Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); + + // FIXME: remove krait check when GNU tools support krait cpu + // for now replace it with -march=armv7-a to avoid a lower + // march from being picked in the absence of a cpu flag. + Arg *A; + if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) && + StringRef(A->getValue()) == "krait") + CmdArgs.push_back("-march=armv7-a"); + else + Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ); } else if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mipsel || @@ -6279,13 +7031,34 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + ABIName = getGnuCompatibleMipsABIName(ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); - CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); + CmdArgs.push_back(ABIName.data()); + + // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE, + // or -mshared (not implemented) is in effect. + bool IsPicOrPie = false; + if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, + options::OPT_fpie, options::OPT_fno_pie)) { + if (A->getOption().matches(options::OPT_fPIC) || + A->getOption().matches(options::OPT_fpic) || + A->getOption().matches(options::OPT_fPIE) || + A->getOption().matches(options::OPT_fpie)) + IsPicOrPie = true; + } + if (!IsPicOrPie) + CmdArgs.push_back("-mno-shared"); + + // LLVM doesn't support -mplt yet and acts as if it is always given. + // However, -mplt has no effect with the N64 ABI. + CmdArgs.push_back(ABIName == "64" ? "-KPIC" : "-call_nonpic"); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) @@ -6298,14 +7071,28 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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")); + // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default. + if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, + options::OPT_mfp64)) { + A->claim(); + A->render(Args, CmdArgs); + } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName, + ABIName)) + CmdArgs.push_back("-mfpxx"); + + // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of + // -mno-mips16 is actually -no-mips16. + if (Arg *A = Args.getLastArg(options::OPT_mips16, + options::OPT_mno_mips16)) { + if (A->getOption().matches(options::OPT_mips16)) { + A->claim(); + A->render(Args, CmdArgs); + } else { + A->claim(); + CmdArgs.push_back("-no-mips16"); + } } - Args.AddLastArg(CmdArgs, options::OPT_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); @@ -6318,6 +7105,12 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-mmsa")); } + Args.AddLastArg(CmdArgs, options::OPT_mhard_float, + options::OPT_msoft_float); + + Args.AddLastArg(CmdArgs, options::OPT_modd_spreg, + options::OPT_mno_odd_spreg); + NeedsKPIC = true; } else if (getToolChain().getArch() == llvm::Triple::systemz) { // Always pass an -march option, since our default of z10 is later @@ -6326,19 +7119,8 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); } - if (NeedsKPIC) { - 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"); - } - } + if (NeedsKPIC) + addAssemblerKPIC(Args, CmdArgs); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -6346,14 +7128,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + 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 @@ -6365,7 +7143,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, SplitDebugName(Args, Inputs)); } -static void AddLibgcc(llvm::Triple Triple, const Driver &D, +static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android; bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || @@ -6398,47 +7176,77 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D, CmdArgs.push_back("-ldl"); } -static bool hasMipsN32ABIArg(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef("n32")); -} - static StringRef getLinuxDynamicLinker(const ArgList &Args, const toolchains::Linux &ToolChain) { - if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) - return "/system/bin/linker"; - else if (ToolChain.getArch() == llvm::Triple::x86 || - ToolChain.getArch() == llvm::Triple::sparc) + if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) { + if (ToolChain.getTriple().isArch64Bit()) + return "/system/bin/linker64"; + else + return "/system/bin/linker"; + } else if (ToolChain.getArch() == llvm::Triple::x86 || + ToolChain.getArch() == llvm::Triple::sparc) return "/lib/ld-linux.so.2"; - else if (ToolChain.getArch() == llvm::Triple::aarch64) + else if (ToolChain.getArch() == llvm::Triple::aarch64 || + ToolChain.getArch() == llvm::Triple::arm64) return "/lib/ld-linux-aarch64.so.1"; + else if (ToolChain.getArch() == llvm::Triple::aarch64_be || + ToolChain.getArch() == llvm::Triple::arm64_be) + return "/lib/ld-linux-aarch64_be.so.1"; else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) return "/lib/ld-linux-armhf.so.3"; else return "/lib/ld-linux.so.3"; + } else if (ToolChain.getArch() == llvm::Triple::armeb || + ToolChain.getArch() == llvm::Triple::thumbeb) { + if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) + return "/lib/ld-linux-armhf.so.3"; /* TODO: check which dynamic linker name. */ + else + return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */ } else if (ToolChain.getArch() == llvm::Triple::mips || - ToolChain.getArch() == llvm::Triple::mipsel) + ToolChain.getArch() == llvm::Triple::mipsel) { + if (mips::isNaN2008(Args, ToolChain.getTriple())) + return "/lib/ld-linux-mipsn8.so.1"; 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::mips64 || + ToolChain.getArch() == llvm::Triple::mips64el) { + if (mips::hasMipsAbiArg(Args, "n32")) + return mips::isNaN2008(Args, ToolChain.getTriple()) + ? "/lib32/ld-linux-mipsn8.so.1" : "/lib32/ld.so.1"; + return mips::isNaN2008(Args, ToolChain.getTriple()) + ? "/lib64/ld-linux-mipsn8.so.1" : "/lib64/ld.so.1"; } else if (ToolChain.getArch() == llvm::Triple::ppc) return "/lib/ld.so.1"; else if (ToolChain.getArch() == llvm::Triple::ppc64 || - ToolChain.getArch() == llvm::Triple::ppc64le || ToolChain.getArch() == llvm::Triple::systemz) return "/lib64/ld64.so.1"; + else if (ToolChain.getArch() == llvm::Triple::ppc64le) + return "/lib64/ld64.so.2"; else if (ToolChain.getArch() == llvm::Triple::sparcv9) return "/lib64/ld-linux.so.2"; + else if (ToolChain.getArch() == llvm::Triple::x86_64 && + ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32) + return "/libx32/ld-linux-x32.so.2"; else return "/lib64/ld-linux-x86-64.so.2"; } +static void AddRunTimeLibs(const ToolChain &TC, const Driver &D, + ArgStringList &CmdArgs, const ArgList &Args) { + // Make use of compiler-rt if --rtlib option is used + ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args); + + switch(RLT) { + case ToolChain::RLT_CompilerRT: + addClangRTLinux(TC, Args, CmdArgs); + break; + case ToolChain::RLT_Libgcc: + AddLibgcc(TC.getTriple(), D, CmdArgs, Args); + break; + } +} + void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -6449,10 +7257,14 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = ToolChain.getDriver(); const bool isAndroid = ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; - const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && - (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow()); + !Args.hasArg(options::OPT_static) && + (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() || + // On Android every code is PIC so every executable is PIE + // Cannot use isPIEDefault here since otherwise + // PIE only logic will be enabled during compilation + isAndroid); ArgStringList CmdArgs; @@ -6476,10 +7288,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); - for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), - e = ToolChain.ExtraOpts.end(); - i != e; ++i) - CmdArgs.push_back(i->c_str()); + for (const auto &Opt : ToolChain.ExtraOpts) + CmdArgs.push_back(Opt.c_str()); if (!Args.hasArg(options::OPT_static)) { CmdArgs.push_back("--eh-frame-hdr"); @@ -6488,15 +7298,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-m"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); - else if (ToolChain.getArch() == llvm::Triple::aarch64) + else if (ToolChain.getArch() == llvm::Triple::aarch64 || + ToolChain.getArch() == llvm::Triple::arm64) CmdArgs.push_back("aarch64linux"); + else if (ToolChain.getArch() == llvm::Triple::aarch64_be || + ToolChain.getArch() == llvm::Triple::arm64_be) + CmdArgs.push_back("aarch64_be_linux"); else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); + else if (ToolChain.getArch() == llvm::Triple::armeb + || ToolChain.getArch() == llvm::Triple::thumbeb) + CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME. */ else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("elf32ppclinux"); else if (ToolChain.getArch() == llvm::Triple::ppc64) CmdArgs.push_back("elf64ppc"); + else if (ToolChain.getArch() == llvm::Triple::ppc64le) + CmdArgs.push_back("elf64lppc"); else if (ToolChain.getArch() == llvm::Triple::sparc) CmdArgs.push_back("elf32_sparc"); else if (ToolChain.getArch() == llvm::Triple::sparcv9) @@ -6506,37 +7325,41 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); else if (ToolChain.getArch() == llvm::Triple::mips64) { - if (hasMipsN32ABIArg(Args)) + if (mips::hasMipsAbiArg(Args, "n32")) CmdArgs.push_back("elf32btsmipn32"); else CmdArgs.push_back("elf64btsmip"); } else if (ToolChain.getArch() == llvm::Triple::mips64el) { - if (hasMipsN32ABIArg(Args)) + if (mips::hasMipsAbiArg(Args, "n32")) CmdArgs.push_back("elf32ltsmipn32"); else CmdArgs.push_back("elf64ltsmip"); } else if (ToolChain.getArch() == llvm::Triple::systemz) CmdArgs.push_back("elf64_s390"); + else if (ToolChain.getArch() == llvm::Triple::x86_64 && + ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32) + CmdArgs.push_back("elf32_x86_64"); else CmdArgs.push_back("elf_x86_64"); if (Args.hasArg(options::OPT_static)) { - if (ToolChain.getArch() == llvm::Triple::arm - || ToolChain.getArch() == llvm::Triple::thumb) + if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::armeb || + ToolChain.getArch() == llvm::Triple::thumb || + ToolChain.getArch() == llvm::Triple::thumbeb) CmdArgs.push_back("-Bstatic"); else CmdArgs.push_back("-static"); } else if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); - if (isAndroid) { - CmdArgs.push_back("-Bsymbolic"); - } } if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::armeb || ToolChain.getArch() == llvm::Triple::thumb || + ToolChain.getArch() == llvm::Triple::thumbeb || (!Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-dynamic-linker"); @@ -6550,7 +7373,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!isAndroid) { - const char *crt1 = NULL; + const char *crt1 = nullptr; if (!Args.hasArg(options::OPT_shared)){ if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; @@ -6581,57 +7404,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); const ToolChain::path_list Paths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); - i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); - - // Tell the linker to load the plugin. This has to come before AddLinkerInputs - // as gold requires -plugin to come before any -plugin-opt that -Wl might - // forward. - if (D.IsUsingLTO(Args)) { - CmdArgs.push_back("-plugin"); - std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; - CmdArgs.push_back(Args.MakeArgString(Plugin)); - - // Try to pass driver level flags relevant to LTO code generation down to - // the plugin. - - // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(Args, ToolChain.getTriple()); - if (!CPU.empty()) { - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=mcpu=") + - CPU)); - } - } + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + if (D.IsUsingLTO(Args)) + AddGoldPlugin(ToolChain, Args, CmdArgs); if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); - // Call these before we add the C++ ABI library. - if (Sanitize.needsUbsanRt()) - addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(), - Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || - Sanitize.needsMsanRt() || Sanitize.needsLsanRt()); - if (Sanitize.needsAsanRt()) - addAsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsTsanRt()) - addTsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsMsanRt()) - addMsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsLsanRt()) - addLsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsDfsanRt()) - addDfsanRTLinux(getToolChain(), Args, CmdArgs); - + addSanitizerRuntimes(getToolChain(), Args, CmdArgs); // The profile runtime also needs access to system libraries. - addProfileRTLinux(getToolChain(), Args, CmdArgs); + addProfileRT(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && @@ -6651,19 +7441,37 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); - bool OpenMP = Args.hasArg(options::OPT_fopenmp); - if (OpenMP) { + LibOpenMP UsedOpenMPLib = LibUnknown; + if (Args.hasArg(options::OPT_fopenmp)) { + UsedOpenMPLib = LibGOMP; + } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { + UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue()) + .Case("libgomp", LibGOMP) + .Case("libiomp5", LibIOMP5) + .Default(LibUnknown); + if (UsedOpenMPLib == LibUnknown) + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(); + } + switch (UsedOpenMPLib) { + case LibGOMP: CmdArgs.push_back("-lgomp"); - // FIXME: Exclude this for platforms whith libgomp that doesn't require - // librt. Most modern Linux platfroms require it, but some may not. + // FIXME: Exclude this for platforms with libgomp that don't require + // librt. Most modern Linux platforms require it, but some may not. CmdArgs.push_back("-lrt"); + break; + case LibIOMP5: + CmdArgs.push_back("-liomp5"); + break; + case LibUnknown: + break; } + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); - - if (Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads) || OpenMP) + if ((Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) && + !isAndroid) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); @@ -6671,7 +7479,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); else - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); } if (!Args.hasArg(options::OPT_nostartfiles)) { @@ -6699,20 +7507,15 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6745,7 +7548,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -6766,7 +7569,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6786,20 +7589,15 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6947,13 +7745,21 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().GetFilePath("crtn.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, + const StringRef RTName) { + SmallString<128> LibSanitizer(getCompilerRTLibDir(TC)); + llvm::sys::path::append(LibSanitizer, + Twine("clang_rt.") + RTName + ".lib"); + CmdArgs.push_back(Args.MakeArgString(LibSanitizer)); +} + void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -6976,6 +7782,10 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-nologo"); + if (Args.hasArg(options::OPT_g_Group)) { + CmdArgs.push_back("-debug"); + } + bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd); if (DLL) { @@ -6990,28 +7800,25 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, 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"); + // FIXME: Handle 64-bit. if (DLL) { - llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, + "asan_dll_thunk-i386"); } else { - llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386"); } - // 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()); + for (const auto &Input : Inputs) + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); else - it->getInputArg().renderAsInput(Args, CmdArgs); - } + Input.getInputArg().renderAsInput(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); @@ -7036,14 +7843,9 @@ static std::string FindFallback(const char *FallbackName, if (!OptPath.hasValue()) return FallbackName; -#ifdef LLVM_ON_WIN32 - const StringRef PathSeparators = ";"; -#else - const StringRef PathSeparators = ":"; -#endif - + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; SmallVector<StringRef, 8> PathSegments; - llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators); + llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); for (size_t i = 0, e = PathSegments.size(); i != e; ++i) { const StringRef &PathSegment = PathSegments[i]; @@ -7093,19 +7895,31 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, // 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.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, + /*default=*/false)) + CmdArgs.push_back("/GR-"); + if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections, + options::OPT_fno_function_sections)) + CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections + ? "/Gy" + : "/Gy-"); + if (Arg *A = Args.getLastArg(options::OPT_fdata_sections, + options::OPT_fno_data_sections)) + CmdArgs.push_back( + A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-"); if (Args.hasArg(options::OPT_fsyntax_only)) CmdArgs.push_back("/Zs"); + if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only)) + CmdArgs.push_back("/Z7"); std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include); - for (size_t I = 0, E = Includes.size(); I != E; ++I) - CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I])); + for (const auto &Include : Includes) + CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include)); // Flags that can simply be passed through. Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD); Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd); + Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH); // The order of these flags is relevant, so pick the last one. if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd, @@ -7131,7 +7945,6 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); std::string Exec = FindFallback("cl.exe", D.getClangProgramPath()); - return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); } @@ -7151,21 +7964,24 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-c"); - if (Args.hasArg(options::OPT_g_Group)) { - CmdArgs.push_back("-g"); - } + if (Args.hasArg(options::OPT_v)) + CmdArgs.push_back("-v"); + + if (Arg *A = Args.getLastArg(options::OPT_g_Group)) + if (!A->getOption().matches(options::OPT_g0)) + CmdArgs.push_back("-g"); + + if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, + false)) + CmdArgs.push_back("-fverbose-asm"); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("xcc")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -7183,9 +7999,15 @@ void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA, assert(Output.isNothing() && "Invalid output."); } + if (Args.hasArg(options::OPT_v)) + CmdArgs.push_back("-v"); + + ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple()); + if (EH.ShouldUseExceptionTables) + CmdArgs.push_back("-fexceptions"); + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("xcc")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } |