diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Tools.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 1757 |
1 files changed, 820 insertions, 937 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 5739fa1..294b791 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -8,33 +8,31 @@ //===----------------------------------------------------------------------===// #include "Tools.h" - +#include "InputInfo.h" +#include "SanitizerArgs.h" +#include "ToolChains.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" #include "clang/Driver/Action.h" #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" +#include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/Compilation.h" #include "clang/Driver/Job.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" -#include "clang/Basic/ObjCRuntime.h" - #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" #include "llvm/Support/Process.h" -#include "llvm/Support/ErrorHandling.h" - -#include "InputInfo.h" -#include "SanitizerArgs.h" -#include "ToolChains.h" +#include "llvm/Support/raw_ostream.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -230,6 +228,7 @@ static bool forwardToGCC(const Option &O) { } void Clang::AddPreprocessingOptions(Compilation &C, + const JobAction &JA, const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, @@ -250,15 +249,15 @@ void Clang::AddPreprocessingOptions(Compilation &C, const char *DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(); - C.addFailureResultFile(DepFile); + C.addFailureResultFile(DepFile, &JA); } else if (Output.getType() == types::TY_Dependencies) { DepFile = Output.getFilename(); } else if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { - DepFile = darwin::CC1::getDependencyFileName(Args, Inputs); - C.addFailureResultFile(DepFile); + DepFile = getDependencyFileName(Args, Inputs); + C.addFailureResultFile(DepFile, &JA); } CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); @@ -415,21 +414,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); } } - - // If a module path was provided, pass it along. Otherwise, use a temporary - // directory. - if (Arg *A = Args.getLastArg(options::OPT_fmodule_cache_path)) { - A->claim(); - A->render(Args, CmdArgs); - } else { - SmallString<128> DefaultModuleCache; - llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, - DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "clang-module-cache"); - CmdArgs.push_back("-fmodule-cache-path"); - CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); - } - + // Parse additional include paths from environment variables. // FIXME: We should probably sink the logic for handling these from the // frontend into the driver. It will allow deleting 4 otherwise unused flags. @@ -471,10 +456,12 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) { .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") - .Cases("cortex-a8", "cortex-a9", "cortex-a15", "v7") - .Case("cortex-m3", "v7m") - .Case("cortex-m4", "v7m") + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") + .Cases("cortex-a9", "cortex-a15", "v7") + .Case("cortex-r5", "v7r") .Case("cortex-m0", "v6m") + .Case("cortex-m3", "v7m") + .Case("cortex-m4", "v7em") .Case("cortex-a9-mp", "v7f") .Case("swift", "v7s") .Default(""); @@ -530,7 +517,9 @@ static std::string getARMTargetCPU(const ArgList &Args, .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") @@ -538,7 +527,6 @@ static std::string getARMTargetCPU(const ArgList &Args, .Case("ep9312", "ep9312") .Case("iwmmxt", "iwmmxt") .Case("xscale", "xscale") - .Cases("armv6m", "armv6-m", "cortex-m0") // If all else failed, return the most base CPU LLVM supports. .Default("arm7tdmi"); } @@ -549,6 +537,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { default: return true; + case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::ppc: case llvm::Triple::ppc64: @@ -609,8 +598,9 @@ static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args, CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+neonfp"); - if (CPU != "cortex-a8" && CPU != "cortex-a9" && CPU != "cortex-a9-mp" && - CPU != "cortex-a15") + if (CPU != "cortex-a5" && CPU != "cortex-a7" && + CPU != "cortex-a8" && CPU != "cortex-a9" && + CPU != "cortex-a9-mp" && CPU != "cortex-a15") D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU; } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" || @@ -883,8 +873,8 @@ static void getMipsCPUAndABI(const ArgList &Args, if (!ABIName.empty()) { // Deduce CPU name from ABI name. CPUName = llvm::StringSwitch<const char *>(ABIName) - .Cases("o32", "eabi", DefMips32CPU) - .Cases("n32", "n64", DefMips64CPU) + .Cases("32", "o32", "eabi", DefMips32CPU) + .Cases("n32", "n64", "64", DefMips64CPU) .Default(""); } else if (!CPUName.empty()) { @@ -898,6 +888,14 @@ static void getMipsCPUAndABI(const ArgList &Args, // FIXME: Warn on inconsistent cpu and abi usage. } +// Convert ABI name to the GNU tools acceptable variant. +static StringRef getGnuCompatibleMipsABIName(StringRef ABI) { + return llvm::StringSwitch<llvm::StringRef>(ABI) + .Case("o32", "32") + .Case("n64", "64") + .Default(ABI); +} + // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, // and -mfloat-abi=. static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) { @@ -960,7 +958,9 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, StringRef FloatABI = getMipsFloatABI(D, Args); - if (FloatABI == "soft") { + bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; + + if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); CmdArgs.push_back("-mfloat-abi"); @@ -971,6 +971,11 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, // Now it is the only method. CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+soft-float"); + + if (FloatABI == "hard" && IsMips16) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-mips16-hard-float"); + } } else if (FloatABI == "single") { // Restrict the use of hardware floating-point @@ -995,6 +1000,13 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, options::OPT_mdspr2, options::OPT_mno_dspr2, "dspr2"); + if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { + if (A->getOption().matches(options::OPT_mxgot)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-mxgot"); + } + } + if (Arg *A = Args.getLastArg(options::OPT_G)) { StringRef v = A->getValue(); CmdArgs.push_back("-mllvm"); @@ -1029,6 +1041,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("604", "604") .Case("604e", "604e") .Case("620", "620") + .Case("630", "pwr3") .Case("G3", "g3") .Case("7400", "7400") .Case("G4", "g4") @@ -1038,10 +1051,23 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("970", "970") .Case("G5", "g5") .Case("a2", "a2") + .Case("a2q", "a2q") .Case("e500mc", "e500mc") .Case("e5500", "e5500") + .Case("power3", "pwr3") + .Case("power4", "pwr4") + .Case("power5", "pwr5") + .Case("power5x", "pwr5x") .Case("power6", "pwr6") + .Case("power6x", "pwr6x") .Case("power7", "pwr7") + .Case("pwr3", "pwr3") + .Case("pwr4", "pwr4") + .Case("pwr5", "pwr5") + .Case("pwr5x", "pwr5x") + .Case("pwr6", "pwr6") + .Case("pwr6x", "pwr6x") + .Case("pwr7", "pwr7") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Default(""); @@ -1069,6 +1095,55 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(TargetCPUName.c_str())); } + + // Allow override of the Altivec feature. + AddTargetFeature(Args, CmdArgs, + options::OPT_faltivec, options::OPT_fno_altivec, + "altivec"); + + AddTargetFeature(Args, CmdArgs, + options::OPT_mfprnd, options::OPT_mno_fprnd, + "fprnd"); + + // Note that gcc calls this mfcrf and LLVM calls this mfocrf. + AddTargetFeature(Args, CmdArgs, + options::OPT_mmfcrf, options::OPT_mno_mfcrf, + "mfocrf"); + + AddTargetFeature(Args, CmdArgs, + options::OPT_mpopcntd, options::OPT_mno_popcntd, + "popcntd"); + + // It is really only possible to turn qpx off because turning qpx on is tied + // to using the a2q CPU. + if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-qpx"); + } +} + +/// Get the (LLVM) name of the R600 gpu we are targeting. +static std::string getR600TargetGPU(const ArgList &Args) { + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + std::string GPUName = A->getValue(); + return llvm::StringSwitch<const char *>(GPUName) + .Cases("rv610", "rv620", "rv630", "r600") + .Cases("rv635", "rs780", "rs880", "r600") + .Case("rv740", "rv770") + .Case("palm", "cedar") + .Cases("sumo", "sumo2", "redwood") + .Case("hemlock", "cypress") + .Case("aruba", "cayman") + .Default(GPUName.c_str()); + } + return ""; +} + +void Clang::AddR600TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + std::string TargetGPUName = getR600TargetGPU(Args); + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str())); } void Clang::AddSparcTargetArgs(const ArgList &Args, @@ -1174,9 +1249,18 @@ void Clang::AddX86TargetArgs(const ArgList &Args, Args.hasArg(options::OPT_fapple_kext)) CmdArgs.push_back("-disable-red-zone"); - if (Args.hasFlag(options::OPT_msoft_float, - options::OPT_mno_soft_float, - false)) + // Default to avoid implicit floating-point for kernel/kext code, but allow + // that to be overridden with -mno-soft-float. + bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)); + if (Arg *A = Args.getLastArg(options::OPT_msoft_float, + options::OPT_mno_soft_float, + options::OPT_mno_implicit_float)) { + const Option &O = A->getOption(); + NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) || + O.matches(options::OPT_msoft_float)); + } + if (NoImplicitFloat) CmdArgs.push_back("-no-implicit-float"); if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) { @@ -1219,43 +1303,26 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } -static Arg* getLastHexagonArchArg (const ArgList &Args) -{ - Arg * A = NULL; - - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it) { - if ((*it)->getOption().matches(options::OPT_march_EQ) || - (*it)->getOption().matches(options::OPT_mcpu_EQ)) { - A = *it; - A->claim(); - } - else if ((*it)->getOption().matches(options::OPT_m_Joined)){ - StringRef Value = (*it)->getValue(0); - if (Value.startswith("v")) { - A = *it; - A->claim(); - } - } - } - return A; +static inline bool HasPICArg(const ArgList &Args) { + return Args.hasArg(options::OPT_fPIC) + || Args.hasArg(options::OPT_fpic); } -static StringRef getHexagonTargetCPU(const ArgList &Args) -{ - Arg *A; - llvm::StringRef WhichHexagon; +static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) { + return Args.getLastArg(options::OPT_G, + options::OPT_G_EQ, + options::OPT_msmall_data_threshold_EQ); +} - // Select the default CPU (v4) if none was given or detection failed. - if ((A = getLastHexagonArchArg (Args))) { - WhichHexagon = A->getValue(); - if (WhichHexagon == "") - return "v4"; - else - return WhichHexagon; +static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) { + std::string value; + if (HasPICArg(Args)) + value = "0"; + else if (Arg *A = GetLastSmallDataThresholdArg(Args)) { + value = A->getValue(); + A->claim(); } - else - return "v4"; + return value; } void Clang::AddHexagonTargetArgs(const ArgList &Args, @@ -1263,20 +1330,18 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, llvm::Triple Triple = getToolChain().getTriple(); CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(Args.MakeArgString("hexagon" + getHexagonTargetCPU(Args))); + CmdArgs.push_back(Args.MakeArgString( + "hexagon" + + toolchains::Hexagon_TC::GetTargetCPU(Args))); CmdArgs.push_back("-fno-signed-char"); - CmdArgs.push_back("-nobuiltininc"); - - if (Args.hasArg(options::OPT_mqdsp6_compat)) - CmdArgs.push_back("-mqdsp6-compat"); + CmdArgs.push_back("-mqdsp6-compat"); + CmdArgs.push_back("-Wreturn-type"); - if (Arg *A = Args.getLastArg(options::OPT_G, - options::OPT_msmall_data_threshold_EQ)) { - std::string SmallDataThreshold="-small-data-threshold="; - SmallDataThreshold += A->getValue(); + std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); + if (!SmallDataThreshold.empty()) { CmdArgs.push_back ("-mllvm"); - CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold)); - A->claim(); + CmdArgs.push_back(Args.MakeArgString( + "-hexagon-small-data-threshold=" + SmallDataThreshold)); } if (!Args.hasArg(options::OPT_fno_short_enums)) @@ -1393,24 +1458,18 @@ static bool ShouldDisableCFI(const ArgList &Args, 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 = Args.hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - TC.IsIntegratedAssemblerDefault()); + Default = TC.useIntegratedAs(); } return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, - options::OPT_fno_dwarf2_cfi_asm, - Default); + options::OPT_fno_dwarf2_cfi_asm, + Default); } static bool ShouldDisableDwarfDirectory(const ArgList &Args, const ToolChain &TC) { - bool IsIADefault = TC.IsIntegratedAssemblerDefault(); - bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - IsIADefault); bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm, options::OPT_fno_dwarf_directory_asm, - UseIntegratedAs); + TC.useIntegratedAs()); return !UseDwarfDirectory; } @@ -1449,63 +1508,147 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { RelaxDefault); } -SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) { - Kind = 0; - - const Arg *AsanArg, *TsanArg, *UbsanArg; +SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) + : Kind(0), BlacklistFile(""), MsanTrackOrigins(false), + AsanZeroBaseShadow(false) { + unsigned AllKinds = 0; // All kinds of sanitizers that were turned on + // at least once (possibly, disabled further). for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { - unsigned Add = 0, Remove = 0; - const char *DeprecatedReplacement = 0; - if ((*I)->getOption().matches(options::OPT_faddress_sanitizer)) { - Add = Address; - DeprecatedReplacement = "-fsanitize=address"; - } else if ((*I)->getOption().matches(options::OPT_fno_address_sanitizer)) { - Remove = Address; - DeprecatedReplacement = "-fno-sanitize=address"; - } else if ((*I)->getOption().matches(options::OPT_fthread_sanitizer)) { - Add = Thread; - DeprecatedReplacement = "-fsanitize=thread"; - } else if ((*I)->getOption().matches(options::OPT_fno_thread_sanitizer)) { - Remove = Thread; - DeprecatedReplacement = "-fno-sanitize=thread"; - } else if ((*I)->getOption().matches(options::OPT_fcatch_undefined_behavior)) { - Add = Undefined; - DeprecatedReplacement = "-fsanitize=undefined"; - } else if ((*I)->getOption().matches(options::OPT_fsanitize_EQ)) { - Add = parse(D, *I); - } else if ((*I)->getOption().matches(options::OPT_fno_sanitize_EQ)) { - Remove = parse(D, *I); - } else { + unsigned Add, Remove; + if (!parse(D, Args, *I, Add, Remove, true)) continue; - } - (*I)->claim(); - Kind |= Add; Kind &= ~Remove; + AllKinds |= Add; + } - if (Add & NeedsAsanRt) AsanArg = *I; - if (Add & NeedsTsanRt) TsanArg = *I; - if (Add & NeedsUbsanRt) UbsanArg = *I; + UbsanTrapOnError = + Args.hasArg(options::OPT_fcatch_undefined_behavior) || + Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + options::OPT_fno_sanitize_undefined_trap_on_error, false); - // If this is a deprecated synonym, produce a warning directing users - // towards the new spelling. - if (DeprecatedReplacement) - D.Diag(diag::warn_drv_deprecated_arg) - << (*I)->getAsString(Args) << DeprecatedReplacement; + if (Args.hasArg(options::OPT_fcatch_undefined_behavior) && + !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + options::OPT_fno_sanitize_undefined_trap_on_error, true)) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fcatch-undefined-behavior" + << "-fno-sanitize-undefined-trap-on-error"; + } + + // Warn about undefined sanitizer options that require runtime support. + if (UbsanTrapOnError && notAllowedWithTrap()) { + if (Args.hasArg(options::OPT_fcatch_undefined_behavior)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, NotAllowedWithTrap) + << "-fcatch-undefined-behavior"; + else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + options::OPT_fno_sanitize_undefined_trap_on_error, + false)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, NotAllowedWithTrap) + << "-fsanitize-undefined-trap-on-error"; } // Only one runtime library can be used at once. - // FIXME: Allow Ubsan to be combined with the other two. bool NeedsAsan = needsAsanRt(); bool NeedsTsan = needsTsanRt(); - bool NeedsUbsan = needsUbsanRt(); - if (NeedsAsan + NeedsTsan + NeedsUbsan > 1) + bool NeedsMsan = needsMsanRt(); + if (NeedsAsan && NeedsTsan) D.Diag(diag::err_drv_argument_not_allowed_with) - << describeSanitizeArg(Args, NeedsAsan ? AsanArg : TsanArg, - NeedsAsan ? NeedsAsanRt : NeedsTsanRt) - << describeSanitizeArg(Args, NeedsUbsan ? UbsanArg : TsanArg, - NeedsUbsan ? NeedsUbsanRt : NeedsTsanRt); + << lastArgumentForKind(D, Args, NeedsAsanRt) + << lastArgumentForKind(D, Args, NeedsTsanRt); + if (NeedsAsan && NeedsMsan) + D.Diag(diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, NeedsAsanRt) + << lastArgumentForKind(D, Args, NeedsMsanRt); + if (NeedsTsan && NeedsMsan) + D.Diag(diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, NeedsTsanRt) + << lastArgumentForKind(D, Args, NeedsMsanRt); + + // If -fsanitize contains extra features of ASan, it should also + // explicitly contain -fsanitize=address (probably, turned off later in the + // command line). + if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0) + D.Diag(diag::warn_drv_unused_sanitizer) + << lastArgumentForKind(D, Args, AddressFull) + << "-fsanitize=address"; + + // Parse -f(no-)sanitize-blacklist options. + if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist, + options::OPT_fno_sanitize_blacklist)) { + if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) { + std::string BLPath = BLArg->getValue(); + bool BLExists = false; + if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists) + BlacklistFile = BLPath; + else + D.Diag(diag::err_drv_no_such_file) << BLPath; + } + } else { + // If no -fsanitize-blacklist option is specified, try to look up for + // blacklist in the resource directory. + std::string BLPath; + bool BLExists = false; + if (getDefaultBlacklistForKind(D, Kind, BLPath) && + !llvm::sys::fs::exists(BLPath, BLExists) && BLExists) + BlacklistFile = BLPath; + } + + // Parse -f(no-)sanitize-memory-track-origins options. + if (NeedsMsan) + MsanTrackOrigins = + Args.hasFlag(options::OPT_fsanitize_memory_track_origins, + options::OPT_fno_sanitize_memory_track_origins, + /* Default */false); + + // Parse -f(no-)sanitize-address-zero-base-shadow options. + if (NeedsAsan) + AsanZeroBaseShadow = + Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow, + options::OPT_fno_sanitize_address_zero_base_shadow, + /* Default */false); +} + +static void addSanitizerRTLinkFlagsLinux( + const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, + const StringRef Sanitizer, bool BeforeLibStdCXX, + bool ExportSymbols = true) { + // Sanitizer runtime is located in the Linux library directory and + // has name "libclang_rt.<Sanitizer>-<ArchName>.a". + SmallString<128> LibSanitizer(TC.getDriver().ResourceDir); + llvm::sys::path::append( + LibSanitizer, "lib", "linux", + (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a")); + + // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a, + // etc.) so that the linker picks custom versions of the global 'operator + // new' and 'operator delete' symbols. We take the extreme (but simple) + // strategy of inserting it at the front of the link command. It also + // needs to be forced to end up in the executable, so wrap it in + // whole-archive. + SmallVector<const char *, 3> LibSanitizerArgs; + LibSanitizerArgs.push_back("-whole-archive"); + LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer)); + LibSanitizerArgs.push_back("-no-whole-archive"); + + CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(), + LibSanitizerArgs.begin(), LibSanitizerArgs.end()); + + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + + // If possible, use a dynamic symbols file to export the symbols from the + // runtime library. If we can't do so, use -export-dynamic instead to export + // all symbols from the binary. + if (ExportSymbols) { + if (llvm::sys::fs::exists(LibSanitizer + ".syms")) + CmdArgs.push_back( + Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms")); + else + CmdArgs.push_back("-export-dynamic"); + } } /// If AddressSanitizer is enabled, add appropriate linker flags (Linux). @@ -1522,19 +1665,17 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, llvm::sys::path::append(LibAsan, "lib", "linux", (Twine("libclang_rt.asan-") + TC.getArchName() + "-android.so")); - CmdArgs.push_back(Args.MakeArgString(LibAsan)); + CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan)); } else { if (!Args.hasArg(options::OPT_shared)) { - // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library - // resource directory. - SmallString<128> LibAsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibAsan, "lib", "linux", - (Twine("libclang_rt.asan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibAsan)); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-export-dynamic"); + bool ZeroBaseShadow = Args.hasFlag( + options::OPT_fsanitize_address_zero_base_shadow, + options::OPT_fno_sanitize_address_zero_base_shadow, false); + if (ZeroBaseShadow && !Args.hasArg(options::OPT_pie)) { + TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << + "-fsanitize-address-zero-base-shadow" << "-pie"; + } + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); } } } @@ -1544,33 +1685,44 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) { - // LibTsan is "libclang_rt.tsan-<ArchName>.a" in the Linux library - // resource directory. - SmallString<128> LibTsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibTsan, "lib", "linux", - (Twine("libclang_rt.tsan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibTsan)); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-export-dynamic"); + if (!Args.hasArg(options::OPT_pie)) + TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << + "-fsanitize=thread" << "-pie"; + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true); + } +} + +/// If MemorySanitizer is enabled, add appropriate linker flags (Linux). +/// This needs to be called before we add the C run-time (malloc, etc). +static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + if (!Args.hasArg(options::OPT_shared)) { + if (!Args.hasArg(options::OPT_pie)) + TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << + "-fsanitize=memory" << "-pie"; + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true); } } /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags /// (Linux). static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_shared)) { - // LibUbsan is "libclang_rt.ubsan-<ArchName>.a" in the Linux library - // resource directory. - SmallString<128> LibUbsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibUbsan, "lib", "linux", - (Twine("libclang_rt.ubsan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibUbsan)); - CmdArgs.push_back("-lpthread"); - } + ArgStringList &CmdArgs, bool IsCXX, + bool HasOtherSanitizerRt) { + if (Args.hasArg(options::OPT_shared)) + return; + + // Need a copy of sanitizer_common. This could come from another sanitizer + // runtime; if we're not including one, include our own copy. + if (!HasOtherSanitizerRt) + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false); + + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false); + + // Only include the bits of the runtime which need a C++ ABI library if + // we're linking in C++ mode. + if (IsCXX) + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false); } static bool shouldUseFramePointer(const ArgList &Args, @@ -1591,6 +1743,80 @@ static bool shouldUseFramePointer(const ArgList &Args, return true; } +static bool shouldUseLeafFramePointer(const ArgList &Args, + const llvm::Triple &Triple) { + if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer, + options::OPT_momit_leaf_frame_pointer)) + return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); + + // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing. + if ((Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::x86) && + Triple.getOS() == llvm::Triple::Linux) { + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) + if (!A->getOption().matches(options::OPT_O0)) + return false; + } + + return true; +} + +/// If the PWD environment variable is set, add a CC1 option to specify the +/// debug compilation directory. +static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { + if (const char *pwd = ::getenv("PWD")) { + // GCC also verifies that stat(pwd) and stat(".") have the same inode + // number. Not doing those because stats are slow, but we could. + if (llvm::sys::path::is_absolute(pwd)) { + std::string CompDir = pwd; + CmdArgs.push_back("-fdebug-compilation-dir"); + CmdArgs.push_back(Args.MakeArgString(CompDir)); + } + } +} + +static const char *SplitDebugName(const ArgList &Args, + const InputInfoList &Inputs) { + Arg *FinalOutput = Args.getLastArg(options::OPT_o); + if (FinalOutput && Args.hasArg(options::OPT_c)) { + SmallString<128> T(FinalOutput->getValue()); + llvm::sys::path::replace_extension(T, "dwo"); + return Args.MakeArgString(T); + } else { + // Use the compilation dir. + SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); + SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput())); + llvm::sys::path::replace_extension(F, "dwo"); + T += F; + return Args.MakeArgString(F); + } +} + +static void SplitDebugInfo(const ToolChain &TC, Compilation &C, + const Tool &T, const JobAction &JA, + const ArgList &Args, const InputInfo &Output, + const char *OutFile) { + ArgStringList ExtractArgs; + ExtractArgs.push_back("--extract-dwo"); + + ArgStringList StripArgs; + StripArgs.push_back("--strip-dwo"); + + // Grabbing the output of the earlier compile step. + StripArgs.push_back(Output.getFilename()); + ExtractArgs.push_back(Output.getFilename()); + ExtractArgs.push_back(OutFile); + + const char *Exec = + Args.MakeArgString(TC.GetProgramPath("objcopy")); + + // First extract the dwo sections. + C.addCommand(new Command(JA, T, Exec, ExtractArgs)); + + // Then remove them from the original .o file. + C.addCommand(new Command(JA, T, Exec, StripArgs)); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -1624,8 +1850,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (isa<PreprocessJobAction>(JA)) { if (Output.getType() == types::TY_Dependencies) CmdArgs.push_back("-Eonly"); - else + else { CmdArgs.push_back("-E"); + if (Args.hasArg(options::OPT_rewrite_objc) && + !Args.hasArg(options::OPT_g_Group)) + CmdArgs.push_back("-P"); + } } else if (isa<AssembleJobAction>(JA)) { CmdArgs.push_back("-emit-obj"); @@ -1686,6 +1916,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-S"); } else if (JA.getType() == types::TY_AST) { CmdArgs.push_back("-emit-pch"); + } else if (JA.getType() == types::TY_ModuleFile) { + CmdArgs.push_back("-module-file-info"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_NonFragile; @@ -1709,10 +1941,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Set the main file name, so that debug info works even with // -save-temps. CmdArgs.push_back("-main-file-name"); - CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs)); + CmdArgs.push_back(getBaseInputName(Args, Inputs)); // Some flags which affect the language (via preprocessor - // defines). See darwin::CC1::AddCPPArgs. + // defines). if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static-define"); @@ -1808,8 +2040,7 @@ 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 ((Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_fapple_kext)) && + if (KernelOrKext && (Triple.getOS() != llvm::Triple::IOS || Triple.isOSVersionLT(6))) PIC = PIE = false; @@ -1874,6 +2105,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasArg(options::OPT_fstruct_path_tbaa)) + CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); @@ -1881,6 +2114,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_optimize_sibling_calls)) CmdArgs.push_back("-mdisable-tail-calls"); + // Handle segmented stacks. + if (Args.hasArg(options::OPT_fsplit_stack)) + CmdArgs.push_back("-split-stacks"); + // Handle various floating point optimization flags, mapping them to the // appropriate LLVM code generation flags. The pattern for all of these is to // default off the codegen optimizations, and if any flag enables them and no @@ -2043,7 +2280,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); - getToolChain().addClangTargetOptions(CmdArgs); + getToolChain().addClangTargetOptions(Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); @@ -2080,6 +2317,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AddPPCTargetArgs(Args, CmdArgs); break; + case llvm::Triple::r600: + AddR600TargetArgs(Args, CmdArgs); + break; + case llvm::Triple::sparc: AddSparcTargetArgs(Args, CmdArgs); break; @@ -2102,10 +2343,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } - // -mno-omit-leaf-frame-pointer is the default on Darwin. - if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, - options::OPT_mno_omit_leaf_frame_pointer, - !getToolChain().getTriple().isOSDarwin())) + if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple())) CmdArgs.push_back("-momit-leaf-frame-pointer"); // Explicitly error on some things we know we don't support and can't just @@ -2139,16 +2377,15 @@ 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" + // is preserved, all other debug options are substituted with "-g". Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) { - if (A->getOption().matches(options::OPT_gline_tables_only)) { + if (A->getOption().matches(options::OPT_gline_tables_only)) CmdArgs.push_back("-gline-tables-only"); - } else if (!A->getOption().matches(options::OPT_g0) && - !A->getOption().matches(options::OPT_ggdb0)) { + else if (!A->getOption().matches(options::OPT_g0) && + !A->getOption().matches(options::OPT_ggdb0)) CmdArgs.push_back("-g"); - } } // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. @@ -2156,6 +2393,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gcolumn_info)) CmdArgs.push_back("-dwarf-column-info"); + // -gsplit-dwarf should turn on -g and enable the backend dwarf + // splitting and extraction. + // FIXME: Currently only works on Linux. + if (getToolChain().getTriple().getOS() == llvm::Triple::Linux && + Args.hasArg(options::OPT_gsplit_dwarf)) { + CmdArgs.push_back("-g"); + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-split-dwarf=Enable"); + } + Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); @@ -2172,9 +2419,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { CmdArgs.push_back("-coverage-file"); - SmallString<128> absFilename(Output.getFilename()); - llvm::sys::fs::make_absolute(absFilename); - CmdArgs.push_back(Args.MakeArgString(absFilename)); + SmallString<128> CoverageFilename(Output.getFilename()); + if (llvm::sys::path::is_relative(CoverageFilename.str())) { + if (const char *pwd = ::getenv("PWD")) { + if (llvm::sys::path::is_absolute(pwd)) { + SmallString<128> Pwd(pwd); + llvm::sys::path::append(Pwd, CoverageFilename.str()); + CoverageFilename.swap(Pwd); + } + } + } + CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); } } @@ -2246,7 +2501,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: Support -fpreprocessed if (types::getPreprocessedType(InputType) != types::TY_INVALID) - AddPreprocessingOptions(C, D, Args, CmdArgs, Output, Inputs); + AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs); // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes // that "The compiler can only warn and ignore the option if not recognized". @@ -2266,6 +2521,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, A->render(Args, CmdArgs); } + // Don't warn about unused -flto. This can happen when we're preprocessing or + // precompiling. + Args.ClaimAllArgs(options::OPT_flto); + Args.AddAllArgs(CmdArgs, options::OPT_W_Group); if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false)) CmdArgs.push_back("-pedantic"); @@ -2338,15 +2597,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (ShouldDisableDwarfDirectory(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf-directory-asm"); - if (const char *pwd = ::getenv("PWD")) { - // GCC also verifies that stat(pwd) and stat(".") have the same inode - // number. Not doing those because stats are slow, but we could. - if (llvm::sys::path::is_absolute(pwd)) { - std::string CompDir = pwd; - CmdArgs.push_back("-fdebug-compilation-dir"); - CmdArgs.push_back(Args.MakeArgString(CompDir)); - } - } + // Add in -fdebug-compilation-dir if necessary. + addDebugCompDirArg(Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, options::OPT_ftemplate_depth_EQ)) { @@ -2359,6 +2611,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } + if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) { + CmdArgs.push_back("-fbracket-depth"); + CmdArgs.push_back(A->getValue()); + } + if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ, options::OPT_Wlarge_by_value_copy_def)) { if (A->getNumValues()) { @@ -2368,14 +2625,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value } - if (Arg *A = Args.getLastArg(options::OPT_fbounds_checking, - options::OPT_fbounds_checking_EQ)) { - if (A->getNumValues()) { - StringRef val = A->getValue(); - CmdArgs.push_back(Args.MakeArgString("-fbounds-checking=" + val)); - } else - CmdArgs.push_back("-fbounds-checking=1"); - } if (Args.hasArg(options::OPT_relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); @@ -2422,9 +2671,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Twine(N))); } - if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) { - CmdArgs.push_back("-fvisibility"); - CmdArgs.push_back(A->getValue()); + // -fvisibility= and -fvisibility-ms-compat are of a piece. + if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) { + if (A->getOption().matches(options::OPT_fvisibility_EQ)) { + CmdArgs.push_back("-fvisibility"); + CmdArgs.push_back(A->getValue()); + } else { + assert(A->getOption().matches(options::OPT_fvisibility_ms_compat)); + CmdArgs.push_back("-fvisibility"); + CmdArgs.push_back("hidden"); + CmdArgs.push_back("-ftype-visibility"); + CmdArgs.push_back("default"); + } } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); @@ -2450,7 +2709,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, SanitizerArgs Sanitize(D, Args); Sanitize.addArgs(Args, CmdArgs); - // Report and error for -faltivec on anything other then PowerPC. + if (!Args.hasFlag(options::OPT_fsanitize_recover, + options::OPT_fno_sanitize_recover, + true)) + CmdArgs.push_back("-fno-sanitize-recover"); + + if (Args.hasArg(options::OPT_fcatch_undefined_behavior) || + Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + options::OPT_fno_sanitize_undefined_trap_on_error, false)) + CmdArgs.push_back("-fsanitize-undefined-trap-on-error"); + + // Report an error for -faltivec on anything other than PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || getToolChain().getTriple().getArch() == llvm::Triple::ppc64)) @@ -2549,7 +2818,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } - if (Args.hasArg(options::OPT_mstrict_align)) { + // -mkernel implies -mstrict-align; don't add the redundant option. + if (Args.hasArg(options::OPT_mstrict_align) && !KernelOrKext) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-arm-strict-align"); } @@ -2588,12 +2858,49 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fmodules enables modules (off by default). However, for C++/Objective-C++, // users must also pass -fcxx-modules. The latter flag will disappear once the // modules implementation is solid for C++/Objective-C++ programs as well. + bool HaveModules = false; if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, options::OPT_fno_cxx_modules, false); - if (AllowedInCXX || !types::isCXX(InputType)) + if (AllowedInCXX || !types::isCXX(InputType)) { CmdArgs.push_back("-fmodules"); + HaveModules = true; + } + } + + // If a module path was provided, pass it along. Otherwise, use a temporary + // directory. + if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) { + A->claim(); + if (HaveModules) { + A->render(Args, CmdArgs); + } + } else if (HaveModules) { + SmallString<128> DefaultModuleCache; + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, + DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); + llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + const char Arg[] = "-fmodules-cache-path="; + DefaultModuleCache.insert(DefaultModuleCache.begin(), + Arg, Arg + strlen(Arg)); + CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); + } + + // Pass through all -fmodules-ignore-macro arguments. + Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); + Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval); + Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after); + + // -fmodules-autolink (on by default when modules is enabled) automatically + // links against libraries for imported modules. This requires the + // integrated assembler. + if (HaveModules && getToolChain().useIntegratedAs() && + Args.hasFlag(options::OPT_fmodules_autolink, + options::OPT_fno_modules_autolink, + true)) { + CmdArgs.push_back("-fmodules-autolink"); } // -faccess-control is default. @@ -2655,10 +2962,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fms-extensions"); - // -fms-inline-asm. - if (Args.hasArg(options::OPT_fenable_experimental_ms_inline_asm)) - CmdArgs.push_back("-fenable-experimental-ms-inline-asm"); - // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, @@ -2680,7 +2983,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } - // -fborland-extensions=0 is default. + // -fno-borland-extensions is default. if (Args.hasFlag(options::OPT_fborland_extensions, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); @@ -2834,8 +3137,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fpack-struct=1"); } - if (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_fapple_kext)) { + if (KernelOrKext) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); Args.ClaimAllArgs(options::OPT_fno_common); @@ -2916,9 +3218,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-spell-checking"); - // Silently ignore -fasm-blocks for now. - (void) Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks, - false); + // -fno-asm-blocks is default. + if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks, + false)) + CmdArgs.push_back("-fasm-blocks"); + + // -fvectorize is default. + if (Args.hasFlag(options::OPT_fvectorize, + options::OPT_fno_vectorize, true)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-vectorize-loops"); + } + + // -fno-slp-vectorize is default. + if (Args.hasFlag(options::OPT_fslp_vectorize, + options::OPT_fno_slp_vectorize, false)) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-vectorize"); + } if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); @@ -2980,6 +3297,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fretain_comments_from_system_headers)) CmdArgs.push_back("-fretain-comments-from-system-headers"); + // Forward -fcomment-block-commands to -cc1. + Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands); + // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); @@ -3040,8 +3360,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Flags.str())); } + // Add the split debug info name to the command lines here so we + // can propagate it to the backend. + bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) && + (getToolChain().getTriple().getOS() == llvm::Triple::Linux) && + (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA)); + const char *SplitDwarfOut; + if (SplitDwarf) { + CmdArgs.push_back("-split-dwarf-file"); + SplitDwarfOut = SplitDebugName(Args, Inputs); + CmdArgs.push_back(SplitDwarfOut); + } + + // Finally add the compile command to the compilation. C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + // Handle the debug info splitting at object creation time if we're + // creating an object. + // TODO: Currently only works on linux with newer objcopy. + if (SplitDwarf && !isa<CompileJobAction>(JA)) + SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut); + if (Arg *A = Args.getLastArg(options::OPT_pg)) if (Args.hasArg(options::OPT_fomit_frame_pointer)) D.Diag(diag::err_drv_argument_not_allowed_with) @@ -3249,6 +3588,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-filetype"); CmdArgs.push_back("obj"); + // Set the main file name, so that debug info works even with + // -save-temps or preprocessed assembly. + CmdArgs.push_back("-main-file-name"); + CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs)); + if (UseRelaxAll(C, Args)) CmdArgs.push_back("-relax-all"); @@ -3278,13 +3622,22 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SourceAction = SourceAction->getInputs()[0]; } - // Forward -g, assuming we are dealing with an actual assembly file. + // Forward -g and handle debug info related flags, assuming we are dealing + // with an actual assembly file. if (SourceAction->getType() == types::TY_Asm || SourceAction->getType() == types::TY_PP_Asm) { Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) if (!A->getOption().matches(options::OPT_g0)) CmdArgs.push_back("-g"); + + // Add the -fdebug-compilation-dir flag if needed. + addDebugCompDirArg(Args, CmdArgs); + + // Set the AT_producer to the clang version when using the integrated + // assembler on assembly source files. + CmdArgs.push_back("-dwarf-debug-producer"); + CmdArgs.push_back(Args.MakeArgString(getClangFullVersion())); } // Optionally embed the -cc1as level arguments into the debug info, for build @@ -3372,7 +3725,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // here. if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) CmdArgs.push_back("-m32"); - else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86_64) + else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64) CmdArgs.push_back("-m64"); if (Output.isFilename()) { @@ -3406,6 +3759,9 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, else if (II.getType() == types::TY_AST) D.Diag(diag::err_drv_no_ast_support) << getToolChain().getTripleString(); + else if (II.getType() == types::TY_ModuleFile) + D.Diag(diag::err_drv_no_module_support) + << getToolChain().getTripleString(); if (types::canTypeBeUserSpecified(II.getType())) { CmdArgs.push_back("-x"); @@ -3494,7 +3850,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, ArgStringList CmdArgs; std::string MarchString = "-march="; - MarchString += getHexagonTargetCPU(Args); + MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString(MarchString)); RenderExtraToolArgs(JA, CmdArgs); @@ -3507,6 +3863,14 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fsyntax-only"); } + std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); + if (!SmallDataThreshold.empty()) + CmdArgs.push_back( + Args.MakeArgString(std::string("-G") + SmallDataThreshold)); + + Args.AddAllArgs(CmdArgs, options::OPT_g_Group); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go @@ -3528,6 +3892,9 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else if (II.getType() == types::TY_AST) D.Diag(clang::diag::err_drv_no_ast_support) << getToolChain().getTripleString(); + else if (II.getType() == types::TY_ModuleFile) + D.Diag(diag::err_drv_no_module_support) + << getToolChain().getTripleString(); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); @@ -3553,77 +3920,168 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, const ArgList &Args, const char *LinkingOutput) const { - const Driver &D = getToolChain().getDriver(); + const toolchains::Hexagon_TC& ToolChain = + static_cast<const toolchains::Hexagon_TC&>(getToolChain()); + const Driver &D = ToolChain.getDriver(); + ArgStringList CmdArgs; - for (ArgList::const_iterator - it = Args.begin(), ie = Args.end(); it != ie; ++it) { - Arg *A = *it; - if (forwardToGCC(A->getOption())) { - // Don't forward any -g arguments to assembly steps. - if (isa<AssembleJobAction>(JA) && - A->getOption().matches(options::OPT_g_Group)) - continue; + //---------------------------------------------------------------------------- + // + //---------------------------------------------------------------------------- + bool hasStaticArg = Args.hasArg(options::OPT_static); + bool buildingLib = Args.hasArg(options::OPT_shared); + bool buildPIE = Args.hasArg(options::OPT_pie); + bool incStdLib = !Args.hasArg(options::OPT_nostdlib); + bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles); + bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); + bool useShared = buildingLib && !hasStaticArg; + + //---------------------------------------------------------------------------- + // Silence warnings for various options + //---------------------------------------------------------------------------- - // It is unfortunate that we have to claim here, as this means - // we will basically never report anything interesting for - // platforms using a generic gcc, even if we are just using gcc - // to get to the assembler. - A->claim(); - A->render(Args, CmdArgs); - } + Args.ClaimAllArgs(options::OPT_g_Group); + Args.ClaimAllArgs(options::OPT_emit_llvm); + Args.ClaimAllArgs(options::OPT_w); // Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_static_libgcc); + + //---------------------------------------------------------------------------- + // + //---------------------------------------------------------------------------- + for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), + e = ToolChain.ExtraOpts.end(); + i != e; ++i) + CmdArgs.push_back(i->c_str()); + + std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args); + CmdArgs.push_back(Args.MakeArgString("-m" + MarchString)); + + if (buildingLib) { + CmdArgs.push_back("-shared"); + CmdArgs.push_back("-call_shared"); // should be the default, but doing as + // hexagon-gcc does } - RenderExtraToolArgs(JA, CmdArgs); + if (hasStaticArg) + CmdArgs.push_back("-static"); - // Add Arch Information - Arg *A; - if ((A = getLastHexagonArchArg(Args))) { - if (A->getOption().matches(options::OPT_m_Joined)) - A->render(Args, CmdArgs); - else - CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args))); + if (buildPIE && !buildingLib) + CmdArgs.push_back("-pie"); + + std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); + if (!SmallDataThreshold.empty()) { + CmdArgs.push_back( + Args.MakeArgString(std::string("-G") + SmallDataThreshold)); } - else { - CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args))); + + //---------------------------------------------------------------------------- + // + //---------------------------------------------------------------------------- + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + const std::string MarchSuffix = "/" + MarchString; + const std::string G0Suffix = "/G0"; + const std::string MarchG0Suffix = MarchSuffix + G0Suffix; + const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir) + + "/"; + const std::string StartFilesDir = RootDir + + "hexagon/lib" + + (buildingLib + ? MarchG0Suffix : MarchSuffix); + + //---------------------------------------------------------------------------- + // moslib + //---------------------------------------------------------------------------- + std::vector<std::string> oslibs; + bool hasStandalone= false; + + for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ), + ie = Args.filtered_end(); it != ie; ++it) { + (*it)->claim(); + oslibs.push_back((*it)->getValue()); + hasStandalone = hasStandalone || (oslibs.back() == "standalone"); + } + if (oslibs.empty()) { + oslibs.push_back("standalone"); + hasStandalone = true; } - CmdArgs.push_back("-mqdsp6-compat"); + //---------------------------------------------------------------------------- + // Start Files + //---------------------------------------------------------------------------- + if (incStdLib && incStartFiles) { - const char *GCCName; - if (C.getDriver().CCCIsCXX) - GCCName = "hexagon-g++"; - else - GCCName = "hexagon-gcc"; - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + if (!buildingLib) { + if (hasStandalone) { + CmdArgs.push_back( + Args.MakeArgString(StartFilesDir + "/crt0_standalone.o")); + } + CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o")); + } + std::string initObj = useShared ? "/initS.o" : "/init.o"; + CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj)); + } + + //---------------------------------------------------------------------------- + // Library Search Paths + //---------------------------------------------------------------------------- + const ToolChain::path_list &LibPaths = ToolChain.getFilePaths(); + for (ToolChain::path_list::const_iterator + i = LibPaths.begin(), + e = LibPaths.end(); + i != e; + ++i) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); - if (Output.isFilename()) { - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); - } + //---------------------------------------------------------------------------- + // + //---------------------------------------------------------------------------- + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_s); + Args.AddAllArgs(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_u_Group); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); - // Don't try to pass LLVM or AST inputs to a generic gcc. - if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || - II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) - D.Diag(clang::diag::err_drv_no_linker_llvm_support) - << getToolChain().getTripleString(); - else if (II.getType() == types::TY_AST) - D.Diag(clang::diag::err_drv_no_ast_support) - << getToolChain().getTripleString(); + //---------------------------------------------------------------------------- + // Libraries + //---------------------------------------------------------------------------- + if (incStdLib && incDefLibs) { + if (D.CCCIsCXX) { + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lm"); + } - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ? - II.getInputArg().render(Args, CmdArgs); + CmdArgs.push_back("--start-group"); + + if (!buildingLib) { + for(std::vector<std::string>::iterator i = oslibs.begin(), + e = oslibs.end(); i != e; ++i) + CmdArgs.push_back(Args.MakeArgString("-l" + *i)); + CmdArgs.push_back("-lc"); + } + CmdArgs.push_back("-lgcc"); + + CmdArgs.push_back("--end-group"); + } + + //---------------------------------------------------------------------------- + // End files + //---------------------------------------------------------------------------- + if (incStdLib && incStartFiles) { + std::string finiObj = useShared ? "/finiS.o" : "/fini.o"; + CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj)); } - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + std::string Linker = ToolChain.GetProgramPath("hexagon-ld"); + C.addCommand( + new Command( + JA, *this, + Args.MakeArgString(Linker), CmdArgs)); } // Hexagon tools end. @@ -3649,8 +4107,9 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { llvm::Triple::x86) .Case("x86_64", llvm::Triple::x86_64) // This is derived from the driver driver. - .Cases("arm", "armv4t", "armv5", "armv6", llvm::Triple::arm) - .Cases("armv7", "armv7f", "armv7k", "armv7s", "xscale", llvm::Triple::arm) + .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) + .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm) + .Cases("armv7s", "xscale", llvm::Triple::arm) .Case("r600", llvm::Triple::r600) .Case("nvptx", llvm::Triple::nvptx) .Case("nvptx64", llvm::Triple::nvptx64) @@ -3659,38 +4118,14 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .Default(llvm::Triple::UnknownArch); } -const char *darwin::CC1::getCC1Name(types::ID Type) const { - switch (Type) { - default: - llvm_unreachable("Unexpected type for Darwin CC1 tool."); - case types::TY_Asm: - case types::TY_C: case types::TY_CHeader: - case types::TY_PP_C: case types::TY_PP_CHeader: - return "cc1"; - case types::TY_ObjC: case types::TY_ObjCHeader: - case types::TY_PP_ObjC: case types::TY_PP_ObjC_Alias: - case types::TY_PP_ObjCHeader: - return "cc1obj"; - case types::TY_CXX: case types::TY_CXXHeader: - case types::TY_PP_CXX: case types::TY_PP_CXXHeader: - return "cc1plus"; - case types::TY_ObjCXX: case types::TY_ObjCXXHeader: - case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXX_Alias: - case types::TY_PP_ObjCXXHeader: - return "cc1objplus"; - } -} - -void darwin::CC1::anchor() {} - -const char *darwin::CC1::getBaseInputName(const ArgList &Args, - const InputInfoList &Inputs) { +const char *Clang::getBaseInputName(const ArgList &Args, + const InputInfoList &Inputs) { return Args.MakeArgString( llvm::sys::path::filename(Inputs[0].getBaseInput())); } -const char *darwin::CC1::getBaseInputStem(const ArgList &Args, - const InputInfoList &Inputs) { +const char *Clang::getBaseInputStem(const ArgList &Args, + const InputInfoList &Inputs) { const char *Str = getBaseInputName(Args, Inputs); if (const char *End = strrchr(Str, '.')) @@ -3699,9 +4134,8 @@ const char *darwin::CC1::getBaseInputStem(const ArgList &Args, return Str; } -const char * -darwin::CC1::getDependencyFileName(const ArgList &Args, - const InputInfoList &Inputs) { +const char *Clang::getDependencyFileName(const ArgList &Args, + const InputInfoList &Inputs) { // FIXME: Think about this more. std::string Res; @@ -3709,588 +4143,11 @@ darwin::CC1::getDependencyFileName(const ArgList &Args, std::string Str(OutputOpt->getValue()); Res = Str.substr(0, Str.rfind('.')); } else { - Res = darwin::CC1::getBaseInputStem(Args, Inputs); + Res = getBaseInputStem(Args, Inputs); } return Args.MakeArgString(Res + ".d"); } -void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { - for (ArgStringList::iterator it = CmdArgs.begin(), ie = CmdArgs.end(); - it != ie;) { - - StringRef Option = *it; - bool RemoveOption = false; - - // Erase both -fmodule-cache-path and its argument. - if (Option.equals("-fmodule-cache-path") && it+2 != ie) { - it = CmdArgs.erase(it, it+2); - ie = CmdArgs.end(); - continue; - } - - // Remove unsupported -f options. - if (Option.startswith("-f")) { - // Remove -f/-fno- to reduce the number of cases. - if (Option.startswith("-fno-")) - Option = Option.substr(5); - else - Option = Option.substr(2); - RemoveOption = llvm::StringSwitch<bool>(Option) - .Case("altivec", true) - .Case("modules", true) - .Case("diagnostics-show-note-include-stack", true) - .Default(false); - } - - // Handle machine specific options. - if (Option.startswith("-m")) { - RemoveOption = llvm::StringSwitch<bool>(Option) - .Case("-mthumb", true) - .Case("-mno-thumb", true) - .Case("-mno-fused-madd", true) - .Case("-mlong-branch", true) - .Case("-mlongcall", true) - .Case("-mcpu=G4", true) - .Case("-mcpu=G5", true) - .Default(false); - } - - // Handle warning options. - if (Option.startswith("-W")) { - // Remove -W/-Wno- to reduce the number of cases. - if (Option.startswith("-Wno-")) - Option = Option.substr(5); - else - Option = Option.substr(2); - - RemoveOption = llvm::StringSwitch<bool>(Option) - .Case("address-of-temporary", true) - .Case("ambiguous-member-template", true) - .Case("analyzer-incompatible-plugin", true) - .Case("array-bounds", true) - .Case("array-bounds-pointer-arithmetic", true) - .Case("bind-to-temporary-copy", true) - .Case("bitwise-op-parentheses", true) - .Case("bool-conversions", true) - .Case("builtin-macro-redefined", true) - .Case("c++-hex-floats", true) - .Case("c++0x-compat", true) - .Case("c++0x-extensions", true) - .Case("c++0x-narrowing", true) - .Case("c++11-compat", true) - .Case("c++11-extensions", true) - .Case("c++11-narrowing", true) - .Case("conditional-uninitialized", true) - .Case("constant-conversion", true) - .Case("conversion-null", true) - .Case("CFString-literal", true) - .Case("constant-logical-operand", true) - .Case("custom-atomic-properties", true) - .Case("default-arg-special-member", true) - .Case("delegating-ctor-cycles", true) - .Case("delete-non-virtual-dtor", true) - .Case("deprecated-implementations", true) - .Case("deprecated-writable-strings", true) - .Case("distributed-object-modifiers", true) - .Case("duplicate-method-arg", true) - .Case("dynamic-class-memaccess", true) - .Case("enum-compare", true) - .Case("enum-conversion", true) - .Case("exit-time-destructors", true) - .Case("gnu", true) - .Case("gnu-designator", true) - .Case("header-hygiene", true) - .Case("idiomatic-parentheses", true) - .Case("ignored-qualifiers", true) - .Case("implicit-atomic-properties", true) - .Case("incompatible-pointer-types", true) - .Case("incomplete-implementation", true) - .Case("int-conversion", true) - .Case("initializer-overrides", true) - .Case("invalid-noreturn", true) - .Case("invalid-token-paste", true) - .Case("language-extension-token", true) - .Case("literal-conversion", true) - .Case("literal-range", true) - .Case("local-type-template-args", true) - .Case("logical-op-parentheses", true) - .Case("method-signatures", true) - .Case("microsoft", true) - .Case("mismatched-tags", true) - .Case("missing-method-return-type", true) - .Case("non-pod-varargs", true) - .Case("nonfragile-abi2", true) - .Case("null-arithmetic", true) - .Case("null-dereference", true) - .Case("out-of-line-declaration", true) - .Case("overriding-method-mismatch", true) - .Case("readonly-setter-attrs", true) - .Case("return-stack-address", true) - .Case("self-assign", true) - .Case("semicolon-before-method-body", true) - .Case("sentinel", true) - .Case("shift-overflow", true) - .Case("shift-sign-overflow", true) - .Case("sign-conversion", true) - .Case("sizeof-array-argument", true) - .Case("sizeof-pointer-memaccess", true) - .Case("string-compare", true) - .Case("super-class-method-mismatch", true) - .Case("tautological-compare", true) - .Case("typedef-redefinition", true) - .Case("typename-missing", true) - .Case("undefined-reinterpret-cast", true) - .Case("unknown-warning-option", true) - .Case("unnamed-type-template-args", true) - .Case("unneeded-internal-declaration", true) - .Case("unneeded-member-function", true) - .Case("unused-comparison", true) - .Case("unused-exception-parameter", true) - .Case("unused-member-function", true) - .Case("unused-result", true) - .Case("vector-conversions", true) - .Case("vla", true) - .Case("used-but-marked-unused", true) - .Case("weak-vtables", true) - .Default(false); - } // if (Option.startswith("-W")) - if (RemoveOption) { - it = CmdArgs.erase(it); - ie = CmdArgs.end(); - } else { - ++it; - } - } -} - -void darwin::CC1::AddCC1Args(const ArgList &Args, - ArgStringList &CmdArgs) const { - const Driver &D = getToolChain().getDriver(); - - CheckCodeGenerationOptions(D, Args); - - // Derived from cc1 spec. - if ((!Args.hasArg(options::OPT_mkernel) || - (getDarwinToolChain().isTargetIPhoneOS() && - !getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) && - !Args.hasArg(options::OPT_static) && - !Args.hasArg(options::OPT_mdynamic_no_pic)) - CmdArgs.push_back("-fPIC"); - - if (getToolChain().getTriple().getArch() == llvm::Triple::arm || - getToolChain().getTriple().getArch() == llvm::Triple::thumb) { - if (!Args.hasArg(options::OPT_fbuiltin_strcat)) - CmdArgs.push_back("-fno-builtin-strcat"); - if (!Args.hasArg(options::OPT_fbuiltin_strcpy)) - CmdArgs.push_back("-fno-builtin-strcpy"); - } - - if (Args.hasArg(options::OPT_g_Flag) && - !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols)) - CmdArgs.push_back("-feliminate-unused-debug-symbols"); -} - -void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, - const InputInfoList &Inputs, - const ArgStringList &OutputArgs) const { - const Driver &D = getToolChain().getDriver(); - - // Derived from cc1_options spec. - if (Args.hasArg(options::OPT_fast) || - Args.hasArg(options::OPT_fastf) || - Args.hasArg(options::OPT_fastcp)) - CmdArgs.push_back("-O3"); - - if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (Args.hasArg(options::OPT_fomit_frame_pointer)) - D.Diag(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << "-fomit-frame-pointer"; - - AddCC1Args(Args, CmdArgs); - - if (!Args.hasArg(options::OPT_Q)) - CmdArgs.push_back("-quiet"); - - CmdArgs.push_back("-dumpbase"); - CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs)); - - Args.AddAllArgs(CmdArgs, options::OPT_d_Group); - - Args.AddAllArgs(CmdArgs, options::OPT_m_Group); - Args.AddAllArgs(CmdArgs, options::OPT_a_Group); - - // FIXME: The goal is to use the user provided -o if that is our - // final output, otherwise to drive from the original input - // name. Find a clean way to go about this. - if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) && - Args.hasArg(options::OPT_o)) { - Arg *OutputOpt = Args.getLastArg(options::OPT_o); - CmdArgs.push_back("-auxbase-strip"); - CmdArgs.push_back(OutputOpt->getValue()); - } else { - CmdArgs.push_back("-auxbase"); - CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs)); - } - - Args.AddAllArgs(CmdArgs, options::OPT_g_Group); - - Args.AddAllArgs(CmdArgs, options::OPT_O); - // FIXME: -Wall is getting some special treatment. Investigate. - Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group); - Args.AddLastArg(CmdArgs, options::OPT_w); - Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi, - options::OPT_trigraphs); - if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { - // Honor -std-default. - Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, - "-std=", /*Joined=*/true); - } - - if (Args.hasArg(options::OPT_v)) - CmdArgs.push_back("-version"); - if (Args.hasArg(options::OPT_pg) && - getToolChain().SupportsProfiling()) - CmdArgs.push_back("-p"); - Args.AddLastArg(CmdArgs, options::OPT_p); - - // The driver treats -fsyntax-only specially. - if (getToolChain().getTriple().getArch() == llvm::Triple::arm || - getToolChain().getTriple().getArch() == llvm::Triple::thumb) { - // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are - // used to inhibit the default -fno-builtin-str{cat,cpy}. - // - // FIXME: Should we grow a better way to deal with "removing" args? - for (arg_iterator it = Args.filtered_begin(options::OPT_f_Group, - options::OPT_fsyntax_only), - ie = Args.filtered_end(); it != ie; ++it) { - if (!(*it)->getOption().matches(options::OPT_fbuiltin_strcat) && - !(*it)->getOption().matches(options::OPT_fbuiltin_strcpy)) { - (*it)->claim(); - (*it)->render(Args, CmdArgs); - } - } - } else - Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); - - // Claim Clang only -f options, they aren't worth warning about. - Args.ClaimAllArgs(options::OPT_f_clang_Group); - - Args.AddAllArgs(CmdArgs, options::OPT_undef); - if (Args.hasArg(options::OPT_Qn)) - CmdArgs.push_back("-fno-ident"); - - // FIXME: This isn't correct. - //Args.AddLastArg(CmdArgs, options::OPT__help) - //Args.AddLastArg(CmdArgs, options::OPT__targetHelp) - - CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); - - // FIXME: Still don't get what is happening here. Investigate. - Args.AddAllArgs(CmdArgs, options::OPT__param); - - if (Args.hasArg(options::OPT_fmudflap) || - Args.hasArg(options::OPT_fmudflapth)) { - CmdArgs.push_back("-fno-builtin"); - CmdArgs.push_back("-fno-merge-constants"); - } - - if (Args.hasArg(options::OPT_coverage)) { - CmdArgs.push_back("-fprofile-arcs"); - CmdArgs.push_back("-ftest-coverage"); - } - - if (types::isCXX(Inputs[0].getType())) - CmdArgs.push_back("-D__private_extern__=extern"); -} - -void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, - const InputInfoList &Inputs, - const ArgStringList &OutputArgs) const { - // Derived from cpp_options - AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs); - - CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); - - AddCC1Args(Args, CmdArgs); - - // NOTE: The code below has some commonality with cpp_options, but - // in classic gcc style ends up sending things in different - // orders. This may be a good merge candidate once we drop pedantic - // compatibility. - - Args.AddAllArgs(CmdArgs, options::OPT_m_Group); - Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi, - options::OPT_trigraphs); - if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { - // Honor -std-default. - Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, - "-std=", /*Joined=*/true); - } - Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group); - Args.AddLastArg(CmdArgs, options::OPT_w); - - // The driver treats -fsyntax-only specially. - Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); - - // Claim Clang only -f options, they aren't worth warning about. - Args.ClaimAllArgs(options::OPT_f_clang_Group); - - if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) && - !Args.hasArg(options::OPT_fno_working_directory)) - CmdArgs.push_back("-fworking-directory"); - - Args.AddAllArgs(CmdArgs, options::OPT_O); - Args.AddAllArgs(CmdArgs, options::OPT_undef); - if (Args.hasArg(options::OPT_save_temps)) - CmdArgs.push_back("-fpch-preprocess"); -} - -void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args, - ArgStringList &CmdArgs, - const InputInfoList &Inputs) const { - const Driver &D = getToolChain().getDriver(); - - CheckPreprocessingOptions(D, Args); - - // Derived from cpp_unique_options. - // -{C,CC} only with -E is checked in CheckPreprocessingOptions(). - Args.AddLastArg(CmdArgs, options::OPT_C); - Args.AddLastArg(CmdArgs, options::OPT_CC); - if (!Args.hasArg(options::OPT_Q)) - CmdArgs.push_back("-quiet"); - Args.AddAllArgs(CmdArgs, options::OPT_nostdinc); - Args.AddAllArgs(CmdArgs, options::OPT_nostdincxx); - Args.AddLastArg(CmdArgs, options::OPT_v); - Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F); - Args.AddLastArg(CmdArgs, options::OPT_P); - - // FIXME: Handle %I properly. - if (getToolChain().getArch() == llvm::Triple::x86_64) { - CmdArgs.push_back("-imultilib"); - CmdArgs.push_back("x86_64"); - } - - if (Args.hasArg(options::OPT_MD)) { - CmdArgs.push_back("-MD"); - CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs)); - } - - if (Args.hasArg(options::OPT_MMD)) { - CmdArgs.push_back("-MMD"); - CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs)); - } - - Args.AddLastArg(CmdArgs, options::OPT_M); - Args.AddLastArg(CmdArgs, options::OPT_MM); - Args.AddAllArgs(CmdArgs, options::OPT_MF); - Args.AddLastArg(CmdArgs, options::OPT_MG); - Args.AddLastArg(CmdArgs, options::OPT_MP); - Args.AddAllArgs(CmdArgs, options::OPT_MQ); - Args.AddAllArgs(CmdArgs, options::OPT_MT); - if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) && - (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) { - if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { - CmdArgs.push_back("-MQ"); - CmdArgs.push_back(OutputOpt->getValue()); - } - } - - Args.AddLastArg(CmdArgs, options::OPT_remap); - if (Args.hasArg(options::OPT_g3)) - CmdArgs.push_back("-dD"); - Args.AddLastArg(CmdArgs, options::OPT_H); - - AddCPPArgs(Args, CmdArgs); - - Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A); - Args.AddAllArgs(CmdArgs, options::OPT_i_Group); - - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - CmdArgs.push_back(II.getFilename()); - } - - Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA, - options::OPT_Xpreprocessor); - - if (Args.hasArg(options::OPT_fmudflap)) { - CmdArgs.push_back("-D_MUDFLAP"); - CmdArgs.push_back("-include"); - CmdArgs.push_back("mf-runtime.h"); - } - - if (Args.hasArg(options::OPT_fmudflapth)) { - CmdArgs.push_back("-D_MUDFLAP"); - CmdArgs.push_back("-D_MUDFLAPTH"); - CmdArgs.push_back("-include"); - CmdArgs.push_back("mf-runtime.h"); - } -} - -void darwin::CC1::AddCPPArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - // Derived from cpp spec. - - if (Args.hasArg(options::OPT_static)) { - // The gcc spec is broken here, it refers to dynamic but - // that has been translated. Start by being bug compatible. - - // if (!Args.hasArg(arglist.parser.dynamicOption)) - CmdArgs.push_back("-D__STATIC__"); - } else - CmdArgs.push_back("-D__DYNAMIC__"); - - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-D_REENTRANT"); -} - -void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { - ArgStringList CmdArgs; - - assert(Inputs.size() == 1 && "Unexpected number of inputs!"); - - CmdArgs.push_back("-E"); - - if (Args.hasArg(options::OPT_traditional) || - Args.hasArg(options::OPT_traditional_cpp)) - CmdArgs.push_back("-traditional-cpp"); - - ArgStringList OutputArgs; - assert(Output.isFilename() && "Unexpected CC1 output."); - OutputArgs.push_back("-o"); - OutputArgs.push_back(Output.getFilename()); - - if (Args.hasArg(options::OPT_E) || getToolChain().getDriver().CCCIsCPP) { - AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs); - } else { - AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); - CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); - } - - Args.AddAllArgs(CmdArgs, options::OPT_d_Group); - - RemoveCC1UnsupportedArgs(CmdArgs); - - const char *CC1Name = getCC1Name(Inputs[0].getType()); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); -} - -void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { - const Driver &D = getToolChain().getDriver(); - ArgStringList CmdArgs; - - assert(Inputs.size() == 1 && "Unexpected number of inputs!"); - - // Silence warning about unused --serialize-diagnostics - Args.ClaimAllArgs(options::OPT__serialize_diags); - - types::ID InputType = Inputs[0].getType(); - if (const Arg *A = Args.getLastArg(options::OPT_traditional)) - D.Diag(diag::err_drv_argument_only_allowed_with) - << A->getAsString(Args) << "-E"; - - if (JA.getType() == types::TY_LLVM_IR || - JA.getType() == types::TY_LTO_IR) - CmdArgs.push_back("-emit-llvm"); - else if (JA.getType() == types::TY_LLVM_BC || - JA.getType() == types::TY_LTO_BC) - CmdArgs.push_back("-emit-llvm-bc"); - else if (Output.getType() == types::TY_AST) - D.Diag(diag::err_drv_no_ast_support) - << getToolChain().getTripleString(); - else if (JA.getType() != types::TY_PP_Asm && - JA.getType() != types::TY_PCH) - D.Diag(diag::err_drv_invalid_gcc_output_type) - << getTypeName(JA.getType()); - - ArgStringList OutputArgs; - if (Output.getType() != types::TY_PCH) { - OutputArgs.push_back("-o"); - if (Output.isNothing()) - OutputArgs.push_back("/dev/null"); - else - OutputArgs.push_back(Output.getFilename()); - } - - // There is no need for this level of compatibility, but it makes - // diffing easier. - bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) || - Args.hasArg(options::OPT_S)); - - if (types::getPreprocessedType(InputType) != types::TY_INVALID) { - AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs); - if (OutputArgsEarly) { - AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs); - } else { - AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); - CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); - } - } else { - CmdArgs.push_back("-fpreprocessed"); - - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Reject AST inputs. - if (II.getType() == types::TY_AST) { - D.Diag(diag::err_drv_no_ast_support) - << getToolChain().getTripleString(); - return; - } - - CmdArgs.push_back(II.getFilename()); - } - - if (OutputArgsEarly) { - AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs); - } else { - AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); - CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); - } - } - - if (Output.getType() == types::TY_PCH) { - assert(Output.isFilename() && "Invalid PCH output."); - - CmdArgs.push_back("-o"); - // NOTE: gcc uses a temp .s file for this, but there doesn't seem - // to be a good reason. - const char *TmpPath = C.getArgs().MakeArgString( - D.GetTemporaryPath("cc", "s")); - C.addTempFile(TmpPath); - CmdArgs.push_back(TmpPath); - - // If we're emitting a pch file with the last 4 characters of ".pth" - // and falling back to llvm-gcc we want to use ".gch" instead. - std::string OutputFile(Output.getFilename()); - size_t loc = OutputFile.rfind(".pth"); - if (loc != std::string::npos) - OutputFile.replace(loc, 4, ".gch"); - const char *Tmp = C.getArgs().MakeArgString("--output-pch="+OutputFile); - CmdArgs.push_back(Tmp); - } - - RemoveCC1UnsupportedArgs(CmdArgs); - - const char *CC1Name = getCC1Name(Inputs[0].getType()); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); -} - void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4624,6 +4481,9 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX)) CmdArgs.push_back("-ObjC"); + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export_dynamic"); + CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); @@ -4721,11 +4581,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); SanitizerArgs Sanitize(getToolChain().getDriver(), Args); - // If we're building a dynamic lib with -fsanitize=address, or - // -fsanitize=undefined, unresolved symbols may appear. Mark all + // If we're building a dynamic lib with -fsanitize=address, + // unresolved symbols may appear. Mark all // of them as dynamic_lookup. Linking executables is handled in // lib/Driver/ToolChains.cpp. - if (Sanitize.needsAsanRt() || Sanitize.needsUbsanRt()) { + if (Sanitize.needsAsanRt()) { if (Args.hasArg(options::OPT_dynamiclib) || Args.hasArg(options::OPT_bundle)) { CmdArgs.push_back("-undefined"); @@ -4839,10 +4699,10 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("--verify"); CmdArgs.push_back("--debug-info"); @@ -5136,6 +4996,14 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + if ((!Args.hasArg(options::OPT_nostdlib)) && (!Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-e"); @@ -5190,6 +5058,10 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_s); + Args.AddAllArgs(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); + Args.AddAllArgs(CmdArgs, options::OPT_r); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -5406,14 +5278,8 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); - // Convert ABI name to the GNU tools acceptable variant. - if (ABIName == "o32") - ABIName = "32"; - else if (ABIName == "n64") - ABIName = "64"; - CmdArgs.push_back("-mabi"); - CmdArgs.push_back(ABIName.data()); + CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) @@ -5788,11 +5654,11 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } -void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { +void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { ArgStringList CmdArgs; // Add --32/--64 to make sure we get the format we want. @@ -5832,14 +5698,8 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); - // Convert ABI name to the GNU tools acceptable variant. - if (ABIName == "o32") - ABIName = "32"; - else if (ABIName == "n64") - ABIName = "64"; - CmdArgs.push_back("-mabi"); - CmdArgs.push_back(ABIName.data()); + CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) @@ -5880,12 +5740,12 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, static void AddLibgcc(llvm::Triple Triple, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android; - bool StaticLibgcc = isAndroid || Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_static_libgcc); + bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || + Args.hasArg(options::OPT_static); if (!D.CCCIsCXX) CmdArgs.push_back("-lgcc"); - if (StaticLibgcc) { + if (StaticLibgcc || isAndroid) { if (D.CCCIsCXX) CmdArgs.push_back("-lgcc"); } else { @@ -5900,6 +5760,14 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D, CmdArgs.push_back("-lgcc_eh"); else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) CmdArgs.push_back("-lgcc"); + + // According to Android ABI, we have to link with libdl if we are + // linking with non-static libgcc. + // + // NOTE: This fixes a link error on Android MIPS as well. The non-static + // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl. + if (isAndroid && !StaticLibgcc) + CmdArgs.push_back("-ldl"); } static bool hasMipsN32ABIArg(const ArgList &Args) { @@ -5907,11 +5775,11 @@ static bool hasMipsN32ABIArg(const ArgList &Args) { return A && (A->getValue() == StringRef("n32")); } -void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { +void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { const toolchains::Linux& ToolChain = static_cast<const toolchains::Linux&>(getToolChain()); const Driver &D = ToolChain.getDriver(); @@ -5931,7 +5799,7 @@ void linuxtools::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 (Args.hasArg(options::OPT_pie) && !Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_rdynamic)) @@ -5952,6 +5820,8 @@ void linuxtools::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) + CmdArgs.push_back("aarch64linux"); else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); @@ -6000,6 +5870,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("/system/bin/linker"); else if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("/lib/ld-linux.so.2"); + else if (ToolChain.getArch() == llvm::Triple::aarch64) + CmdArgs.push_back("/lib/ld-linux-aarch64.so.1"); else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) @@ -6102,9 +5974,17 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, SanitizerArgs Sanitize(D, Args); - // Call this before we add the C++ ABI library. + // Call these before we add the C++ ABI library. if (Sanitize.needsUbsanRt()) - addUbsanRTLinux(getToolChain(), Args, CmdArgs); + addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX, + Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || + Sanitize.needsMsanRt()); + if (Sanitize.needsAsanRt()) + addAsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsTsanRt()) + addTsanRTLinux(getToolChain(), Args, CmdArgs); + if (Sanitize.needsMsanRt()) + addMsanRTLinux(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib) && @@ -6119,21 +5999,24 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lm"); } - // Call this before we add the C run-time. - if (Sanitize.needsAsanRt()) - addAsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsTsanRt()) - addTsanRTLinux(getToolChain(), Args, CmdArgs); - if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); + bool OpenMP = Args.hasArg(options::OPT_fopenmp); + if (OpenMP) { + CmdArgs.push_back("-lgomp"); + + // FIXME: Exclude this for platforms whith libgomp that doesn't require + // librt. Most modern Linux platfroms require it, but some may not. + CmdArgs.push_back("-lrt"); + } + AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads)) + Args.hasArg(options::OPT_pthreads) || OpenMP) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); @@ -6235,7 +6118,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lCompilerRT-Generic"); CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib"); CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); + Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); |