diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Compilation.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 117 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/OptTable.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | 16 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 471 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.h | 82 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 492 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.h | 3 |
9 files changed, 731 insertions, 467 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index 5619212..2657faa 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -101,6 +101,12 @@ bool Compilation::CleanupFileList(const ArgStringList &Files, llvm::sys::Path P(*it); std::string Error; + // Don't try to remove files which we don't have write access to (but may be + // able to remove). Underlying tools may have intentionally not overwritten + // them. + if (!P.canWrite()) + continue; + if (P.eraseFromDisk(false, &Error)) { // Failure is only failure if the file exists and is "regular". There is // a race condition here due to the limited interface of diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 4b6aef6..302779b 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/Version.h" #include "llvm/Config/config.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/PrettyStackTrace.h" @@ -42,13 +43,6 @@ #include <map> -#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; @@ -58,15 +52,17 @@ Driver::Driver(llvm::StringRef _ClangExecutable, bool IsProduction, bool CXXIsProduction, Diagnostic &_Diags) : Opts(createDriverOptTable()), Diags(_Diags), - ClangExecutable(_ClangExecutable), DefaultHostTriple(_DefaultHostTriple), - DefaultImageName(_DefaultImageName), + ClangExecutable(_ClangExecutable), UseStdLib(true), + DefaultHostTriple(_DefaultHostTriple), DefaultImageName(_DefaultImageName), DriverTitle("clang \"gcc-compatible\" driver"), Host(0), - CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), CCCIsCXX(false), - CCCEcho(false), CCCPrintBindings(false), CCPrintOptions(false), - CCPrintHeaders(false), CCCGenericGCCName("gcc"), - CheckInputsExist(true), CCCUseClang(true), CCCUseClangCXX(true), - CCCUseClangCPP(true), CCCUsePCH(true), SuppressMissingInputWarning(false) { + CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), + CCLogDiagnosticsFilename(0), CCCIsCXX(false), + CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), + CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), + CCCGenericGCCName(""), CheckInputsExist(true), CCCUseClang(true), + CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true), + SuppressMissingInputWarning(false) { if (IsProduction) { // In a "production" build, only use clang on architectures we expect to // work, and don't use clang C++. @@ -100,11 +96,10 @@ Driver::~Driver() { delete Host; } -InputArgList *Driver::ParseArgStrings(const char **ArgBegin, - const char **ArgEnd) { +InputArgList *Driver::ParseArgStrings(llvm::ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned MissingArgIndex, MissingArgCount; - InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd, + InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), MissingArgIndex, MissingArgCount); // Check for missing argument error. @@ -206,7 +201,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { return DAL; } -Compilation *Driver::BuildCompilation(int argc, const char **argv) { +Compilation *Driver::BuildCompilation(llvm::ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which effect driver behavior, somewhere @@ -218,9 +213,7 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintOptions = false, CCCPrintActions = false; - const char **Start = argv + 1, **End = argv + argc; - - InputArgList *Args = ParseArgStrings(Start, End); + InputArgList *Args = ParseArgStrings(ArgList.slice(1)); // -no-canonical-prefixes is used very early in main. Args->ClaimAllArgs(options::OPT_no_canonical_prefixes); @@ -238,13 +231,6 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases); CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings); CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX; - if (CCCIsCXX) { -#ifdef IS_CYGWIN15 - CCCGenericGCCName = "g++-4"; -#else - CCCGenericGCCName = "g++"; -#endif - } CCCEcho = Args->hasArg(options::OPT_ccc_echo); if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name)) CCCGenericGCCName = A->getValue(*Args); @@ -287,6 +273,10 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { A->claim(); PrefixDirs.push_back(A->getValue(*Args, 0)); } + if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ)) + SysRoot = A->getValue(*Args); + if (Args->hasArg(options::OPT_nostdlib)) + UseStdLib = false; Host = GetHostInfo(DefaultHostTriple.c_str()); @@ -593,7 +583,7 @@ static bool ContainsCompileAction(const Action *A) { } void Driver::BuildUniversalActions(const ToolChain &TC, - const ArgList &Args, + const DerivedArgList &Args, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building universal build actions"); // Collect the list of architectures. Duplicates are allowed, but should only @@ -688,7 +678,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, } } -void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, +void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); // Start by constructing the list of inputs and their types. @@ -721,18 +711,23 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // // Otherwise emit an error but still use a valid type to avoid // spurious errors (e.g., no inputs). - if (!Args.hasArgNoClaim(options::OPT_E)) + if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP) Diag(clang::diag::err_drv_unknown_stdin_type); Ty = types::TY_C; } else { - // Otherwise lookup by extension, and fallback to ObjectType if not - // found. We use a host hook here because Darwin at least has its own + // Otherwise lookup by extension. + // Fallback is C if invoked as C preprocessor or Object otherwise. + // We use a host hook here because Darwin at least has its own // idea of what .s is. if (const char *Ext = strrchr(Value, '.')) Ty = TC.LookupTypeForExtension(Ext + 1); - if (Ty == types::TY_INVALID) - Ty = types::TY_Object; + if (Ty == types::TY_INVALID) { + if (CCCIsCPP) + Ty = types::TY_C; + else + Ty = types::TY_Object; + } // If the driver is invoked as C++ compiler (like clang++ or c++) it // should autodetect some input files as C++ for g++ compatibility. @@ -799,6 +794,15 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, } } + if (CCCIsCPP && Inputs.empty()) { + // If called as standalone preprocessor, stdin is processed + // if no other input is present. + unsigned Index = Args.getBaseArgs().MakeIndex("-"); + Arg *A = Opts->ParseOneArg(Args, Index); + A->claim(); + Inputs.push_back(std::make_pair(types::TY_C, A)); + } + if (!SuppressMissingInputWarning && Inputs.empty()) { Diag(clang::diag::err_drv_no_input_files); return; @@ -811,7 +815,8 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, phases::ID FinalPhase; // -{E,M,MM} only run the preprocessor. - if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) || + if (CCCIsCPP || + (FinalPhaseArg = Args.getLastArg(options::OPT_E)) || (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { FinalPhase = phases::Preprocess; @@ -853,6 +858,10 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // Claim here to avoid the more general unused warning. InputArg->claim(); + // Suppress all unused style warnings with -Qunused-arguments + if (Args.hasArg(options::OPT_Qunused_arguments)) + continue; + // Special case '-E' warning on a previously preprocessed file to make // more sense. if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess && @@ -945,7 +954,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, } else if (Args.hasArg(options::OPT_emit_ast)) { return new CompileJobAction(Input, types::TY_AST); } else if (Args.hasArg(options::OPT_emit_llvm) || - Args.hasArg(options::OPT_flto) || HasO4) { + Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false) || + HasO4) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return new CompileJobAction(Input, Output); @@ -1064,14 +1074,17 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) || C.getArgs().hasArg(options::OPT_static) || C.getArgs().hasArg(options::OPT_fapple_kext)); - bool IsIADefault = (TC->IsIntegratedAssemblerDefault() && !HasStatic); + bool IsDarwin = TC->getTriple().getOS() == llvm::Triple::Darwin; + bool IsIADefault = TC->IsIntegratedAssemblerDefault() && + !(HasStatic && IsDarwin); if (C.getArgs().hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, IsIADefault) && !C.getArgs().hasArg(options::OPT_save_temps) && isa<AssembleJobAction>(JA) && Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) { - const Tool &Compiler = TC->SelectTool(C,cast<JobAction>(**Inputs->begin())); + const Tool &Compiler = TC->SelectTool( + C, cast<JobAction>(**Inputs->begin()), (*Inputs)[0]->getInputs()); if (Compiler.hasIntegratedAssembler()) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = &Compiler; @@ -1080,7 +1093,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, // Otherwise use the tool for the current job. if (!ToolForJob) - ToolForJob = &TC->SelectTool(C, *JA); + ToolForJob = &TC->SelectTool(C, *JA, *Inputs); // See if we should use an integrated preprocessor. We do so when we have // exactly one input, since this is the only use case we care about @@ -1206,7 +1219,13 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } llvm::SmallString<128> BasePath(BaseInput); - llvm::StringRef BaseName = llvm::sys::path::filename(BasePath); + llvm::StringRef BaseName; + + // Dsymutil actions should use the full path. + if (isa<DsymutilJobAction>(JA)) + BaseName = BasePath; + else + BaseName = llvm::sys::path::filename(BasePath); // Determine what the derived output name should be. const char *NamedOutput; @@ -1243,7 +1262,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { // attempting to use this prefix when lokup up program paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), ie = PrefixDirs.end(); it != ie; ++it) { - llvm::sys::Path P(*it); + std::string Dir(*it); + if (Dir.empty()) + continue; + if (Dir[0] == '=') + Dir = SysRoot + Dir.substr(1); + llvm::sys::Path P(Dir); P.appendComponent(Name); bool Exists; if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) @@ -1253,7 +1277,12 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { const ToolChain::path_list &List = TC.getFilePaths(); for (ToolChain::path_list::const_iterator it = List.begin(), ie = List.end(); it != ie; ++it) { - llvm::sys::Path P(*it); + std::string Dir(*it); + if (Dir.empty()) + continue; + if (Dir[0] == '=') + Dir = SysRoot + Dir.substr(1); + llvm::sys::Path P(Dir); P.appendComponent(Name); bool Exists; if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) @@ -1323,7 +1352,7 @@ std::string Driver::GetTemporaryPath(const char *Suffix) const { const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { llvm::PrettyStackTraceString CrashInfo("Constructing host"); - llvm::Triple Triple(TripleStr); + llvm::Triple Triple(llvm::Triple::normalize(TripleStr).c_str()); // TCE is an osless target if (Triple.getArchName() == "tce") diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp index cd413180..198af54 100644 --- a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp @@ -113,14 +113,9 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, TCTriple.setArch(Arch); // If we recognized the arch, match it to the toolchains we support. - const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN"); - if (UseNewToolChain || - Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { TC = new toolchains::DarwinClang(*this, TCTriple); - } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { - // We still use the legacy DarwinGCC toolchain on X86. - TC = new toolchains::DarwinGCC(*this, TCTriple); } else TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); } diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp index c3d3048..0252b3e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp @@ -20,9 +20,9 @@ using namespace clang::driver::options; // Ordering on Info. The ordering is *almost* lexicographic, with two // exceptions. First, '\0' comes at the end of the alphabet instead of -// the beginning (thus options preceed any other options which prefix +// the beginning (thus options precede any other options which prefix // them). Second, for options with the same name, the less permissive -// version should come first; a Flag option should preceed a Joined +// version should come first; a Flag option should precede a Joined // option, for example. static int StrCmpOptionName(const char *A, const char *B) { diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index e305683..d919915 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -47,7 +47,7 @@ bool ToolChain::HasNativeLLVMSupport() const { return false; } -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. +/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, @@ -101,6 +101,8 @@ static const char *getARMTargetCPU(const ArgList &Args, return "iwmmxt"; if (MArch == "xscale") return "xscale"; + if (MArch == "armv6m" || MArch == "armv6-m") + return "cortex-m0"; // If all else failed, return the most base CPU LLVM supports. return "arm7tdmi"; @@ -137,6 +139,12 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) { if (CPU == "cortex-a8" || CPU == "cortex-a9") return "v7"; + if (CPU == "cortex-m3") + return "v7m"; + + if (CPU == "cortex-m0") + return "v6m"; + return ""; } @@ -168,10 +176,10 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const { } std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const { - // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on - // non-Darwin. + // Diagnose use of Darwin OS deployment target arguments on non-Darwin. if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, - options::OPT_miphoneos_version_min_EQ)) + options::OPT_miphoneos_version_min_EQ, + options::OPT_mios_simulator_version_min_EQ)) getDriver().Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 422c572..499587a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -105,7 +105,8 @@ static const char *GetArmArchForMCpu(llvm::StringRef Value) { return "xscale"; if (Value == "arm1136j-s" || Value == "arm1136jf-s" || - Value == "arm1176jz-s" || Value == "arm1176jzf-s") + Value == "arm1176jz-s" || Value == "arm1176jzf-s" || + Value == "cortex-m0" ) return "armv6"; if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3") @@ -118,7 +119,8 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const { switch (getTriple().getArch()) { default: return getArchName(); - + + case llvm::Triple::thumb: case llvm::Triple::arm: { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) @@ -133,82 +135,6 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const { } } -DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple) - : Darwin(Host, Triple) -{ - // We can only work with 4.2.1 currently. - GCCVersion[0] = 4; - GCCVersion[1] = 2; - GCCVersion[2] = 1; - - // Set up the tool chain paths to match gcc. - ToolChainDir = "i686-apple-darwin"; - ToolChainDir += llvm::utostr(DarwinVersion[0]); - ToolChainDir += "/"; - ToolChainDir += llvm::utostr(GCCVersion[0]); - ToolChainDir += '.'; - ToolChainDir += llvm::utostr(GCCVersion[1]); - ToolChainDir += '.'; - ToolChainDir += llvm::utostr(GCCVersion[2]); - - // Try the next major version if that tool chain dir is invalid. - std::string Tmp = "/usr/lib/gcc/" + ToolChainDir; - bool Exists; - if (llvm::sys::fs::exists(Tmp, Exists) || Exists) { - std::string Next = "i686-apple-darwin"; - Next += llvm::utostr(DarwinVersion[0] + 1); - Next += "/"; - Next += llvm::utostr(GCCVersion[0]); - Next += '.'; - Next += llvm::utostr(GCCVersion[1]); - Next += '.'; - Next += llvm::utostr(GCCVersion[2]); - - // Use that if it exists, otherwise hope the user isn't linking. - // - // FIXME: Drop dependency on gcc's tool chain. - Tmp = "/usr/lib/gcc/" + Next; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - ToolChainDir = Next; - } - - std::string Path; - if (getArchName() == "x86_64") { - Path = getDriver().Dir; - Path += "/../lib/gcc/"; - Path += ToolChainDir; - Path += "/x86_64"; - getFilePaths().push_back(Path); - - Path = "/usr/lib/gcc/"; - Path += ToolChainDir; - Path += "/x86_64"; - getFilePaths().push_back(Path); - } - - Path = getDriver().Dir; - Path += "/../lib/gcc/"; - Path += ToolChainDir; - getFilePaths().push_back(Path); - - Path = "/usr/lib/gcc/"; - Path += ToolChainDir; - getFilePaths().push_back(Path); - - Path = getDriver().Dir; - Path += "/../libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); - - Path = "/usr/libexec/gcc/"; - Path += ToolChainDir; - getProgramPaths().push_back(Path); - - getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); -} - Darwin::~Darwin() { // Free tool implementations. for (llvm::DenseMap<unsigned, Tool*>::iterator @@ -226,33 +152,31 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const { unsigned Version[3]; getTargetVersion(Version); - - // Mangle the target version into the OS triple component. For historical - // reasons that make little sense, the version passed here is the "darwin" - // version, which drops the 10 and offsets by 4. See inverse code when - // setting the OS version preprocessor define. - if (!isTargetIPhoneOS()) { - Version[0] = Version[1] + 4; - Version[1] = Version[2]; - Version[2] = 0; - } else { - // Use the environment to communicate that we are targetting iPhoneOS. - Triple.setEnvironmentName("iphoneos"); - } - + llvm::SmallString<16> Str; - llvm::raw_svector_ostream(Str) << "darwin" << Version[0] - << "." << Version[1] << "." << Version[2]; + llvm::raw_svector_ostream(Str) + << (isTargetIPhoneOS() ? "ios" : "macosx") + << Version[0] << "." << Version[1] << "." << Version[2]; Triple.setOSName(Str.str()); return Triple.getTriple(); } -Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; - if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) - Key = Action::AnalyzeJobClass; - else + + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) { + // Fallback to llvm-gcc for i386 kext compiles, we don't support that ABI. + if (Inputs.size() == 1 && + types::isCXX(Inputs[0]->getType()) && + getTriple().getOS() == llvm::Triple::Darwin && + getTriple().getArch() == llvm::Triple::x86 && + C.getArgs().getLastArg(options::OPT_fapple_kext)) + Key = JA.getKind(); + else + Key = Action::AnalyzeJobClass; + } else Key = JA.getKind(); // FIXME: This doesn't belong here, but ideally we will support static soon @@ -297,91 +221,12 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const { return *T; } -void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - std::string Tmp; - - // FIXME: Derive these correctly. - if (getArchName() == "x86_64") { - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/x86_64")); - // Intentionally duplicated for (temporary) gcc bug compatibility. - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/x86_64")); - } - - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir)); - - Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir; - bool Exists; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - Tmp = getDriver().Dir + "/../lib/gcc"; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir)); - // Intentionally duplicated for (temporary) gcc bug compatibility. - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir)); - Tmp = getDriver().Dir + "/../lib/" + ToolChainDir; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - Tmp = getDriver().Dir + "/../lib"; - if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) - CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/../../../" + ToolChainDir)); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir + - "/../../..")); -} - -void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - // Note that this routine is only used for targetting OS X. - - // Derived from libgcc and lib specs but refactored. - if (Args.hasArg(options::OPT_static)) { - CmdArgs.push_back("-lgcc_static"); - } else { - if (Args.hasArg(options::OPT_static_libgcc)) { - CmdArgs.push_back("-lgcc_eh"); - } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) { - // Derived from darwin_iphoneos_libgcc spec. - if (isTargetIPhoneOS()) { - CmdArgs.push_back("-lgcc_s.1"); - } else { - CmdArgs.push_back("-lgcc_s.10.5"); - } - } else if (Args.hasArg(options::OPT_shared_libgcc) || - Args.hasFlag(options::OPT_fexceptions, - options::OPT_fno_exceptions) || - Args.hasArg(options::OPT_fgnu_runtime)) { - // FIXME: This is probably broken on 10.3? - if (isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lgcc_s.10.4"); - else if (isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lgcc_s.10.5"); - } else { - if (isMacosxVersionLT(10, 3, 9)) - ; // Do nothing. - else if (isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lgcc_s.10.4"); - else if (isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lgcc_s.10.5"); - } - - if (isTargetIPhoneOS() || isMacosxVersionLT(10, 6)) { - CmdArgs.push_back("-lgcc"); - CmdArgs.push_back("-lSystem"); - } else { - CmdArgs.push_back("-lSystem"); - CmdArgs.push_back("-lgcc"); - } - } -} DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) : Darwin(Host, Triple) { + std::string UsrPrefix = "llvm-gcc-4.2/"; + getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -392,18 +237,18 @@ DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) getProgramPaths().push_back(getDriver().Dir); // For fallback, we need to know how to find the GCC cc1 executables, so we - // also add the GCC libexec paths. This is legiy code that can be removed once - // fallback is no longer useful. + // also add the GCC libexec paths. This is legacy code that can be removed + // once fallback is no longer useful. std::string ToolChainDir = "i686-apple-darwin"; ToolChainDir += llvm::utostr(DarwinVersion[0]); ToolChainDir += "/4.2.1"; std::string Path = getDriver().Dir; - Path += "/../libexec/gcc/"; + Path += "/../" + UsrPrefix + "libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); - Path = "/usr/libexec/gcc/"; + Path = "/usr/" + UsrPrefix + "libexec/gcc/"; Path += ToolChainDir; getProgramPaths().push_back(Path); } @@ -498,12 +343,13 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // Select the dynamic runtime library and the target specific static library. const char *DarwinStaticLib = 0; if (isTargetIPhoneOS()) { - CmdArgs.push_back("-lgcc_s.1"); + // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, + // it never went into the SDK. + if (!isTargetIOSSimulator()) + CmdArgs.push_back("-lgcc_s.1"); - // We may need some static functions for armv6/thumb which are required to - // be in the same linkage unit as their caller. - if (getDarwinArchName(Args) == "armv6") - DarwinStaticLib = "libclang_rt.armv6.a"; + // We currently always need a static runtime library for iOS. + DarwinStaticLib = "libclang_rt.ios.a"; } else { // The dynamic runtime library was merged with libSystem for 10.6 and // beyond; only 10.4 and 10.5 need an additional runtime library. @@ -513,7 +359,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, CmdArgs.push_back("-lgcc_s.10.5"); // For OS X, we thought we would only need a static runtime library when - // targetting 10.4, to provide versions of the static functions which were + // targeting 10.4, to provide versions of the static functions which were // omitted from 10.4.dylib. // // Unfortunately, that turned out to not be true, because Darwin system @@ -547,46 +393,69 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { const OptTable &Opts = getDriver().getOpts(); Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ); - Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); - if (OSXVersion && iPhoneVersion) { + Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); + Arg *iOSSimVersion = Args.getLastArg( + options::OPT_mios_simulator_version_min_EQ); + if (OSXVersion && (iOSVersion || iOSSimVersion)) { getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) - << iPhoneVersion->getAsString(Args); - iPhoneVersion = 0; - } else if (!OSXVersion && !iPhoneVersion) { - // If neither OS X nor iPhoneOS targets were specified, check for + << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args); + iOSVersion = iOSSimVersion = 0; + } else if (iOSVersion && iOSSimVersion) { + getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with) + << iOSVersion->getAsString(Args) + << iOSSimVersion->getAsString(Args); + iOSSimVersion = 0; + } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) { + // If not deployment target was specified on the command line, check for // environment defines. const char *OSXTarget = ::getenv("MACOSX_DEPLOYMENT_TARGET"); - const char *iPhoneOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"); + const char *iOSTarget = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"); + const char *iOSSimTarget = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET"); // Ignore empty strings. if (OSXTarget && OSXTarget[0] == '\0') OSXTarget = 0; - if (iPhoneOSTarget && iPhoneOSTarget[0] == '\0') - iPhoneOSTarget = 0; + if (iOSTarget && iOSTarget[0] == '\0') + iOSTarget = 0; + if (iOSSimTarget && iOSSimTarget[0] == '\0') + iOSSimTarget = 0; - // Diagnose conflicting deployment targets, and choose default platform - // based on the tool chain. + // Handle conflicting deployment targets // // FIXME: Don't hardcode default here. - if (OSXTarget && iPhoneOSTarget) { - // FIXME: We should see if we can get away with warning or erroring on - // this. Perhaps put under -pedantic? + + // Do not allow conflicts with the iOS simulator target. + if (iOSSimTarget && (OSXTarget || iOSTarget)) { + getDriver().Diag(clang::diag::err_drv_conflicting_deployment_targets) + << "IOS_SIMULATOR_DEPLOYMENT_TARGET" + << (OSXTarget ? "MACOSX_DEPLOYMENT_TARGET" : + "IPHONEOS_DEPLOYMENT_TARGET"); + } + + // Allow conflicts among OSX and iOS for historical reasons, but choose the + // default platform. + if (OSXTarget && iOSTarget) { if (getTriple().getArch() == llvm::Triple::arm || getTriple().getArch() == llvm::Triple::thumb) OSXTarget = 0; else - iPhoneOSTarget = 0; + iOSTarget = 0; } if (OSXTarget) { const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget); Args.append(OSXVersion); - } else if (iPhoneOSTarget) { + } else if (iOSTarget) { const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); - iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget); - Args.append(iPhoneVersion); + iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget); + Args.append(iOSVersion); + } else if (iOSSimTarget) { + const Option *O = Opts.getOption( + options::OPT_mios_simulator_version_min_EQ); + iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget); + Args.append(iOSSimVersion); } else { // Otherwise, assume we are targeting OS X. const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); @@ -595,25 +464,44 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } + // Reject invalid architecture combinations. + if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 && + getTriple().getArch() != llvm::Triple::x86_64)) { + getDriver().Diag(clang::diag::err_drv_invalid_arch_for_deployment_target) + << getTriple().getArchName() << iOSSimVersion->getAsString(Args); + } + // Set the tool chain target information. unsigned Major, Minor, Micro; bool HadExtra; if (OSXVersion) { - assert(!iPhoneVersion && "Unknown target platform!"); + assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!"); if (!Driver::GetReleaseVersion(OSXVersion->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || - Major != 10 || Minor >= 10 || Micro >= 10) + Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(clang::diag::err_drv_invalid_version_number) << OSXVersion->getAsString(Args); } else { - assert(iPhoneVersion && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(iPhoneVersion->getValue(Args), Major, Minor, + const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; + assert(Version && "Unknown target platform!"); + if (!Driver::GetReleaseVersion(Version->getValue(Args), Major, Minor, Micro, HadExtra) || HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(clang::diag::err_drv_invalid_version_number) - << iPhoneVersion->getAsString(Args); + << Version->getAsString(Args); } - setTarget(iPhoneVersion, Major, Minor, Micro); + + bool IsIOSSim = bool(iOSSimVersion); + + // In GCC, the simulator historically was treated as being OS X in some + // contexts, like determining the link logic, despite generally being called + // with an iOS deployment target. For compatibility, we detect the + // simulator as iOS + x86, and treat it differently in a few contexts. + if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64)) + IsIOSSim = true; + + setTarget(/*IsIPhoneOS=*/ !OSXVersion, Major, Minor, Micro, IsIOSSim); } void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, @@ -716,9 +604,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // driver behavior; that isn't going to work in our model. We // use isDriverOption() as an approximation, although things // like -O4 are going to slip through. - if (!XarchArg || Index > Prev + 1 || - XarchArg->getOption().isDriverOption()) { - getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument) + if (!XarchArg || Index > Prev + 1) { + getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_with_args) + << A->getAsString(Args); + continue; + } else if (XarchArg->getOption().isDriverOption()) { + getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument_isdriver) << A->getAsString(Args); continue; } @@ -922,6 +813,11 @@ const char *Darwin::GetForcedPicModel() const { return 0; } +bool Darwin::SupportsProfiling() const { + // Profiling instrumentation is only supported on x86. + return getArchName() == "i386" || getArchName() == "x86_64"; +} + bool Darwin::SupportsObjCGC() const { // Garbage collection is supported everywhere except on iPhone OS. return !isTargetIPhoneOS(); @@ -939,7 +835,7 @@ Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const { Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) : ToolChain(Host, Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); } @@ -951,7 +847,8 @@ Generic_GCC::~Generic_GCC() { } Tool &Generic_GCC::SelectTool(const Compilation &C, - const JobAction &JA) const { + const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1039,7 +936,8 @@ const char *TCEToolChain::GetForcedPicModel() const { } Tool &TCEToolChain::SelectTool(const Compilation &C, - const JobAction &JA) const { + const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; Key = Action::AnalyzeJobClass; @@ -1065,7 +963,8 @@ OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/lib"); } -Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1089,7 +988,7 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::openbsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1115,7 +1014,8 @@ FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple) } } -Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1138,7 +1038,7 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::freebsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1157,16 +1057,16 @@ NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple) llvm::Triple::x86_64) Lib32 = true; - getProgramPaths().push_back(getDriver().Dir + "/../libexec"); - getProgramPaths().push_back("/usr/libexec"); - if (Lib32) { - getFilePaths().push_back("/usr/lib/i386"); - } else { - getFilePaths().push_back("/usr/lib"); + if (getDriver().UseStdLib) { + if (Lib32) + getFilePaths().push_back("=/usr/lib/i386"); + else + getFilePaths().push_back("=/usr/lib"); } } -Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1189,7 +1089,7 @@ Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::netbsd::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1206,7 +1106,8 @@ Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/gnu/lib/gcc/i686-pc-minix/4.4.3"); } -Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1221,7 +1122,7 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::minix::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1234,7 +1135,7 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple) : Generic_GCC(Host, Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); getFilePaths().push_back(getDriver().Dir + "/../lib"); @@ -1245,7 +1146,8 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple) } -Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1260,7 +1162,7 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::auroraux::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1277,16 +1179,22 @@ enum LinuxDistro { Exherbo, Fedora13, Fedora14, + Fedora15, + FedoraRawhide, OpenSuse11_3, + UbuntuHardy, + UbuntuIntrepid, UbuntuJaunty, UbuntuKarmic, UbuntuLucid, UbuntuMaverick, + UbuntuNatty, UnknownDistro }; static bool IsFedora(enum LinuxDistro Distro) { - return Distro == Fedora13 || Distro == Fedora14; + return Distro == Fedora13 || Distro == Fedora14 || + Distro == Fedora15 || Distro == FedoraRawhide; } static bool IsOpenSuse(enum LinuxDistro Distro) { @@ -1298,8 +1206,10 @@ static bool IsDebian(enum LinuxDistro Distro) { } static bool IsUbuntu(enum LinuxDistro Distro) { - return Distro == UbuntuLucid || Distro == UbuntuMaverick || - Distro == UbuntuJaunty || Distro == UbuntuKarmic; + return Distro == UbuntuHardy || Distro == UbuntuIntrepid || + Distro == UbuntuLucid || Distro == UbuntuMaverick || + Distro == UbuntuJaunty || Distro == UbuntuKarmic || + Distro == UbuntuNatty; } static bool IsDebianBased(enum LinuxDistro Distro) { @@ -1315,7 +1225,9 @@ static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { return true; } - if (Arch == llvm::Triple::x86 && IsDebianBased(Distro)) + if (Arch == llvm::Triple::ppc64) + return true; + if ((Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) && IsDebianBased(Distro)) return true; return false; } @@ -1327,24 +1239,35 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { llvm::SmallVector<llvm::StringRef, 8> Lines; Data.split(Lines, "\n"); for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) { - if (Lines[i] == "DISTRIB_CODENAME=maverick") - return UbuntuMaverick; - else if (Lines[i] == "DISTRIB_CODENAME=lucid") - return UbuntuLucid; + if (Lines[i] == "DISTRIB_CODENAME=hardy") + return UbuntuHardy; + else if (Lines[i] == "DISTRIB_CODENAME=intrepid") + return UbuntuIntrepid; else if (Lines[i] == "DISTRIB_CODENAME=jaunty") return UbuntuJaunty; else if (Lines[i] == "DISTRIB_CODENAME=karmic") return UbuntuKarmic; + else if (Lines[i] == "DISTRIB_CODENAME=lucid") + return UbuntuLucid; + else if (Lines[i] == "DISTRIB_CODENAME=maverick") + return UbuntuMaverick; + else if (Lines[i] == "DISTRIB_CODENAME=natty") + return UbuntuNatty; } return UnknownDistro; } if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { llvm::StringRef Data = File.get()->getBuffer(); - if (Data.startswith("Fedora release 14 (Laughlin)")) + if (Data.startswith("Fedora release 15")) + return Fedora15; + else if (Data.startswith("Fedora release 14")) return Fedora14; - else if (Data.startswith("Fedora release 13 (Goddard)")) + else if (Data.startswith("Fedora release 13")) return Fedora13; + else if (Data.startswith("Fedora release") && + Data.find("Rawhide") != llvm::StringRef::npos) + return FedoraRawhide; return UnknownDistro; } @@ -1384,7 +1307,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Suffix32 = "/32"; std::string Suffix64 = ""; - if (Arch == llvm::Triple::x86) + if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) Suffix64 = "/64"; std::string Lib32 = "lib"; @@ -1400,7 +1323,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Lib64 = "lib64"; std::string GccTriple = ""; - if (Arch == llvm::Triple::arm) { + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) && Exists) GccTriple = "arm-linux-gnueabi"; @@ -1423,6 +1346,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu", Exists) && Exists) GccTriple = "x86_64-manbo-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/x86_64-linux-gnu/gcc", + Exists) && Exists) + GccTriple = "x86_64-linux-gnu"; } else if (Arch == llvm::Triple::x86) { if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-linux-gnu", Exists) && Exists) GccTriple = "i686-linux-gnu"; @@ -1438,11 +1364,26 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) && Exists) GccTriple = "i586-suse-linux"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-slackware-linux", Exists) + && Exists) + GccTriple = "i486-slackware-linux"; + } else if (Arch == llvm::Triple::ppc) { + if (!llvm::sys::fs::exists("/usr/lib/powerpc-linux-gnu", Exists) && Exists) + GccTriple = "powerpc-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc-unknown-linux-gnu"; + } else if (Arch == llvm::Triple::ppc64) { + if (!llvm::sys::fs::exists("/usr/lib/gcc/powerpc64-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc64-unknown-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib64/gcc/powerpc64-unknown-linux-gnu", Exists) && Exists) + GccTriple = "powerpc64-unknown-linux-gnu"; } - const char* GccVersions[] = {"4.5.2", "4.5.1", "4.5", "4.4.5", "4.4.4", - "4.4.3", "4.4", "4.3.4", "4.3.3", "4.3.2", - "4.3"}; + const char* GccVersions[] = {"4.6.0", + "4.5.2", "4.5.1", "4.5", + "4.4.5", "4.4.4", "4.4.3", "4.4", + "4.3.4", "4.3.3", "4.3.2", "4.3", + "4.2.4", "4.2.3", "4.2.2", "4.2.1", "4.2"}; std::string Base = ""; for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) { std::string Suffix = GccTriple + "/" + GccVersions[i]; @@ -1456,10 +1397,15 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Base = t2; break; } + std::string t3 = "/usr/lib/" + GccTriple + "/gcc/" + Suffix; + if (!llvm::sys::fs::exists(t3 + "/crtbegin.o", Exists) && Exists) { + Base = t3; + break; + } } path_list &Paths = getFilePaths(); - bool Is32Bits = getArch() == llvm::Triple::x86; + bool Is32Bits = (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::ppc); std::string Suffix; std::string Lib; @@ -1485,10 +1431,10 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) ExtraOpts.push_back("relro"); } - if (Arch == llvm::Triple::arm) + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); - if (IsFedora(Distro) || Distro == UbuntuMaverick) + if (IsFedora(Distro) || Distro == UbuntuMaverick || Distro == UbuntuNatty) ExtraOpts.push_back("--hash-style=gnu"); if (IsDebian(Distro) || Distro == UbuntuLucid || Distro == UbuntuJaunty || @@ -1500,7 +1446,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (Distro == DebianSqueeze || IsOpenSuse(Distro) || IsFedora(Distro) || Distro == UbuntuLucid || Distro == UbuntuMaverick || - Distro == UbuntuKarmic) + Distro == UbuntuKarmic || Distro == UbuntuNatty) ExtraOpts.push_back("--build-id"); if (Distro == ArchLinux) @@ -1527,7 +1473,8 @@ bool Linux::HasNativeLLVMSupport() const { return true; } -Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1550,7 +1497,7 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::linuxtools::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1564,7 +1511,7 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) // Path mangling to find libexec getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); getFilePaths().push_back(getDriver().Dir + "/../lib"); @@ -1572,7 +1519,8 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) getFilePaths().push_back("/usr/lib/gcc41"); } -Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; @@ -1587,7 +1535,7 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { case Action::LinkJobClass: T = new tools::dragonfly::Link(*this); break; default: - T = &Generic_GCC::SelectTool(C, JA); + T = &Generic_GCC::SelectTool(C, JA, Inputs); } } @@ -1598,7 +1546,8 @@ Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple) : ToolChain(Host, Triple) { } -Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA) const { +Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { Action::ActionClass Key; if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) Key = Action::AnalyzeJobClass; diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index 0e3645c..7a1a050 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -33,7 +33,8 @@ public: Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple); ~Generic_GCC(); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsUnwindTablesDefault() const; virtual const char *GetDefaultRelocationModel() const; @@ -56,10 +57,13 @@ private: // the argument translation business. mutable bool TargetInitialized; - /// Whether we are targetting iPhoneOS target. + /// Whether we are targeting iPhoneOS target. mutable bool TargetIsIPhoneOS; - /// The OS version we are targetting. + /// Whether we are targeting the iPhoneOS simulator target. + mutable bool TargetIsIPhoneOSSimulator; + + /// The OS version we are targeting. mutable unsigned TargetVersion[3]; /// The default macosx-version-min of this tool chain; empty until @@ -80,18 +84,22 @@ public: // FIXME: Eliminate these ...Target functions and derive separate tool chains // for these targets and put version in constructor. - void setTarget(bool isIPhoneOS, unsigned Major, unsigned Minor, - unsigned Micro) const { + void setTarget(bool IsIPhoneOS, unsigned Major, unsigned Minor, + unsigned Micro, bool IsIOSSim) const { + assert((!IsIOSSim || IsIPhoneOS) && "Unexpected deployment target!"); + // FIXME: For now, allow reinitialization as long as values don't // change. This will go away when we move away from argument translation. - if (TargetInitialized && TargetIsIPhoneOS == isIPhoneOS && + if (TargetInitialized && TargetIsIPhoneOS == IsIPhoneOS && + TargetIsIPhoneOSSimulator == IsIOSSim && TargetVersion[0] == Major && TargetVersion[1] == Minor && TargetVersion[2] == Micro) return; assert(!TargetInitialized && "Target already initialized!"); TargetInitialized = true; - TargetIsIPhoneOS = isIPhoneOS; + TargetIsIPhoneOS = IsIPhoneOS; + TargetIsIPhoneOSSimulator = IsIOSSim; TargetVersion[0] = Major; TargetVersion[1] = Minor; TargetVersion[2] = Micro; @@ -102,6 +110,11 @@ public: return TargetIsIPhoneOS; } + bool isTargetIOSSimulator() const { + assert(TargetInitialized && "Target not initialized!"); + return TargetIsIPhoneOSSimulator; + } + bool isTargetInitialized() const { return TargetInitialized; } void getTargetVersion(unsigned (&Res)[3]) const { @@ -160,7 +173,8 @@ public: virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const; - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsBlocksDefault() const { // Always allow blocks on Darwin; users interested in versioning are @@ -212,6 +226,8 @@ public: virtual const char *GetDefaultRelocationModel() const; virtual const char *GetForcedPicModel() const; + virtual bool SupportsProfiling() const; + virtual bool SupportsObjCGC() const; virtual bool UseDwarfDebugFlags() const; @@ -244,29 +260,6 @@ public: /// } }; -/// DarwinGCC - The Darwin toolchain used by GCC. -class LLVM_LIBRARY_VISIBILITY DarwinGCC : public Darwin { - /// GCC version to use. - unsigned GCCVersion[3]; - - /// The directory suffix for this tool chain. - std::string ToolChainDir; - -public: - DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple); - - /// @name Darwin ToolChain Implementation - /// { - - virtual void AddLinkSearchPathArgs(const ArgList &Args, - ArgStringList &CmdArgs) const; - - virtual void AddLinkRuntimeLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const; - - /// } -}; - /// Darwin_Generic_GCC - Generic Darwin tool chain using gcc. class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC { public: @@ -294,42 +287,48 @@ class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { public: AuroraUX(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF { public: OpenBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF { public: FreeBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF { public: NetBSD(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY Minix : public Generic_GCC { public: Minix(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF { public: DragonFly(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { @@ -338,7 +337,8 @@ public: virtual bool HasNativeLLVMSupport() const; - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; std::string Linker; std::vector<std::string> ExtraOpts; @@ -352,7 +352,8 @@ public: TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple); ~TCEToolChain(); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; bool IsMathErrnoDefault() const; bool IsUnwindTablesDefault() const; const char* GetDefaultRelocationModel() const; @@ -369,7 +370,8 @@ class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { public: Windows(const HostInfo &Host, const llvm::Triple& Triple); - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; virtual bool IsIntegratedAssemblerDefault() const; virtual bool IsUnwindTablesDefault() const; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index a2c95fc..7b78cd5 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -34,14 +34,32 @@ #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; +/// FindTargetProgramPath - Return path of the target specific version of +/// ProgName. If it doesn't exist, return path of ProgName itself. +static std::string FindTargetProgramPath(const ToolChain &TheToolChain, + const char *ProgName) { + std::string Executable(TheToolChain.getTripleString() + "-" + ProgName); + std::string Path(TheToolChain.GetProgramPath(Executable.c_str())); + if (Path != Executable) + return Path; + return TheToolChain.GetProgramPath(ProgName); +} + /// CheckPreprocessingOptions - Perform some validation of preprocessing /// arguments that is shared with gcc. static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) - if (!Args.hasArg(options::OPT_E)) + if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP) D.Diag(clang::diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; } @@ -309,7 +327,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, } } -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. +/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. // // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, @@ -363,6 +381,8 @@ static const char *getARMTargetCPU(const ArgList &Args, return "iwmmxt"; if (MArch == "xscale") return "xscale"; + if (MArch == "armv6m" || MArch == "armv6-m") + return "cortex-m0"; // If all else failed, return the most base CPU LLVM supports. return "arm7tdmi"; @@ -420,10 +440,17 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { } void Clang::AddARMTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { + ArgStringList &CmdArgs, + bool KernelOrKext) const { const Driver &D = getToolChain().getDriver(); llvm::Triple Triple = getToolChain().getTriple(); + // Disable movt generation, if requested. +#ifdef DISABLE_ARM_DARWIN_USE_MOVT + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-darwin-use-movt=0"); +#endif + // Select the ABI to use. // // FIXME: Support -meabi. @@ -577,6 +604,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } else D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); } + + // Setting -msoft-float effectively disables NEON because of the GCC + // implementation, although the same isn't true of VFP or VFP3. + if (FloatABI == "soft") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } + + // Kernel code has more strict alignment requirements. + if (KernelOrKext) { + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-long-calls"); + + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-strict-align"); + + // The kext linker doesn't know how to deal with movw/movt. +#ifndef DISABLE_ARM_DARWIN_USE_MOVT + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-darwin-use-movt=0"); +#endif + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -726,12 +775,12 @@ void Clang::AddX86TargetArgs(const ArgList &Args, CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; - } else if (getToolChain().getOS().startswith("netbsd")) { + } else if (getToolChain().getOS().startswith("freebsd")) { if (getToolChain().getArchName() == "x86_64") CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; - } else if (getToolChain().getOS().startswith("freebsd")) { + } else if (getToolChain().getOS().startswith("netbsd")) { if (getToolChain().getArchName() == "x86_64") CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") @@ -767,34 +816,112 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } -static bool needsExceptions(const ArgList &Args, types::ID InputType, - const llvm::Triple &Triple) { - // Handle -fno-exceptions. +static bool +shouldUseExceptionTablesForObjCExceptions(const ArgList &Args, + const llvm::Triple &Triple) { + // We use the zero-cost exception tables for Objective-C if the non-fragile + // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and + // later. + + if (Args.hasArg(options::OPT_fobjc_nonfragile_abi)) + return true; + + if (Triple.getOS() != llvm::Triple::Darwin) + return false; + + return (Triple.getDarwinMajorNumber() >= 9 && + (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::arm)); +} + +/// addExceptionArgs - Adds exception related arguments to the driver command +/// arguments. There's a master flag, -fexceptions and also language specific +/// flags to enable/disable C++ and Objective-C exceptions. +/// This makes it possible to for example disable C++ exceptions but enable +/// Objective-C exceptions. +static void addExceptionArgs(const ArgList &Args, types::ID InputType, + const llvm::Triple &Triple, + bool KernelOrKext, bool IsRewriter, + ArgStringList &CmdArgs) { + if (KernelOrKext) + return; + + // Exceptions are enabled by default. + bool ExceptionsEnabled = true; + + // This keeps track of whether exceptions were explicitly turned on or off. + bool DidHaveExplicitExceptionFlag = false; + if (Arg *A = Args.getLastArg(options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) - return true; - else - return false; + ExceptionsEnabled = true; + else + ExceptionsEnabled = false; + + DidHaveExplicitExceptionFlag = true; } - // Otherwise, C++ inputs use exceptions. - if (types::isCXX(InputType)) - return true; + bool ShouldUseExceptionTables = false; - // As do Objective-C non-fragile ABI inputs and all Objective-C inputs on - // x86_64 and ARM after SnowLeopard. - if (types::isObjC(InputType)) { - if (Args.hasArg(options::OPT_fobjc_nonfragile_abi)) - return true; - if (Triple.getOS() != llvm::Triple::Darwin) - return false; - return (Triple.getDarwinMajorNumber() >= 9 && - (Triple.getArch() == llvm::Triple::x86_64 || - Triple.getArch() == llvm::Triple::arm)); + // Exception tables and cleanups can be enabled with -fexceptions even if the + // language itself doesn't support exceptions. + if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) + ShouldUseExceptionTables = true; + + // Obj-C exceptions are enabled by default, regardless of -fexceptions. This + // is not necessarily sensible, but follows GCC. + if (types::isObjC(InputType) && + Args.hasFlag(options::OPT_fobjc_exceptions, + options::OPT_fno_objc_exceptions, + true)) { + CmdArgs.push_back("-fobjc-exceptions"); + + ShouldUseExceptionTables |= + shouldUseExceptionTablesForObjCExceptions(Args, Triple); } - return false; + if (types::isCXX(InputType)) { + bool CXXExceptionsEnabled = ExceptionsEnabled; + + if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, + options::OPT_fno_cxx_exceptions, + options::OPT_fexceptions, + options::OPT_fno_exceptions)) { + if (A->getOption().matches(options::OPT_fcxx_exceptions)) + CXXExceptionsEnabled = true; + else if (A->getOption().matches(options::OPT_fno_cxx_exceptions)) + CXXExceptionsEnabled = false; + } + + if (CXXExceptionsEnabled) { + CmdArgs.push_back("-fcxx-exceptions"); + + ShouldUseExceptionTables = true; + } + } + + if (ShouldUseExceptionTables) + CmdArgs.push_back("-fexceptions"); +} + +static bool ShouldDisableCFI(const ArgList &Args, + const ToolChain &TC) { + + // 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; } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -837,8 +964,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_O_Group)) IsOpt = !A->getOption().matches(options::OPT_O0); if (Args.hasFlag(options::OPT_mrelax_all, - options::OPT_mno_relax_all, - !IsOpt)) + options::OPT_mno_relax_all, + !IsOpt)) CmdArgs.push_back("-mrelax-all"); // When using an integrated assembler, translate -Wa, and -Xassembler @@ -855,10 +982,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. } else if (Value == "-L") { - // We don't support -L yet, but it isn't important enough to error - // on. No one should really be using it for a semantic change. - D.Diag(clang::diag::warn_drv_unsupported_option_argument) - << A->getOption().getName() << Value; + CmdArgs.push_back("-msave-temp-labels"); } else { D.Diag(clang::diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -925,29 +1049,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Treat blocks as analysis entry points. CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); + CmdArgs.push_back("-analyzer-eagerly-assume"); + // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { - types::ID InputType = Inputs[0].getType(); - - // Checks to perform for all language types. - 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=macosx"); - - // Checks to perform for Objective-C/Objective-C++. - if (types::isObjC(InputType)) { - // Enable all checkers in 'cocoa' package. - CmdArgs.push_back("-analyzer-checker=cocoa"); - } - // NOTE: Leaving -analyzer-check-objc-mem here is intentional. - // It also checks C code. - CmdArgs.push_back("-analyzer-check-objc-mem"); - - CmdArgs.push_back("-analyzer-eagerly-assume"); + if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) + CmdArgs.push_back("-analyzer-checker=osx"); } // Set the output format. The default is plist, for (lame) historical @@ -1011,7 +1125,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) - CmdArgs.push_back("-no-merge-all-constants"); + CmdArgs.push_back("-fno-merge-all-constants"); // LLVM Code Generator Options. @@ -1020,6 +1134,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + 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)) @@ -1054,6 +1171,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin) CmdArgs.push_back("-mconstructor-aliases"); + // Darwin's kernel doesn't support guard variables; just die if we + // try to use them. + if (KernelOrKext && + getToolChain().getTriple().getOS() == llvm::Triple::Darwin) + CmdArgs.push_back("-fforbid-guard-variables"); + if (Args.hasArg(options::OPT_mms_bitfields)) { CmdArgs.push_back("-mms-bitfields"); } @@ -1090,7 +1213,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::arm: case llvm::Triple::thumb: - AddARMTargetArgs(Args, CmdArgs); + AddARMTargetArgs(Args, CmdArgs, KernelOrKext); break; case llvm::Triple::mips: @@ -1155,6 +1278,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); + if (D.CCLogDiagnostics) { + CmdArgs.push_back("-diagnostic-log-file"); + CmdArgs.push_back(D.CCLogDiagnosticsFilename ? + D.CCLogDiagnosticsFilename : "-"); + } + // Special case debug options to only pass -g to clang. This is // wrong. Args.ClaimAllArgs(options::OPT_g_Group); @@ -1167,6 +1296,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); + if (Args.hasArg(options::OPT_ftest_coverage) || + Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back("-femit-coverage-notes"); + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back("-femit-coverage-data"); + Args.AddLastArg(CmdArgs, options::OPT_nostdinc); Args.AddLastArg(CmdArgs, options::OPT_nostdincxx); Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc); @@ -1192,10 +1328,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (A->getOption().matches(options::OPT_O) && A->getValue(Args)[0] == '\0') CmdArgs.push_back("-O2"); - else if (A->getOption().matches(options::OPT_O) && - A->getValue(Args)[0] == 'z' && - A->getValue(Args)[1] == '\0') - CmdArgs.push_back("-Os"); else A->render(Args, CmdArgs); } @@ -1236,6 +1368,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_trigraphs); } + // Map the bizarre '-Wwrite-strings' flag to a more sensible + // '-fconst-strings'; this better indicates its actual behavior. + if (Args.hasFlag(options::OPT_Wwrite_strings, options::OPT_Wno_write_strings, + false)) { + // For perfect compatibility with GCC, we do this even in the presence of + // '-w'. This flag names something other than a warning for GCC. + CmdArgs.push_back("-fconst-strings"); + } + + // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active + // during C++ compilation, which it is by default. GCC keeps this define even + // in the presence of '-w', match this behavior bug-for-bug. + if (types::isCXX(InputType) && + Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated, + true)) { + CmdArgs.push_back("-fdeprecated-macro"); + } + // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'. if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) { if (Asm->getOption().matches(options::OPT_fasm)) @@ -1244,6 +1394,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } + if (ShouldDisableCFI(Args, getToolChain())) + CmdArgs.push_back("-fno-dwarf2-cfi-asm"); + if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) { CmdArgs.push_back("-ftemplate-depth"); CmdArgs.push_back(A->getValue(Args)); @@ -1317,7 +1470,8 @@ 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_pg); + if (getToolChain().SupportsProfiling()) + Args.AddLastArg(CmdArgs, options::OPT_pg); // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, @@ -1354,7 +1508,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - Args.AddLastArg(CmdArgs, options::OPT_fwrapv); + // Forward -ftrap_function= options to the backend. + if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { + llvm::StringRef FuncName = A->getValue(Args); + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back(Args.MakeArgString("-trap-func=" + FuncName)); + } + + // -fno-strict-overflow implies -fwrapv if it isn't disabled, but + // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. + if (Arg *A = Args.getLastArg(options::OPT_fwrapv, + options::OPT_fno_wrapv)) { + if (A->getOption().matches(options::OPT_fwrapv)) + CmdArgs.push_back("-fwrapv"); + } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow, + options::OPT_fno_strict_overflow)) { + if (A->getOption().matches(options::OPT_fno_strict_overflow)) + CmdArgs.push_back("-fwrapv"); + } Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops); @@ -1395,7 +1566,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, - getToolChain().IsBlocksDefault())) { + getToolChain().IsBlocksDefault()) || + (Args.hasArg(options::OPT_fgnu_runtime) && + Args.hasArg(options::OPT_fobjc_nonfragile_abi) && + !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); } @@ -1411,10 +1585,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fno-elide-constructors"); - // -fexceptions=0 is default. - if (!KernelOrKext && - needsExceptions(Args, InputType, getToolChain().getTriple())) - CmdArgs.push_back("-fexceptions"); + // Add exception args. + addExceptionArgs(Args, InputType, getToolChain().getTriple(), + KernelOrKext, IsRewriter, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -1469,6 +1642,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); + // -fno-delayed-template-parsing is default. + if (Args.hasFlag(options::OPT_fdelayed_template_parsing, + options::OPT_fno_delayed_template_parsing, + false)) + CmdArgs.push_back("-fdelayed-template-parsing"); + // -fgnu-keywords default varies depending on language; only pass if // specified. if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords, @@ -1545,17 +1724,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + // FIXME: Don't expose -fobjc-default-synthesize-properties as a top-level + // driver flag yet. This feature is still under active development + // and shouldn't be exposed as a user visible feature (which may change). + // Clang still supports this as a -cc1 option for development and testing. +#if 0 // -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())) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } - - // -fno-objc-exceptions is default. - if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions, - options::OPT_fno_objc_exceptions)) - CmdArgs.push_back("-fobjc-exceptions"); +#endif } if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, @@ -1619,6 +1799,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info, 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, @@ -1631,6 +1816,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg( + options::OPT_fdiagnostics_show_note_include_stack, + options::OPT_fno_diagnostics_show_note_include_stack)) { + if (A->getOption().matches( + options::OPT_fdiagnostics_show_note_include_stack)) + CmdArgs.push_back("-fdiagnostics-show-note-include-stack"); + else + CmdArgs.push_back("-fno-diagnostics-show-note-include-stack"); + } + // Color diagnostics are the default, unless the terminal doesn't support // them. if (Args.hasFlag(options::OPT_fcolor_diagnostics, @@ -1686,9 +1881,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } #endif + // Only allow -traditional or -traditional-cpp outside in preprocessing modes. if (Arg *A = Args.getLastArg(options::OPT_traditional, - options::OPT_traditional_cpp)) - D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + options::OPT_traditional_cpp)) { + if (isa<PreprocessJobAction>(JA)) + CmdArgs.push_back("-traditional-cpp"); + else + D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + } Args.AddLastArg(CmdArgs, options::OPT_dM); Args.AddLastArg(CmdArgs, options::OPT_dD); @@ -1768,6 +1968,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // care to warn the user about. Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group); Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group); + + // Disable warnings for clang -E -use-gold-plugin -emit-llvm foo.c + Args.ClaimAllArgs(options::OPT_use_gold_plugin); + Args.ClaimAllArgs(options::OPT_emit_llvm); } void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, @@ -1782,6 +1986,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Don't warn about "clang -w -c foo.s" Args.ClaimAllArgs(options::OPT_w); + // and "clang -emit-llvm -c foo.s" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and "clang -use-gold-plugin -c foo.s" + Args.ClaimAllArgs(options::OPT_use_gold_plugin); // Invoke ourselves in -cc1as mode. // @@ -1807,7 +2015,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, !IsOpt)) CmdArgs.push_back("-relax-all"); - // FIXME: Add -force_cpusubtype_ALL support, once we have it. + // Ignore explicit -force_cpusubtype_ALL option. + (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); // FIXME: Add -g support, once we have it. @@ -1815,6 +2024,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); + Args.AddAllArgs(CmdArgs, options::OPT_mllvm); assert(Output.isFilename() && "Unexpected lipo output."); CmdArgs.push_back("-o"); @@ -1930,7 +2140,20 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, } } - const char *GCCName = getToolChain().getDriver().getCCCGenericGCCName().c_str(); + const std::string customGCCName = D.getCCCGenericGCCName(); + const char *GCCName; + 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"; + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); @@ -2044,10 +2267,6 @@ void darwin::CC1::AddCC1Args(const ArgList &Args, CmdArgs.push_back("-fno-builtin-strcpy"); } - // gcc has some code here to deal with when no -mmacosx-version-min - // and no -miphoneos-version-min is present, but this never happens - // due to tool chain specific argument translation. - if (Args.hasArg(options::OPT_g_Flag) && !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols)) CmdArgs.push_back("-feliminate-unused-debug-symbols"); @@ -2111,7 +2330,8 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, if (Args.hasArg(options::OPT_v)) CmdArgs.push_back("-version"); - if (Args.hasArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_pg) && + getToolChain().SupportsProfiling()) CmdArgs.push_back("-p"); Args.AddLastArg(CmdArgs, options::OPT_p); @@ -2134,6 +2354,9 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &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"); @@ -2191,6 +2414,9 @@ void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, // 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"); @@ -2322,7 +2548,7 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, OutputArgs.push_back("-o"); OutputArgs.push_back(Output.getFilename()); - if (Args.hasArg(options::OPT_E)) { + if (Args.hasArg(options::OPT_E) || getToolChain().getDriver().CCCIsCPP) { AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs); } else { AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); @@ -2442,11 +2668,16 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, assert(Inputs.size() == 1 && "Unexpected number of inputs."); const InputInfo &Input = Inputs[0]; - // Bit of a hack, this is only used for original inputs. - // - // FIXME: This is broken for preprocessed .s inputs. - if (Input.isFilename() && - strcmp(Input.getFilename(), Input.getBaseInput()) == 0) { + // 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) { if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); else if (Args.hasArg(options::OPT_g_Group)) @@ -2502,6 +2733,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); + const toolchains::Darwin &DarwinTC = getDarwinToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { @@ -2521,7 +2753,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // 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) && - !getDarwinToolChain().isTargetIPhoneOS()) { + !DarwinTC.isTargetIPhoneOS()) { // Don't pass -demangle to ld_classic. // // FIXME: This is a temporary workaround, ld should be handling this. @@ -2596,7 +2828,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_all__load); Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); - if (getDarwinToolChain().isTargetIPhoneOS()) + if (DarwinTC.isTargetIPhoneOS()) Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); Args.AddLastArg(CmdArgs, options::OPT_dead__strip); Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); @@ -2608,15 +2840,27 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_image__base); Args.AddAllArgs(CmdArgs, options::OPT_init); - // Adding all arguments doesn't make sense here but this is what gcc does. One - // of this should always be present thanks to argument translation. - assert((Args.hasArg(options::OPT_mmacosx_version_min_EQ) || - Args.hasArg(options::OPT_miphoneos_version_min_EQ)) && - "Missing version argument (lost in translation)?"); - Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ, - "-macosx_version_min"); - Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ, - "-iphoneos_version_min"); + // Add the deployment target. + unsigned TargetVersion[3]; + DarwinTC.getTargetVersion(TargetVersion); + + // If we had an explicit -mios-simulator-version-min argument, honor that, + // otherwise use the traditional deployment targets. We can't just check the + // is-sim attribute because existing code follows this path, and the linker + // may not handle the argument. + // + // FIXME: We may be able to remove this, once we can verify no one depends on + // it. + if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) + CmdArgs.push_back("-ios_simulator_version_min"); + else if (DarwinTC.isTargetIPhoneOS()) + CmdArgs.push_back("-iphoneos_version_min"); + else + CmdArgs.push_back("-macosx_version_min"); + CmdArgs.push_back(Args.MakeArgString(llvm::Twine(TargetVersion[0]) + "." + + llvm::Twine(TargetVersion[1]) + "." + + llvm::Twine(TargetVersion[2]))); + Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); Args.AddLastArg(CmdArgs, options::OPT_single__module); @@ -2722,7 +2966,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // Derived from startfile spec. if (Args.hasArg(options::OPT_dynamiclib)) { // Derived from darwin_dylib1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-ldylib1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-ldylib1.o"); } else { @@ -2735,7 +2982,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_bundle)) { if (!Args.hasArg(options::OPT_static)) { // Derived from darwin_bundle1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-lbundle1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lbundle1.o"); } else { @@ -2744,7 +2994,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, } } } else { - if (Args.hasArg(options::OPT_pg)) { + if (Args.hasArg(options::OPT_pg) && + getToolChain().SupportsProfiling()) { if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || Args.hasArg(options::OPT_preload)) { @@ -2761,7 +3012,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lcrt0.o"); } else { // Derived from darwin_crt1 spec. - if (getDarwinToolChain().isTargetIPhoneOS()) { + if (getDarwinToolChain().isTargetIOSSimulator()) { + // The simulator doesn't have a versioned crt1 file. + CmdArgs.push_back("-lcrt1.o"); + } else if (getDarwinToolChain().isTargetIPhoneOS()) { if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lcrt1.o"); else @@ -3156,6 +3410,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { @@ -3206,12 +3463,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); - const ToolChain::path_list Paths = getToolChain().getFilePaths(); for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); - Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -3323,8 +3578,8 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), + "as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3336,6 +3591,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { @@ -3434,8 +3692,8 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, "crtn.o"))); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(FindTargetProgramPath(getToolChain(), + "ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -3487,14 +3745,14 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, // 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 -g foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) { - CmdArgs.push_back("--sysroot"); - CmdArgs.push_back(A->getValue(Args)); - } + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back("-pie"); @@ -3517,13 +3775,19 @@ 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::arm) + else if (ToolChain.getArch() == llvm::Triple::arm + || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("armelf_linux_eabi"); + else if (ToolChain.getArch() == llvm::Triple::ppc) + CmdArgs.push_back("elf32ppclinux"); + else if (ToolChain.getArch() == llvm::Triple::ppc64) + CmdArgs.push_back("elf64ppc"); else CmdArgs.push_back("elf_x86_64"); if (Args.hasArg(options::OPT_static)) { - if (ToolChain.getArch() == llvm::Triple::arm) + if (ToolChain.getArch() == llvm::Triple::arm + || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("-Bstatic"); else CmdArgs.push_back("-static"); @@ -3532,13 +3796,19 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, } if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::thumb || (!Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-dynamic-linker"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("/lib/ld-linux.so.2"); - else if (ToolChain.getArch() == llvm::Triple::arm) + 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::ppc) + CmdArgs.push_back("/lib/ld.so.1"); + else if (ToolChain.getArch() == llvm::Triple::ppc64) + CmdArgs.push_back("/lib64/ld64.so.1"); else CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2"); } @@ -3573,6 +3843,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); + for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); i != e; ++i) CmdArgs.push_back(Args.MakeArgString(llvm::StringRef("-L") + *i)); @@ -3770,6 +4041,9 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index 10c8839..93abf75 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -34,7 +34,8 @@ namespace tools { const InputInfo &Output, const InputInfoList &Inputs) const; - void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs, + bool KernelOrKext) const; void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; |