diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Tools.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 1594 |
1 files changed, 1242 insertions, 352 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index d9423d2..d3dab19 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -16,7 +16,6 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Job.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" @@ -36,13 +35,6 @@ #include "InputInfo.h" #include "ToolChains.h" -#ifdef __CYGWIN__ -#include <cygwin/version.h> -#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 -#define IS_CYGWIN15 1 -#endif -#endif - using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; @@ -96,6 +88,39 @@ static void QuoteTarget(StringRef Target, } } +static void addDirectoryList(const ArgList &Args, + ArgStringList &CmdArgs, + const char *ArgName, + const char *EnvVar) { + const char *DirList = ::getenv(EnvVar); + if (!DirList) + return; // Nothing to do. + + StringRef Dirs(DirList); + if (Dirs.empty()) // Empty string should not add '.'. + return; + + StringRef::size_type Delim; + while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { + if (Delim == 0) { // Leading colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); + } + Dirs = Dirs.substr(Delim + 1); + } + + if (Dirs.empty()) { // Trailing colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { // Add the last path. + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs)); + } +} + static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs) { @@ -136,6 +161,9 @@ static void AddLinkerInputs(const ToolChain &TC, } else A.renderAsInput(Args, CmdArgs); } + + // LIBRARY_PATH - included following the user specified library paths. + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); } /// \brief Determine whether Objective-C automated reference counting is @@ -144,6 +172,13 @@ static bool isObjCAutoRefCount(const ArgList &Args) { return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); } +/// \brief Determine whether we are linking the ObjC runtime. +static bool isObjCRuntimeLinked(const ArgList &Args) { + if (isObjCAutoRefCount(Args)) + return true; + return Args.hasArg(options::OPT_fobjc_link_runtime); +} + static void addProfileRT(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, llvm::Triple Triple) { @@ -157,53 +192,14 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, // 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. - Twine ProfileRT = - Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.a"; - - if (Triple.isOSDarwin()) { - // On Darwin, if the static library doesn't exist try the dylib. - bool Exists; - if (llvm::sys::fs::exists(ProfileRT.str(), Exists) || !Exists) - ProfileRT = - Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.dylib"; - } + std::string ProfileRT = + std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a"; CmdArgs.push_back(Args.MakeArgString(ProfileRT)); } -static void AddIncludeDirectoryList(const ArgList &Args, - ArgStringList &CmdArgs, - const char *ArgName, - const char *DirList) { - if (!DirList) - return; // Nothing to do. - - StringRef Dirs(DirList); - if (Dirs.empty()) // Empty string should not add '.'. - return; - - StringRef::size_type Delim; - while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { - if (Delim == 0) { // Leading colon. - CmdArgs.push_back(ArgName); - CmdArgs.push_back("."); - } else { - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); - } - Dirs = Dirs.substr(Delim + 1); - } - - if (Dirs.empty()) { // Trailing colon. - CmdArgs.push_back(ArgName); - CmdArgs.push_back("."); - } else { // Add the last path. - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs)); - } -} - -void Clang::AddPreprocessingOptions(const Driver &D, +void Clang::AddPreprocessingOptions(Compilation &C, + const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, @@ -225,11 +221,13 @@ void Clang::AddPreprocessingOptions(const Driver &D, DepFile = Output.getFilename(); } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(Args); + C.addFailureResultFile(DepFile); } 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); } CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); @@ -247,13 +245,13 @@ void Clang::AddPreprocessingOptions(const Driver &D, // Otherwise derive from the base input. // // FIXME: This should use the computed output file location. - llvm::SmallString<128> P(Inputs[0].getBaseInput()); + SmallString<128> P(Inputs[0].getBaseInput()); llvm::sys::path::replace_extension(P, "o"); DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } CmdArgs.push_back("-MT"); - llvm::SmallString<128> Quoted; + SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); } @@ -281,7 +279,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, if (A->getOption().matches(options::OPT_MQ)) { CmdArgs.push_back("-MT"); - llvm::SmallString<128> Quoted; + SmallString<128> Quoted; QuoteTarget(A->getValue(Args), Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); @@ -392,7 +390,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, A->claim(); A->render(Args, CmdArgs); } else { - llvm::SmallString<128> DefaultModuleCache; + SmallString<128> DefaultModuleCache; llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, DefaultModuleCache); llvm::sys::path::append(DefaultModuleCache, "clang-module-cache"); @@ -400,24 +398,20 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); } - Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import); - // Parse additional include paths from environment variables. + // FIXME: We should probably sink the logic for handling these from the + // frontend into the driver. It will allow deleting 4 otherwise unused flags. // CPATH - included following the user specified includes (but prior to // builtin and standard includes). - AddIncludeDirectoryList(Args, CmdArgs, "-I", ::getenv("CPATH")); + addDirectoryList(Args, CmdArgs, "-I", "CPATH"); // C_INCLUDE_PATH - system includes enabled when compiling C. - AddIncludeDirectoryList(Args, CmdArgs, "-c-isystem", - ::getenv("C_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH"); // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++. - AddIncludeDirectoryList(Args, CmdArgs, "-cxx-isystem", - ::getenv("CPLUS_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH"); // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC. - AddIncludeDirectoryList(Args, CmdArgs, "-objc-isystem", - ::getenv("OBJC_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH"); // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++. - AddIncludeDirectoryList(Args, CmdArgs, "-objcxx-isystem", - ::getenv("OBJCPLUS_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH"); // Add C++ include arguments, if needed. if (types::isCXX(Inputs[0].getType())) @@ -489,6 +483,9 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) { .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") .Cases("cortex-a8", "cortex-a9", "v7") + .Case("cortex-m3", "v7m") + .Case("cortex-m4", "v7m") + .Case("cortex-m0", "v6m") .Default(""); } @@ -504,46 +501,78 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { if (Triple.isOSDarwin()) return true; return false; - - case llvm::Triple::systemz: - return false; } } -void Clang::AddARMTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs, - bool KernelOrKext) const { - const Driver &D = getToolChain().getDriver(); - llvm::Triple Triple = getToolChain().getTriple(); +// Handle -mfpu=. +// +// FIXME: Centralize feature selection, defaulting shouldn't be also in the +// frontend target. +static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args, + ArgStringList &CmdArgs) { + StringRef FPU = A->getValue(Args); + + // Set the target features based on the FPU. + if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { + // Disable any default FPU support. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+d16"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3" || FPU == "vfpv3") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neon"); + } else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} - // Select the ABI to use. - // - // FIXME: Support -meabi. - const char *ABIName = 0; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { - ABIName = A->getValue(Args); - } else { - // Select the default based on the platform. - switch(Triple.getEnvironment()) { - case llvm::Triple::GNUEABI: - ABIName = "aapcs-linux"; - break; - case llvm::Triple::EABI: - ABIName = "aapcs"; - break; - default: - ABIName = "apcs-gnu"; - } - } - CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); +// Handle -mfpmath=. +static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args, + ArgStringList &CmdArgs, StringRef CPU) { + StringRef FPMath = A->getValue(Args); + + // Set the target features based on the FPMath. + if (FPMath == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neonfp"); + + if (CPU != "cortex-a8" && CPU != "cortex-a9" && CPU != "cortex-a9-mp") + D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU; + + } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" || + FPMath == "vfp4") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neonfp"); - // Set the CPU based on -march= and -mcpu=. - CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + // FIXME: Add warnings when disabling a feature not present for a given CPU. + } else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} - // Select the float ABI as determined by -msoft-float, -mhard-float, and - // -mfloat-abi=. +// Select the float ABI as determined by -msoft-float, -mhard-float, and +// -mfloat-abi=. +static StringRef getARMFloatABI(const Driver &D, + const ArgList &Args, + const llvm::Triple &Triple) { StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -564,7 +593,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { - const llvm::Triple &Triple = getToolChain().getTriple(); switch (Triple.getOS()) { case llvm::Triple::Darwin: case llvm::Triple::MacOSX: @@ -582,7 +610,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } case llvm::Triple::Linux: { - if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUEABI) { + if (Triple.getEnvironment() == llvm::Triple::GNUEABI) { FloatABI = "softfp"; break; } @@ -598,6 +626,15 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // EABI is always AAPCS, and if it was not marked 'hard', it's softfp FloatABI = "softfp"; break; + case llvm::Triple::ANDROIDEABI: { + StringRef ArchName = + getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + if (ArchName.startswith("v7")) + FloatABI = "softfp"; + else + FloatABI = "soft"; + break; + } default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; @@ -607,6 +644,45 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } } + return FloatABI; +} + + +void Clang::AddARMTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs, + bool KernelOrKext) const { + const Driver &D = getToolChain().getDriver(); + llvm::Triple Triple = getToolChain().getTriple(); + + // Select the ABI to use. + // + // FIXME: Support -meabi. + const char *ABIName = 0; + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + ABIName = A->getValue(Args); + } else { + // Select the default based on the platform. + switch(Triple.getEnvironment()) { + case llvm::Triple::ANDROIDEABI: + case llvm::Triple::GNUEABI: + ABIName = "aapcs-linux"; + break; + case llvm::Triple::EABI: + ABIName = "aapcs"; + break; + default: + ABIName = "apcs-gnu"; + } + } + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName); + + // Set the CPU based on -march= and -mcpu=. + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + + // Determine floating point ABI from the options & target defaults. + StringRef FloatABI = getARMFloatABI(D, Args, Triple); if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // @@ -644,33 +720,12 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } // Honor -mfpu=. - // - // FIXME: Centralize feature selection, defaulting shouldn't be also in the - // frontend target. - if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { - StringRef FPU = A->getValue(Args); - - // Set the target features based on the FPU. - if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { - // Disable any default FPU support. - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-vfp2"); - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-vfp3"); - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-neon"); - } else if (FPU == "vfp") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vfp2"); - } else if (FPU == "vfp3") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vfp3"); - } else if (FPU == "neon") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+neon"); - } else - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); - } + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + addFPUArgs(D, A, Args, CmdArgs); + + // Honor -mfpmath=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) + addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. @@ -703,25 +758,32 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Get default architecture. static const char* getMipsArchFromCPU(StringRef CPUName) { - if (CPUName == "mips32r1" || CPUName == "4ke") + if (CPUName == "mips32" || CPUName == "mips32r2") return "mips"; - assert((CPUName == "mips64r1" || CPUName == "mips64r2") && + assert((CPUName == "mips64" || CPUName == "mips64r2") && "Unexpected cpu name."); return "mips64"; } +// Check that ArchName is a known Mips architecture name. +static bool checkMipsArchName(StringRef ArchName) { + return ArchName == "mips" || + ArchName == "mipsel" || + ArchName == "mips64" || + ArchName == "mips64el"; +} + // Get default target cpu. -static const char* getMipsCPUFromArch(StringRef ArchName, const Driver &D) { +static const char* getMipsCPUFromArch(StringRef ArchName) { if (ArchName == "mips" || ArchName == "mipsel") - return "mips32r1"; - else if (ArchName == "mips64" || ArchName == "mips64el") - return "mips64r1"; - else - D.Diag(diag::err_drv_invalid_arch_name) << ArchName; + return "mips32"; + + assert((ArchName == "mips64" || ArchName == "mips64el") && + "Unexpected arch name."); - return 0; + return "mips64"; } // Get default ABI. @@ -734,61 +796,98 @@ static const char* getMipsABIFromArch(StringRef ArchName) { return "n64"; } -void Clang::AddMIPSTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - const Driver &D = getToolChain().getDriver(); - +// Get CPU and ABI names. They are not independent +// so we have to calculate them together. +static void getMipsCPUAndABI(const ArgList &Args, + const ToolChain &TC, + StringRef &CPUName, + StringRef &ABIName) { StringRef ArchName; - const char *CPUName; - // Set target cpu and architecture. + // Select target cpu and architecture. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { CPUName = A->getValue(Args); ArchName = getMipsArchFromCPU(CPUName); } else { - ArchName = Args.MakeArgString(getToolChain().getArchName()); - CPUName = getMipsCPUFromArch(ArchName, D); + ArchName = Args.MakeArgString(TC.getArchName()); + if (!checkMipsArchName(ArchName)) + TC.getDriver().Diag(diag::err_drv_invalid_arch_name) << ArchName; + else + CPUName = getMipsCPUFromArch(ArchName); } - - CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(CPUName); // Select the ABI to use. - const char *ABIName = 0; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(Args); else ABIName = getMipsABIFromArch(ArchName); +} + +void Clang::AddMIPSTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); + CmdArgs.push_back(ABIName.data()); - // Select the float ABI as determined by -msoft-float, -mhard-float, and + // Select the float ABI as determined by -msoft-float, -mhard-float, + // and -mfloat-abi=. StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, - options::OPT_mhard_float)) { + options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; + else { + FloatABI = A->getValue(Args); + if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") { + D.Diag(diag::err_drv_invalid_mfloat_abi) + << A->getAsString(Args); + FloatABI = "hard"; + } + } } // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { - // Assume "soft", but warn the user we are guessing. - FloatABI = "soft"; - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + // Assume "hard", because it's a default value used by gcc. + // When we start to recognize specific target MIPS processors, + // we will be able to select the default more correctly. + FloatABI = "hard"; } if (FloatABI == "soft") { // Floating point operations and argument passing are soft. - // - // FIXME: This changes CPP defines, we need -target-soft-float. CmdArgs.push_back("-msoft-float"); - } else { + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("soft"); + + // FIXME: Note, this is a hack. We need to pass the selected float + // mode to the MipsTargetInfoBase to define appropriate macros there. + // Now it is the only method. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+soft-float"); + } + else if (FloatABI == "single") { + // Restrict the use of hardware floating-point + // instructions to 32-bit operations. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+single-float"); + } + else { + // Floating point operations and argument passing are hard. assert(FloatABI == "hard" && "Invalid float abi!"); - CmdArgs.push_back("-mhard-float"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("hard"); } } @@ -797,9 +896,8 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, const Driver &D = getToolChain().getDriver(); if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - StringRef MArch = A->getValue(Args); CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(MArch.str().c_str()); + CmdArgs.push_back(A->getValue(Args)); } // Select the float ABI as determined by -msoft-float, -mhard-float, and @@ -941,6 +1039,70 @@ 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(Args,0); + if (Value.startswith("v")) { + A = *it; + A->claim(); + } + } + } + return A; +} + +static StringRef getHexagonTargetCPU(const ArgList &Args) +{ + Arg *A; + llvm::StringRef WhichHexagon; + + // Select the default CPU (v4) if none was given or detection failed. + if ((A = getLastHexagonArchArg (Args))) { + WhichHexagon = A->getValue(Args); + if (WhichHexagon == "") + return "v4"; + else + return WhichHexagon; + } + else + return "v4"; +} + +void Clang::AddHexagonTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + llvm::Triple Triple = getToolChain().getTriple(); + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(Args.MakeArgString("hexagon" + getHexagonTargetCPU(Args))); + CmdArgs.push_back("-fno-signed-char"); + CmdArgs.push_back("-nobuiltininc"); + + if (Args.hasArg(options::OPT_mqdsp6_compat)) + CmdArgs.push_back("-mqdsp6-compat"); + + if (Arg *A = Args.getLastArg(options::OPT_G, + options::OPT_msmall_data_threshold_EQ)) { + std::string SmallDataThreshold="-small-data-threshold="; + SmallDataThreshold += A->getValue(Args); + CmdArgs.push_back ("-mllvm"); + CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold)); + A->claim(); + } + + CmdArgs.push_back ("-mllvm"); + CmdArgs.push_back ("-machine-sink-split=0"); +} + static bool shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, const llvm::Triple &Triple) { @@ -966,11 +1128,20 @@ shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, /// Objective-C exceptions. static void addExceptionArgs(const ArgList &Args, types::ID InputType, const llvm::Triple &Triple, - bool KernelOrKext, bool IsRewriter, + bool KernelOrKext, unsigned objcABIVersion, ArgStringList &CmdArgs) { - if (KernelOrKext) + if (KernelOrKext) { + // -mkernel and -fapple-kext imply no exceptions, so claim exception related + // arguments now to avoid warnings about unused arguments. + Args.ClaimAllArgs(options::OPT_fexceptions); + Args.ClaimAllArgs(options::OPT_fno_exceptions); + Args.ClaimAllArgs(options::OPT_fobjc_exceptions); + Args.ClaimAllArgs(options::OPT_fno_objc_exceptions); + Args.ClaimAllArgs(options::OPT_fcxx_exceptions); + Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions); return; + } // Exceptions are enabled by default. bool ExceptionsEnabled = true; @@ -1033,28 +1204,29 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, 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 = Args.hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + TC.IsIntegratedAssemblerDefault()); + } + return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, + options::OPT_fno_dwarf2_cfi_asm, + Default); +} - // FIXME: Duplicated code with ToolChains.cpp - // FIXME: This doesn't belong here, but ideally we will support static soon - // anyway. - bool HasStatic = (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_fapple_kext)); - bool IsIADefault = TC.IsIntegratedAssemblerDefault() && !HasStatic; - bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - IsIADefault); - bool UseCFI = Args.hasFlag(options::OPT_fdwarf2_cfi_asm, - options::OPT_fno_dwarf2_cfi_asm, - UseIntegratedAs); - return !UseCFI; - } - - // For now we assume that every other assembler support CFI. - return false; +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); + return !UseDwarfDirectory; } /// \brief Check whether the given input tree contains any compilation actions. @@ -1092,6 +1264,46 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { RelaxDefault); } +/// 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) { + // Add asan linker flags when linking an executable, but not a shared object. + if (Args.hasArg(options::OPT_shared) || + !Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) + return; + + // 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"); +} + +static bool shouldUseFramePointer(const ArgList &Args, + const llvm::Triple &Triple) { + if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, + options::OPT_fomit_frame_pointer)) + return A->getOption().matches(options::OPT_fno_omit_frame_pointer); + + // Don't use a frame pointer on linux x86 and x86_64 if optimizing. + if ((Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::x86) && + Triple.getOS() == llvm::Triple::Linux) { + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) + if (!A->getOption().matches(options::OPT_O0)) + return false; + } + + return true; +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -1116,9 +1328,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Select the appropriate action. bool IsRewriter = false; + bool IsModernRewriter = false; + if (isa<AnalyzeJobAction>(JA)) { assert(JA.getType() == types::TY_Plist && "Invalid output type."); CmdArgs.push_back("-analyze"); + } else if (isa<MigrateJobAction>(JA)) { + CmdArgs.push_back("-migrate"); } else if (isa<PreprocessJobAction>(JA)) { if (Output.getType() == types::TY_Dependencies) CmdArgs.push_back("-Eonly"); @@ -1184,6 +1400,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-emit-pch"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); + IsModernRewriter = true; + } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { + CmdArgs.push_back("-rewrite-objc"); IsRewriter = true; } else { assert(JA.getType() == types::TY_PP_Asm && @@ -1218,17 +1437,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-analyzer-eagerly-assume"); + CmdArgs.push_back("-analyzer-ipa=inlining"); + // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); - CmdArgs.push_back("-analyzer-checker=deadcode"); - CmdArgs.push_back("-analyzer-checker=security"); if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) CmdArgs.push_back("-analyzer-checker=unix"); if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) CmdArgs.push_back("-analyzer-checker=osx"); + + CmdArgs.push_back("-analyzer-checker=deadcode"); + + // Enable the following experimental checkers for testing. + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); } // Set the output format. The default is plist, for (lame) historical @@ -1260,15 +1489,43 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // would do to enable flag_pic. // // FIXME: Centralize this code. - bool PICEnabled = (Args.hasArg(options::OPT_fPIC) || - Args.hasArg(options::OPT_fpic) || - Args.hasArg(options::OPT_fPIE) || - Args.hasArg(options::OPT_fpie)); - bool PICDisabled = (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_static)); + Arg *LastPICArg = 0; + for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { + if ((*I)->getOption().matches(options::OPT_fPIC) || + (*I)->getOption().matches(options::OPT_fno_PIC) || + (*I)->getOption().matches(options::OPT_fpic) || + (*I)->getOption().matches(options::OPT_fno_pic) || + (*I)->getOption().matches(options::OPT_fPIE) || + (*I)->getOption().matches(options::OPT_fno_PIE) || + (*I)->getOption().matches(options::OPT_fpie) || + (*I)->getOption().matches(options::OPT_fno_pie)) { + LastPICArg = *I; + (*I)->claim(); + } + } + bool PICDisabled = false; + bool PICEnabled = false; + bool PICForPIE = false; + if (LastPICArg) { + PICForPIE = (LastPICArg->getOption().matches(options::OPT_fPIE) || + LastPICArg->getOption().matches(options::OPT_fpie)); + PICEnabled = (PICForPIE || + LastPICArg->getOption().matches(options::OPT_fPIC) || + LastPICArg->getOption().matches(options::OPT_fpic)); + PICDisabled = !PICEnabled; + } + // 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. + if (Args.hasArg(options::OPT_mkernel)) + PICDisabled = true; + if (Args.hasArg(options::OPT_static)) + PICDisabled = true; + bool DynamicNoPIC = Args.hasArg(options::OPT_mdynamic_no_pic); + + // Select the relocation model. const char *Model = getToolChain().GetForcedPicModel(); if (!Model) { - if (Args.hasArg(options::OPT_mdynamic_no_pic)) + if (DynamicNoPIC) Model = "dynamic-no-pic"; else if (PICDisabled) Model = "static"; @@ -1277,19 +1534,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else Model = getToolChain().GetDefaultRelocationModel(); } - if (StringRef(Model) != "pic") { + StringRef ModelStr = Model ? Model : ""; + if (Model && ModelStr != "pic") { CmdArgs.push_back("-mrelocation-model"); CmdArgs.push_back(Model); } - // Infer the __PIC__ value. - // - // FIXME: This isn't quite right on Darwin, which always sets - // __PIC__=2. - if (strcmp(Model, "pic") == 0 || strcmp(Model, "dynamic-no-pic") == 0) { + // Infer the __PIC__ and __PIE__ values. + if (ModelStr == "pic" && PICForPIE) { + CmdArgs.push_back("-pie-level"); + CmdArgs.push_back((LastPICArg && + LastPICArg->getOption().matches(options::OPT_fPIE)) ? + "2" : "1"); + } else if (ModelStr == "pic" || ModelStr == "dynamic-no-pic") { CmdArgs.push_back("-pic-level"); - CmdArgs.push_back(Args.hasArg(options::OPT_fPIC) ? "2" : "1"); + CmdArgs.push_back(((ModelStr != "dynamic-no-pic" && LastPICArg && + LastPICArg->getOption().matches(options::OPT_fPIC)) || + getToolChain().getTriple().isOSDarwin()) ? "2" : "1"); } + if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) CmdArgs.push_back("-fno-merge-all-constants"); @@ -1304,9 +1567,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-mrtd"); - // FIXME: Set --enable-unsafe-fp-math. - if (Args.hasFlag(options::OPT_fno_omit_frame_pointer, - options::OPT_fomit_frame_pointer)) + if (shouldUseFramePointer(Args, getToolChain().getTriple())) CmdArgs.push_back("-mdisable-fp-elim"); if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) @@ -1315,6 +1576,96 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, + false)) + CmdArgs.push_back("-fstrict-enums"); + if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, + options::OPT_fno_optimize_sibling_calls)) + CmdArgs.push_back("-mdisable-tail-calls"); + + // Handle various floating point optimization flags, mapping them to the + // appropriate LLVM code generation flags. The pattern for all of these is to + // default off the codegen optimizations, and if any flag enables them and no + // flag disables them after the flag enabling them, enable the codegen + // optimization. This is complicated by several "umbrella" flags. + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_ffinite_math_only, + options::OPT_fno_finite_math_only, + options::OPT_fhonor_infinities, + options::OPT_fno_honor_infinities)) + if (A->getOption().getID() != options::OPT_fno_finite_math_only && + A->getOption().getID() != options::OPT_fhonor_infinities) + CmdArgs.push_back("-menable-no-infs"); + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_ffinite_math_only, + options::OPT_fno_finite_math_only, + options::OPT_fhonor_nans, + options::OPT_fno_honor_nans)) + if (A->getOption().getID() != options::OPT_fno_finite_math_only && + A->getOption().getID() != options::OPT_fhonor_nans) + CmdArgs.push_back("-menable-no-nans"); + + // -fno-math-errno is default. + bool MathErrno = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fmath_errno, + options::OPT_fno_math_errno)) { + if (A->getOption().getID() == options::OPT_fmath_errno) { + CmdArgs.push_back("-fmath-errno"); + MathErrno = true; + } + } + + // There are several flags which require disabling very specific + // optimizations. Any of these being disabled forces us to turn off the + // entire set of LLVM optimizations, so collect them through all the flag + // madness. + bool AssociativeMath = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_fassociative_math, + options::OPT_fno_associative_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fno_associative_math) + AssociativeMath = true; + bool ReciprocalMath = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_freciprocal_math, + options::OPT_fno_reciprocal_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fno_reciprocal_math) + ReciprocalMath = true; + bool SignedZeros = true; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_fsigned_zeros, + options::OPT_fno_signed_zeros)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fsigned_zeros) + SignedZeros = false; + bool TrappingMath = true; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_ftrapping_math, + options::OPT_fno_trapping_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_ftrapping_math) + TrappingMath = false; + if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros && + !TrappingMath) + CmdArgs.push_back("-menable-unsafe-fp-math"); + + // We separately look for the '-ffast-math' flag, and if we find it, tell the + // frontend to provide the appropriate preprocessor macros. This is distinct + // from enabling any optimizations as it induces a language change which must + // survive serialization and deserialization, etc. + if (Args.hasArg(options::OPT_ffast_math)) + CmdArgs.push_back("-ffast-math"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. @@ -1397,8 +1748,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::x86_64: AddX86TargetArgs(Args, CmdArgs); break; + + case llvm::Triple::hexagon: + AddHexagonTargetArgs(Args, CmdArgs); + break; } + + // Pass the linker version in use. if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { CmdArgs.push_back("-target-linker-version"); @@ -1411,21 +1768,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !getToolChain().getTriple().isOSDarwin())) CmdArgs.push_back("-momit-leaf-frame-pointer"); - // -fno-math-errno is default. - if (Args.hasFlag(options::OPT_fmath_errno, - options::OPT_fno_math_errno, - false)) - CmdArgs.push_back("-fmath-errno"); - // Explicitly error on some things we know we don't support and can't just // ignore. types::ID InputType = Inputs[0].getType(); if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; - if ((Unsupported = Args.getLastArg(options::OPT_iframework))) - D.Diag(diag::err_drv_clang_unsupported) - << Unsupported->getOption().getName(); - if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() && getToolChain().getTriple().getArch() == llvm::Triple::x86) { @@ -1456,8 +1803,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // wrong. Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) - if (!A->getOption().matches(options::OPT_g0)) + if (!A->getOption().matches(options::OPT_g0)) { CmdArgs.push_back("-g"); + } Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); @@ -1496,10 +1844,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_working_directory); + bool ARCMTEnabled = false; if (!Args.hasArg(options::OPT_fno_objc_arc)) { if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_modify, options::OPT_ccc_arcmt_migrate)) { + ARCMTEnabled = true; switch (A->getOption().getID()) { default: llvm_unreachable("missed a case"); @@ -1511,7 +1861,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case options::OPT_ccc_arcmt_migrate: CmdArgs.push_back("-arcmt-migrate"); - CmdArgs.push_back("-arcmt-migrate-directory"); + CmdArgs.push_back("-mt-migrate-directory"); CmdArgs.push_back(A->getValue(Args)); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); @@ -1521,12 +1871,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) { + if (ARCMTEnabled) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "-ccc-arcmt-migrate"; + } + CmdArgs.push_back("-mt-migrate-directory"); + CmdArgs.push_back(A->getValue(Args)); + + if (!Args.hasArg(options::OPT_objcmt_migrate_literals, + options::OPT_objcmt_migrate_subscripting)) { + // None specified, means enable them all. + CmdArgs.push_back("-objcmt-migrate-literals"); + CmdArgs.push_back("-objcmt-migrate-subscripting"); + } else { + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); + } + } + // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // // FIXME: Support -fpreprocessed if (types::getPreprocessedType(InputType) != types::TY_INVALID) - AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs); + AddPreprocessingOptions(C, 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". @@ -1611,11 +1980,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (ShouldDisableCFI(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf2-cfi-asm"); - if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) { + 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)); + } + } + + if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, + options::OPT_ftemplate_depth_EQ)) { CmdArgs.push_back("-ftemplate-depth"); CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { + CmdArgs.push_back("-fconstexpr-depth"); + CmdArgs.push_back(A->getValue(Args)); + } + if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ, options::OPT_Wlarge_by_value_copy_def)) { CmdArgs.push_back("-Wlarge-by-value-copy"); @@ -1654,6 +2042,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) { + CmdArgs.push_back("-fconstexpr-backtrace-limit"); + CmdArgs.push_back(A->getValue(Args)); + } + // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) { @@ -1673,9 +2066,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); // -fhosted is default. - if (KernelOrKext || Args.hasFlag(options::OPT_ffreestanding, - options::OPT_fhosted, - false)) + if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) || + KernelOrKext) CmdArgs.push_back("-ffreestanding"); // Forward -f (flag) options which we can pass directly. @@ -1684,9 +2076,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); + Args.AddLastArg(CmdArgs, options::OPT_faltivec); + + // Report and error for -faltivec on anything other then PowerPC. + if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) + if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || + getToolChain().getTriple().getArch() == llvm::Triple::ppc64)) + D.Diag(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "ppc/ppc64"; + if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); + if (Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) + CmdArgs.push_back("-faddress-sanitizer"); + + if (Args.hasFlag(options::OPT_fthread_sanitizer, + options::OPT_fno_thread_sanitizer, false)) + CmdArgs.push_back("-fthread-sanitizer"); + // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, options::OPT_fno_lax_vector_conversions)) @@ -1706,12 +2117,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - // Forward -ftrap_function= options to the backend. - if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { - StringRef FuncName = A->getValue(Args); - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back(Args.MakeArgString("-trap-func=" + FuncName)); - } + Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ); // -fno-strict-overflow implies -fwrapv if it isn't disabled, but // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. @@ -1748,10 +2154,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Translate -mstackrealign - if (Args.hasArg(options::OPT_mstackrealign)) { + if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, + false)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-force-align-stack"); } + if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign, + false)) { + CmdArgs.push_back(Args.MakeArgString("-mstackrealign")); + } + + if (Args.hasArg(options::OPT_mstack_alignment)) { + StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); + CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); + } // Forward -f options with positive and negative forms; we translate // these by hand. @@ -1761,6 +2177,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fapple-kext"); if (!Args.hasArg(options::OPT_fbuiltin)) CmdArgs.push_back("-fno-builtin"); + Args.ClaimAllArgs(options::OPT_fno_builtin); } // -fbuiltin is default. else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) @@ -1783,6 +2200,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fblocks-runtime-optional"); } + // -fmodules enables modules (off by default). However, for C++/Objective-C++, + // users must also pass -fcxx-modules. The latter flag will disappear once the + // modules implementation is solid for C++/Objective-C++ programs as well. + if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { + bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, + options::OPT_fno_cxx_modules, + false); + if (AllowedInCXX || !types::isCXX(InputType)) + CmdArgs.push_back("-fmodules"); + } + // -faccess-control is default. if (Args.hasFlag(options::OPT_fno_access_control, options::OPT_faccess_control, @@ -1796,14 +2224,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-elide-constructors"); // -frtti is default. - if (KernelOrKext || - !Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti)) + if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || + KernelOrKext) CmdArgs.push_back("-fno-rtti"); - // -fshort-enums=0 is default. - // FIXME: Are there targers where -fshort-enums is on by default ? + // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, - options::OPT_fno_short_enums, false)) + options::OPT_fno_short_enums, + getToolChain().getTriple().getArch() == + llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); // -fsigned-char is default. @@ -1817,10 +2246,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-threadsafe-statics"); // -fuse-cxa-atexit is default. - if (KernelOrKext || - !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)) + if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, + options::OPT_fno_use_cxa_atexit, + getToolChain().getTriple().getOS() != llvm::Triple::Cygwin && + getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 && + getToolChain().getTriple().getArch() != llvm::Triple::hexagon) || + KernelOrKext) CmdArgs.push_back("-fno-use-cxa-atexit"); // -fms-extensions=0 is default. @@ -1829,8 +2260,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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)) + if (Args.hasFlag(options::OPT_fms_compatibility, + options::OPT_fno_ms_compatibility, + (getToolChain().getTriple().getOS() == llvm::Triple::Win32 && + Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, + true)))) CmdArgs.push_back("-fms-compatibility"); // -fmsc-version=1300 is default. @@ -1868,11 +2303,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fgnu89-inline"); + if (Args.hasArg(options::OPT_fno_inline)) + CmdArgs.push_back("-fno-inline"); + + if (Args.hasArg(options::OPT_fno_inline_functions)) + CmdArgs.push_back("-fno-inline-functions"); + // -fobjc-nonfragile-abi=0 is default. ObjCRuntime objCRuntime; unsigned objcABIVersion = 0; bool NeXTRuntimeIsDefault - = (IsRewriter || getToolChain().getTriple().isOSDarwin()); + = (IsRewriter || IsModernRewriter || + getToolChain().getTriple().isOSDarwin()); if (Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, NeXTRuntimeIsDefault)) { objCRuntime.setKind(ObjCRuntime::NeXT); @@ -1906,8 +2348,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } else { // Otherwise, determine if we are using the non-fragile ABI. - bool NonFragileABIIsDefault - = (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault()); + bool NonFragileABIIsDefault = + (IsModernRewriter || + (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault())); if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi, options::OPT_fno_objc_nonfragile_abi, NonFragileABIIsDefault)) { @@ -1950,10 +2393,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // -fobjc-default-synthesize-properties=0 is default. - if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, - options::OPT_fno_objc_default_synthesize_properties, - getToolChain().IsObjCDefaultSynthPropertiesDefault())) { + // -fobjc-default-synthesize-properties=1 is default. This only has an effect + // if the nonfragile objc abi is used. + if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } @@ -1961,6 +2403,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // NOTE: This logic is duplicated in ToolChains.cpp. bool ARC = isObjCAutoRefCount(Args); if (ARC) { + if (!getToolChain().SupportsObjCARC()) + D.Diag(diag::err_arc_unsupported); + CmdArgs.push_back("-fobjc-arc"); // FIXME: It seems like this entire block, and several around it should be @@ -1983,7 +2428,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. - if (IsRewriter) + if (IsRewriter || IsModernRewriter) CmdArgs.push_back("-fno-objc-infer-related-result-type"); // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only @@ -2006,7 +2451,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Add exception args. addExceptionArgs(Args, InputType, getToolChain().getTriple(), - KernelOrKext, IsRewriter, objcABIVersion, CmdArgs); + KernelOrKext, objcABIVersion, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -2057,6 +2502,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.hasArg(options::OPT_fapple_kext)) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); + Args.ClaimAllArgs(options::OPT_fno_common); } // -fcommon is default, only pass non-default. @@ -2086,11 +2532,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); - // Enable -fdiagnostics-show-name by default. - if (Args.hasFlag(options::OPT_fdiagnostics_show_name, - options::OPT_fno_diagnostics_show_name, false)) - CmdArgs.push_back("-fdiagnostics-show-name"); - // Enable -fdiagnostics-show-option by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_option, options::OPT_fno_diagnostics_show_option)) @@ -2164,6 +2605,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } + if (Args.hasFlag(options::OPT_fapple_pragma_pack, + options::OPT_fno_apple_pragma_pack, false)) + CmdArgs.push_back("-fapple-pragma-pack"); + // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM. // // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941. @@ -2189,6 +2634,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_dM); Args.AddLastArg(CmdArgs, options::OPT_dD); + + // Handle serialized diagnostics. + if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) { + CmdArgs.push_back("-serialize-diagnostic-file"); + CmdArgs.push_back(Args.MakeArgString(A->getValue(Args))); + } // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. @@ -2237,7 +2688,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ie = Args.end(); it != ie; ++it) (*it)->render(Args, OriginalArgs); - llvm::SmallString<256> Flags; + SmallString<256> Flags; Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { Flags += " "; @@ -2271,6 +2722,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.ClaimAllArgs(options::OPT_emit_llvm); } +void ClangAs::AddARMTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + llvm::Triple Triple = getToolChain().getTriple(); + + // Set the CPU based on -march= and -mcpu=. + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + + // Honor -mfpu=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + addFPUArgs(D, A, Args, CmdArgs); + + // Honor -mfpmath=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) + addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); +} + void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2307,10 +2776,54 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, if (UseRelaxAll(C, Args)) CmdArgs.push_back("-relax-all"); + // Add target specific cpu and features flags. + switch(getToolChain().getTriple().getArch()) { + default: + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + AddARMTargetArgs(Args, CmdArgs); + break; + } + // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); - // FIXME: Add -g support, once we have it. + // Determine the original source input. + const Action *SourceAction = &JA; + while (SourceAction->getKind() != Action::InputClass) { + assert(!SourceAction->getInputs().empty() && "unexpected root action!"); + SourceAction = SourceAction->getInputs()[0]; + } + + // Forward -g, 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"); + } + + // Optionally embed the -cc1as level arguments into the debug info, for build + // analysis. + if (getToolChain().UseDwarfDebugFlags()) { + ArgStringList OriginalArgs; + for (ArgList::const_iterator it = Args.begin(), + ie = Args.end(); it != ie; ++it) + (*it)->render(Args, OriginalArgs); + + SmallString<256> Flags; + const char *Exec = getToolChain().getDriver().getClangProgramPath(); + Flags += Exec; + for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { + Flags += " "; + Flags += OriginalArgs[i]; + } + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(Args.MakeArgString(Flags.str())); + } // FIXME: Add -static support, once we have it. @@ -2389,6 +2902,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fsyntax-only"); } + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go @@ -2437,12 +2952,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, if (!customGCCName.empty()) GCCName = customGCCName.c_str(); else if (D.CCCIsCXX) { -#ifdef IS_CYGWIN15 - // FIXME: Detect the version of Cygwin at runtime? - GCCName = "g++-4"; -#else GCCName = "g++"; -#endif } else GCCName = "gcc"; @@ -2488,6 +2998,155 @@ void gcc::Link::RenderExtraToolArgs(const JobAction &JA, // The types are (hopefully) good enough. } +// Hexagon tools start. +void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const { + +} +void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const Driver &D = getToolChain().getDriver(); + ArgStringList CmdArgs; + + std::string MarchString = "-march="; + MarchString += getHexagonTargetCPU(Args); + CmdArgs.push_back(Args.MakeArgString(MarchString)); + + RenderExtraToolArgs(JA, CmdArgs); + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Unexpected output"); + CmdArgs.push_back("-fsyntax-only"); + } + + + // Only pass -x if gcc will understand it; otherwise hope gcc + // understands the suffix correctly. The main use case this would go + // wrong in is for linker inputs if they happened to have an odd + // suffix; really the only way to get this to happen is a command + // like '-x foobar a.c' which will treat a.c like a linker input. + // + // FIXME: For the linker case specifically, can we safely convert + // inputs into '-Wl,' options? + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + // Don't try to pass LLVM or AST inputs to a generic gcc. + if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || + II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) + D.Diag(clang::diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString(); + else if (II.getType() == types::TY_AST) + D.Diag(clang::diag::err_drv_no_ast_support) + << getToolChain().getTripleString(); + + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ? + II.getInputArg().render(Args, CmdArgs); + } + + const char *GCCName = "hexagon-as"; + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + +} +void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const { + // The types are (hopefully) good enough. +} + +void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const Driver &D = getToolChain().getDriver(); + ArgStringList CmdArgs; + + for (ArgList::const_iterator + it = Args.begin(), ie = Args.end(); it != ie; ++it) { + Arg *A = *it; + if (A->getOption().hasForwardToGCC()) { + // Don't forward any -g arguments to assembly steps. + if (isa<AssembleJobAction>(JA) && + A->getOption().matches(options::OPT_g_Group)) + continue; + + // It is unfortunate that we have to claim here, as this means + // we will basically never report anything interesting for + // platforms using a generic gcc, even if we are just using gcc + // to get to the assembler. + A->claim(); + A->render(Args, CmdArgs); + } + } + + RenderExtraToolArgs(JA, CmdArgs); + + // 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))); + } + else { + CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args))); + } + + CmdArgs.push_back("-mqdsp6-compat"); + + const char *GCCName; + if (C.getDriver().CCCIsCXX) + GCCName = "hexagon-g++"; + else + GCCName = "hexagon-gcc"; + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + + if (Output.isFilename()) { + 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; + + // 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(); + + 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); + } + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + +} +// Hexagon tools end. + + const char *darwin::CC1::getCC1Name(types::ID Type) const { switch (Type) { default: @@ -2510,6 +3169,8 @@ const char *darwin::CC1::getCC1Name(types::ID Type) const { } } +void darwin::CC1::anchor() {} + const char *darwin::CC1::getBaseInputName(const ArgList &Args, const InputInfoList &Inputs) { return Args.MakeArgString( @@ -2548,13 +3209,27 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { StringRef Option = *it; bool RemoveOption = false; - // Remove -faltivec - if (Option.equals("-faltivec")) { - it = CmdArgs.erase(it); + // 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) @@ -2595,6 +3270,7 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { .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) @@ -3000,9 +3676,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, 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(); - const Arg *A; - if ((A = Args.getLastArg(options::OPT_traditional))) + if (const Arg *A = Args.getLastArg(options::OPT_traditional)) D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; @@ -3119,7 +3797,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); else if (Args.hasArg(options::OPT_g_Group)) - CmdArgs.push_back("--gdwarf2"); + CmdArgs.push_back("-g"); } // Derived from asm spec. @@ -3154,6 +3832,8 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void darwin::DarwinTool::anchor() {} + void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const { StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); @@ -3185,13 +3865,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // Newer linkers support -demangle, pass it if supported and not disabled by // the user. - // - // FIXME: We temporarily avoid passing -demangle to any iOS linker, because - // unfortunately we can't be guaranteed that the linker version used there - // will match the linker version detected at configure time. We need the - // universal driver. - if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle) && - !DarwinTC.isTargetIPhoneOS()) { + 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. @@ -3291,8 +3965,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_init); // Add the deployment target. - unsigned TargetVersion[3]; - DarwinTC.getTargetVersion(TargetVersion); + 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 @@ -3307,9 +3980,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, CmdArgs.push_back("-iphoneos_version_min"); else CmdArgs.push_back("-macosx_version_min"); - CmdArgs.push_back(Args.MakeArgString(Twine(TargetVersion[0]) + "." + - Twine(TargetVersion[1]) + "." + - Twine(TargetVersion[2]))); + CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); @@ -3492,7 +4163,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lcrt1.o"); else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lcrt1.10.5.o"); - else + else if (getDarwinToolChain().isMacosxVersionLT(10, 8)) CmdArgs.push_back("-lcrt1.10.6.o"); // darwin_crt2 spec is empty. @@ -3513,20 +4184,42 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); + // If we're building a dynamic lib with -faddress-sanitizer, unresolved + // symbols may appear. Mark all of them as dynamic_lookup. + // Linking executables is handled in lib/Driver/ToolChains.cpp. + if (Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) { + if (Args.hasArg(options::OPT_dynamiclib) || + Args.hasArg(options::OPT_bundle)) { + CmdArgs.push_back("-undefined"); + CmdArgs.push_back("dynamic_lookup"); + } + } + if (Args.hasArg(options::OPT_fopenmp)) // This is more complicated in gcc... CmdArgs.push_back("-lgomp"); getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs); - // In ARC, if we don't have 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. - if (isObjCAutoRefCount(Args)) { - ObjCRuntime runtime; - getDarwinToolChain().configureObjCRuntime(runtime); - if (!runtime.HasARC) - getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); + if (isObjCRuntimeLinked(Args)) { + // Avoid linking compatibility stubs on i386 mac. + if (!getDarwinToolChain().isTargetMacOS() || + getDarwinToolChain().getArchName() != "i386") { + // 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().configureObjCRuntime(runtime); + // We use arclite library for both ARC and subscripting support. + if ((!runtime.HasARC && isObjCAutoRefCount(Args)) || + !runtime.HasSubscripting) + getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); + CmdArgs.push_back("-framework"); + CmdArgs.push_back("Foundation"); + } + // Link libobj. + CmdArgs.push_back("-lobjc"); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -3557,8 +4250,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // endfile_spec is empty. } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_F); @@ -3618,6 +4309,9 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("--verify"); + CmdArgs.push_back("--debug-info"); + CmdArgs.push_back("--eh-frame"); + CmdArgs.push_back("--quiet"); assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; @@ -3631,6 +4325,137 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + CmdArgs.push_back(II.getFilename()); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("as")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + + +void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + // FIXME: Find a real GCC, don't hard-code versions here + std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/"; + const llvm::Triple &T = getToolChain().getTriple(); + std::string LibPath = "/usr/lib/"; + llvm::Triple::ArchType Arch = T.getArch(); + switch (Arch) { + case llvm::Triple::x86: + GCCLibPath += ("i386-" + T.getVendorName() + "-" + + T.getOSName()).str() + "/4.5.2/"; + break; + case llvm::Triple::x86_64: + GCCLibPath += ("i386-" + T.getVendorName() + "-" + + T.getOSName()).str(); + GCCLibPath += "/4.5.2/amd64/"; + LibPath += "amd64/"; + break; + default: + assert(0 && "Unsupported architecture"); + } + + ArgStringList CmdArgs; + + // Demangle C++ names in errors + CmdArgs.push_back("-C"); + + if ((!Args.hasArg(options::OPT_nostdlib)) && + (!Args.hasArg(options::OPT_shared))) { + CmdArgs.push_back("-e"); + CmdArgs.push_back("_start"); + } + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + CmdArgs.push_back("-dn"); + } else { + CmdArgs.push_back("-Bdynamic"); + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-shared"); + } else { + CmdArgs.push_back("--dynamic-linker"); + CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1")); + } + } + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); + } else { + CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); + } + if (getToolChain().getDriver().CCCIsCXX) + CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o")); + } + + CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath)); + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_r); + + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (getToolChain().getDriver().CCCIsCXX) + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lgcc_s"); + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lm"); + } + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o")); + } + CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o")); + + addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("ld")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -3806,8 +4631,12 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crt0.o"))); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("gcrt0.o"))); + else + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { @@ -3832,7 +4661,10 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); - CmdArgs.push_back("-lm"); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lm_p"); + else + CmdArgs.push_back("-lm"); } // FIXME: For some reason GCC passes -lgcc before adding @@ -3841,8 +4673,12 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); - if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back("-lc"); + if (!Args.hasArg(options::OPT_shared)) { + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lc_p"); + else + CmdArgs.push_back("-lc"); + } CmdArgs.push_back("-lgcc"); } @@ -4062,11 +4898,9 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on NetBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. - if (ToolTriple.getArch() == llvm::Triple::x86_64 && - getToolChain().getArch() == llvm::Triple::x86) + if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); - // Set byte order explicitly if (getToolChain().getArchName() == "mips") CmdArgs.push_back("-EB"); @@ -4116,8 +4950,7 @@ 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 (ToolTriple.getArch() == llvm::Triple::x86_64 && - getToolChain().getArch() == llvm::Triple::x86) { + if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); } @@ -4218,12 +5051,49 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--32"); } else if (getToolChain().getArch() == llvm::Triple::x86_64) { CmdArgs.push_back("--64"); + } else if (getToolChain().getArch() == llvm::Triple::ppc) { + CmdArgs.push_back("-a32"); + CmdArgs.push_back("-mppc"); + CmdArgs.push_back("-many"); + } else if (getToolChain().getArch() == llvm::Triple::ppc64) { + CmdArgs.push_back("-a64"); + CmdArgs.push_back("-mppc64"); + CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::arm) { StringRef MArch = getToolChain().getArchName(); if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") CmdArgs.push_back("-mfpu=neon"); + } else if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mipsel || + getToolChain().getArch() == llvm::Triple::mips64 || + getToolChain().getArch() == llvm::Triple::mips64el) { + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); + + 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()); + + if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mips64) + CmdArgs.push_back("-EB"); + else + CmdArgs.push_back("-EL"); } + Args.AddLastArg(CmdArgs, options::OPT_march_EQ); + Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); + Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -4241,6 +5111,30 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs, + const ArgList &Args) { + bool StaticLibgcc = Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_static_libgcc); + if (!D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); + + if (StaticLibgcc) { + if (D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); + } else { + if (!D.CCCIsCXX) + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + if (!D.CCCIsCXX) + CmdArgs.push_back("--no-as-needed"); + } + + if (StaticLibgcc) + CmdArgs.push_back("-lgcc_eh"); + else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); +} + void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4290,6 +5184,14 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf32ppclinux"); else if (ToolChain.getArch() == llvm::Triple::ppc64) CmdArgs.push_back("elf64ppc"); + else if (ToolChain.getArch() == llvm::Triple::mips) + CmdArgs.push_back("elf32btsmip"); + else if (ToolChain.getArch() == llvm::Triple::mipsel) + CmdArgs.push_back("elf32ltsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64) + CmdArgs.push_back("elf64btsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64el) + CmdArgs.push_back("elf64ltsmip"); else CmdArgs.push_back("elf_x86_64"); @@ -4313,6 +5215,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("/lib/ld-linux.so.3"); + else if (ToolChain.getArch() == llvm::Triple::mips || + ToolChain.getArch() == llvm::Triple::mipsel) + CmdArgs.push_back("/lib/ld.so.1"); + else if (ToolChain.getArch() == llvm::Triple::mips64 || + ToolChain.getArch() == llvm::Triple::mips64el) + CmdArgs.push_back("/lib64/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc64) @@ -4356,35 +5264,36 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 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) || Args.hasArg(options::OPT_use_gold_plugin)) { + CmdArgs.push_back("-plugin"); + std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; + CmdArgs.push_back(Args.MakeArgString(Plugin)); + } + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); CmdArgs.push_back("-lm"); } + // Call this before we add the C run-time. + addAsanRTLinux(getToolChain(), Args, CmdArgs); + if (!Args.hasArg(options::OPT_nostdlib)) { if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); - if (!D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - - if (Args.hasArg(options::OPT_static)) { - if (D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - } else { - if (!D.CCCIsCXX) - CmdArgs.push_back("--as-needed"); - CmdArgs.push_back("-lgcc_s"); - if (!D.CCCIsCXX) - CmdArgs.push_back("--no-as-needed"); - } - - if (Args.hasArg(options::OPT_static)) - CmdArgs.push_back("-lgcc_eh"); - else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); + AddLibgcc(D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads)) @@ -4394,19 +5303,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); - else { - if (!D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - - if (!D.CCCIsCXX) - CmdArgs.push_back("--as-needed"); - CmdArgs.push_back("-lgcc_s"); - if (!D.CCCIsCXX) - CmdArgs.push_back("--no-as-needed"); - - if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - } + else + AddLibgcc(D, CmdArgs, Args); if (!Args.hasArg(options::OPT_nostartfiles)) { @@ -4423,12 +5321,6 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - if (Args.hasArg(options::OPT_use_gold_plugin)) { - CmdArgs.push_back("-plugin"); - std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; - CmdArgs.push_back(Args.MakeArgString(Plugin)); - } - C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } @@ -4452,7 +5344,7 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("gas")); + Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -4472,9 +5364,12 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "/usr/gnu/lib/crtso.o"))); + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); + } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); @@ -4482,33 +5377,28 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } - - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-lc"); - CmdArgs.push_back("-lgcc"); - CmdArgs.push_back("-L/usr/gnu/lib"); - // FIXME: fill in the correct search path for the final - // support libraries. - CmdArgs.push_back("-L/usr/gnu/lib/gcc/i686-pc-minix/4.4.3"); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "/usr/gnu/lib/libend.a"))); + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lCompilerRT-Generic"); + CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib"); + CmdArgs.push_back( + Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("/usr/gnu/bin/gld")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } |