diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
18 files changed, 1653 insertions, 353 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp index f34971b..549ce0a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp @@ -1,4 +1,4 @@ -//===--- Action.cpp - Abstract compilation steps ------------------------*-===// +//===--- Action.cpp - Abstract compilation steps --------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp index 83d0d26..f1177cf 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp @@ -1,4 +1,4 @@ -//===--- Arg.cpp - Argument Implementations -----------------------------*-===// +//===--- Arg.cpp - Argument Implementations -------------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp index 9101523..596e2a7 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp @@ -1,4 +1,4 @@ -//===--- ArgList.cpp - Argument List Management -------------------------*-===// +//===--- ArgList.cpp - Argument List Management ---------------------------===// // // The LLVM Compiler Infrastructure // @@ -55,62 +55,59 @@ Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { } Arg *ArgList::getLastArg(OptSpecifier Id) const { - Arg *A = getLastArgNoClaim(Id); - if (A) - A->claim(); - return A; + Arg *Res = 0; + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { + if ((*it)->getOption().matches(Id)) { + Res = *it; + Res->claim(); + } + } + + return Res; } Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const { Arg *Res = 0; - for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1)) { Res = *it; - break; + Res->claim(); + } } - if (Res) - Res->claim(); - return Res; } Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { Arg *Res = 0; - for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) || (*it)->getOption().matches(Id2)) { Res = *it; - break; + Res->claim(); } } - if (Res) - Res->claim(); - return Res; } Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, OptSpecifier Id3) const { Arg *Res = 0; - for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) { + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { if ((*it)->getOption().matches(Id0) || (*it)->getOption().matches(Id1) || (*it)->getOption().matches(Id2) || (*it)->getOption().matches(Id3)) { Res = *it; - break; + Res->claim(); } } - if (Res) - Res->claim(); - return Res; } @@ -214,7 +211,8 @@ const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, // -InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd) +InputArgList::InputArgList(const char* const *ArgBegin, + const char* const *ArgEnd) : NumInputArgStrings(ArgEnd - ArgBegin) { ArgStrings.append(ArgBegin, ArgEnd); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index c059afd..5619212 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -1,4 +1,4 @@ -//===--- Compilation.cpp - Compilation Task Implementation --------------*-===// +//===--- Compilation.cpp - Compilation Task Implementation ----------------===// // // The LLVM Compiler Infrastructure // @@ -17,7 +17,7 @@ #include "clang/Driver/ToolChain.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Program.h" +#include "llvm/Support/Program.h" #include <sys/stat.h> #include <errno.h> using namespace clang::driver; @@ -101,21 +101,15 @@ bool Compilation::CleanupFileList(const ArgStringList &Files, llvm::sys::Path P(*it); std::string Error; - if (!P.isRegularFile()) { - // If we have a special file in our list, i.e. /dev/null - // then don't call eraseFromDisk() and just continue. - continue; - } - if (P.eraseFromDisk(false, &Error)) { - // Failure is only failure if the file doesn't exist. There is a - // race condition here due to the limited interface of - // llvm::sys::Path, we want to know if the removal gave E_NOENT. + // Failure is only failure if the file exists and is "regular". There is + // a race condition here due to the limited interface of + // llvm::sys::Path, we want to know if the removal gave ENOENT. // FIXME: Grumble, P.exists() is broken. PR3837. struct stat buf; - if (::stat(P.c_str(), &buf) == 0 - || errno != ENOENT) { + if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG : + (errno != ENOENT)) { if (IssueErrors) getDriver().Diag(clang::diag::err_drv_unable_to_remove_file) << Error; diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index b8400aa..4b6aef6 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -1,4 +1,4 @@ -//===--- Driver.cpp - Clang GCC Compatible Driver -----------------------*-===// +//===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +#ifdef HAVE_CLANG_CONFIG_H +# include "clang/Config/config.h" +#endif + #include "clang/Driver/Driver.h" #include "clang/Driver/Action.h" @@ -30,13 +34,21 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" -#include "llvm/System/Program.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include "InputInfo.h" #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; @@ -50,8 +62,9 @@ Driver::Driver(llvm::StringRef _ClangExecutable, DefaultImageName(_DefaultImageName), DriverTitle("clang \"gcc-compatible\" driver"), Host(0), - CCCGenericGCCName("gcc"), CCPrintOptionsFilename(0), CCCIsCXX(false), + 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) { if (IsProduction) { @@ -69,16 +82,16 @@ Driver::Driver(llvm::StringRef _ClangExecutable, CCCUseClangCXX = false; } - llvm::sys::Path Executable(ClangExecutable); - Name = Executable.getBasename(); - Dir = Executable.getDirname(); + Name = llvm::sys::path::stem(ClangExecutable); + Dir = llvm::sys::path::parent_path(ClangExecutable); // Compute the path to the resource directory. - llvm::sys::Path P(Dir); - P.eraseComponent(); // Remove /bin from foo/bin - P.appendComponent("lib"); - P.appendComponent("clang"); - P.appendComponent(CLANG_VERSION_STRING); + llvm::StringRef ClangResourceDir(CLANG_RESOURCE_DIR); + llvm::SmallString<128> P(Dir); + if (ClangResourceDir != "") + llvm::sys::path::append(P, ClangResourceDir); + else + llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING); ResourceDir = P.str(); } @@ -115,6 +128,7 @@ InputArgList *Driver::ParseArgStrings(const char **ArgBegin, DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); + bool HasNostdlib = Args.hasArg(options::OPT_nostdlib); for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { const Arg *A = *it; @@ -157,6 +171,25 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { continue; } + // Rewrite reserved library names. + if (A->getOption().matches(options::OPT_l)) { + llvm::StringRef Value = A->getValue(Args); + + // Rewrite unless -nostdlib is present. + if (!HasNostdlib && Value == "stdc++") { + DAL->AddFlagArg(A, Opts->getOption( + options::OPT_Z_reserved_lib_stdcxx)); + continue; + } + + // Rewrite unconditionally. + if (Value == "cc_kext") { + DAL->AddFlagArg(A, Opts->getOption( + options::OPT_Z_reserved_lib_cckext)); + continue; + } + } + DAL->append(*it); } @@ -205,6 +238,13 @@ 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); @@ -241,8 +281,12 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { DefaultHostTriple = A->getValue(*Args); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) Dir = InstalledDir = A->getValue(*Args); - if (const Arg *A = Args->getLastArg(options::OPT_B)) - PrefixDir = A->getValue(*Args); + for (arg_iterator it = Args->filtered_begin(options::OPT_B), + ie = Args->filtered_end(); it != ie; ++it) { + const Arg *A = *it; + A->claim(); + PrefixDirs.push_back(A->getValue(*Args, 0)); + } Host = GetHostInfo(DefaultHostTriple.c_str()); @@ -287,7 +331,7 @@ int Driver::ExecuteCompilation(const Compilation &C) const { } // If there were errors building the compilation, quit now. - if (getDiags().getNumErrors()) + if (getDiags().hasErrorOccurred()) return 1; const Command *FailingCommand = 0; @@ -365,7 +409,7 @@ void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const { /// option. static void PrintDiagnosticCategories(llvm::raw_ostream &OS) { for (unsigned i = 1; // Skip the empty category. - const char *CategoryName = Diagnostic::getCategoryNameFromID(i); ++i) + const char *CategoryName = DiagnosticIDs::getCategoryNameFromID(i); ++i) OS << i << ',' << CategoryName << '\n'; } @@ -373,8 +417,19 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { // The order these options are handled in gcc is all over the place, but we // don't expect inconsistencies w.r.t. that to matter in practice. + if (C.getArgs().hasArg(options::OPT_dumpmachine)) { + llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n'; + return false; + } + if (C.getArgs().hasArg(options::OPT_dumpversion)) { - llvm::outs() << CLANG_VERSION_STRING "\n"; + // Since -dumpversion is only implemented for pedantic GCC compatibility, we + // return an answer which matches our definition of __VERSION__. + // + // If we want to return a more correct answer some day, then we should + // introduce a non-pedantically GCC compatible mode to Clang in which we + // provide sensible definitions for -dumpversion, __VERSION__, etc. + llvm::outs() << "4.2.1\n"; return false; } @@ -709,10 +764,20 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, } // Check that the file exists, if enabled. - if (CheckInputsExist && memcmp(Value, "-", 2) != 0 && - !llvm::sys::Path(Value).exists()) - Diag(clang::diag::err_drv_no_such_file) << A->getValue(Args); - else + if (CheckInputsExist && memcmp(Value, "-", 2) != 0) { + llvm::SmallString<64> Path(Value); + if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) + if (llvm::sys::path::is_absolute(Path.str())) { + Path = WorkDir->getValue(Args); + llvm::sys::path::append(Path, Value); + } + + bool exists = false; + if (/*error_code ec =*/llvm::sys::fs::exists(Value, exists) || !exists) + Diag(clang::diag::err_drv_no_such_file) << Path.str(); + else + Inputs.push_back(std::make_pair(Ty, A)); + } else Inputs.push_back(std::make_pair(Ty, A)); } else if (A->getOption().isLinkerInput()) { @@ -726,7 +791,7 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // Follow gcc behavior and treat as linker input for invalid -x // options. Its not clear why we shouldn't just revert to unknown; but - // this isn't very important, we might as well be bug comatible. + // this isn't very important, we might as well be bug compatible. if (!InputType) { Diag(clang::diag::err_drv_unknown_language) << A->getValue(Args); InputType = types::TY_Object; @@ -747,8 +812,7 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args, // -{E,M,MM} only run the preprocessor. if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_M)) || - (FinalPhaseArg = Args.getLastArg(options::OPT_MM))) { + (FinalPhaseArg = Args.getLastArg(options::OPT_M, options::OPT_MM))) { FinalPhase = phases::Preprocess; // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. @@ -856,7 +920,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, case phases::Preprocess: { types::ID OutputTy; // -{M, MM} alter the output type. - if (Args.hasArg(options::OPT_M) || Args.hasArg(options::OPT_MM)) { + if (Args.hasArg(options::OPT_M, options::OPT_MM)) { OutputTy = types::TY_Dependencies; } else { OutputTy = types::getPreprocessedType(Input->getType()); @@ -945,7 +1009,7 @@ void Driver::BuildJobs(Compilation &C) const { // If the user passed -Qunused-arguments or there were errors, don't warn // about any unused arguments. - if (Diags.getNumErrors() || + if (Diags.hasErrorOccurred() || C.getArgs().hasArg(options::OPT_Qunused_arguments)) return; @@ -1141,8 +1205,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } - llvm::sys::Path BasePath(BaseInput); - std::string BaseName(BasePath.getLast()); + llvm::SmallString<128> BasePath(BaseInput); + llvm::StringRef BaseName = llvm::sys::path::filename(BasePath); // Determine what the derived output name should be. const char *NamedOutput; @@ -1163,11 +1227,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C, // As an annoying special case, PCH generation doesn't strip the pathname. if (JA.getType() == types::TY_PCH) { - BasePath.eraseComponent(); - if (BasePath.isEmpty()) + llvm::sys::path::remove_filename(BasePath); + if (BasePath.empty()) BasePath = NamedOutput; else - BasePath.appendComponent(NamedOutput); + llvm::sys::path::append(BasePath, NamedOutput); return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str())); } else { return C.addResultFile(NamedOutput); @@ -1177,10 +1241,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when lokup up program paths. - if (!PrefixDir.empty()) { - llvm::sys::Path P(PrefixDir); + for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), + ie = PrefixDirs.end(); it != ie; ++it) { + llvm::sys::Path P(*it); P.appendComponent(Name); - if (P.exists()) + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) return P.str(); } @@ -1189,7 +1255,8 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { it = List.begin(), ie = List.end(); it != ie; ++it) { llvm::sys::Path P(*it); P.appendComponent(Name); - if (P.exists()) + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) return P.str(); } @@ -1200,10 +1267,13 @@ std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, bool WantFile) const { // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when lokup up program paths. - if (!PrefixDir.empty()) { - llvm::sys::Path P(PrefixDir); + for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), + ie = PrefixDirs.end(); it != ie; ++it) { + llvm::sys::Path P(*it); P.appendComponent(Name); - if (WantFile ? P.exists() : P.canExecute()) + bool Exists; + if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists + : P.canExecute()) return P.str(); } @@ -1212,7 +1282,9 @@ std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, it = List.begin(), ie = List.end(); it != ie; ++it) { llvm::sys::Path P(*it); P.appendComponent(Name); - if (WantFile ? P.exists() : P.canExecute()) + bool Exists; + if (WantFile ? !llvm::sys::fs::exists(P.str(), Exists) && Exists + : P.canExecute()) return P.str(); } @@ -1266,6 +1338,8 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { return createDragonFlyHostInfo(*this, Triple); case llvm::Triple::OpenBSD: return createOpenBSDHostInfo(*this, Triple); + case llvm::Triple::NetBSD: + return createNetBSDHostInfo(*this, Triple); case llvm::Triple::FreeBSD: return createFreeBSDHostInfo(*this, Triple); case llvm::Triple::Minix: @@ -1275,7 +1349,6 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { case llvm::Triple::Win32: return createWindowsHostInfo(*this, Triple); case llvm::Triple::MinGW32: - case llvm::Triple::MinGW64: return createMinGWHostInfo(*this, Triple); default: return createUnknownHostInfo(*this, Triple); diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp index 72aaf56..f2d9af8 100644 --- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp @@ -1,4 +1,4 @@ -//===--- DriverOptions.cpp - Driver Options Table -----------------------*-===// +//===--- DriverOptions.cpp - Driver Options Table -------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp index 7c5e430..cd413180 100644 --- a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp @@ -1,4 +1,4 @@ -//===--- HostInfo.cpp - Host specific information -----------------------*-===// +//===--- HostInfo.cpp - Host specific information -------------------------===// // // The LLVM Compiler Infrastructure // @@ -115,6 +115,7 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, // 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 || 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) { @@ -371,6 +372,65 @@ ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args, return TC; } +// NetBSD Host Info + +/// NetBSDHostInfo - NetBSD host information implementation. +class NetBSDHostInfo : public HostInfo { + /// Cache of tool chains we have created. + mutable llvm::StringMap<ToolChain*> ToolChains; + +public: + NetBSDHostInfo(const Driver &D, const llvm::Triple& Triple) + : HostInfo(D, Triple) {} + ~NetBSDHostInfo(); + + virtual bool useDriverDriver() const; + + virtual ToolChain *CreateToolChain(const ArgList &Args, + const char *ArchName) const; +}; + +NetBSDHostInfo::~NetBSDHostInfo() { + for (llvm::StringMap<ToolChain*>::iterator + it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) + delete it->second; +} + +bool NetBSDHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *NetBSDHostInfo::CreateToolChain(const ArgList &Args, + const char *ArchName) const { + assert(!ArchName && + "Unexpected arch name on platform without driver driver support."); + + // Automatically handle some instances of -m32/-m64 we know about. + std::string Arch = getArchName(); + ArchName = Arch.c_str(); + if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { + if (Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::x86_64) { + ArchName = + (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; + } else if (Triple.getArch() == llvm::Triple::ppc || + Triple.getArch() == llvm::Triple::ppc64) { + ArchName = + (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; + } + } + + ToolChain *&TC = ToolChains[ArchName]; + if (!TC) { + llvm::Triple TCTriple(getTriple()); + TCTriple.setArchName(ArchName); + + TC = new toolchains::NetBSD(*this, TCTriple); + } + + return TC; +} + // Minix Host Info /// MinixHostInfo - Minix host information implementation. @@ -623,6 +683,12 @@ clang::driver::createFreeBSDHostInfo(const Driver &D, } const HostInfo * +clang::driver::createNetBSDHostInfo(const Driver &D, + const llvm::Triple& Triple) { + return new NetBSDHostInfo(D, Triple); +} + +const HostInfo * clang::driver::createMinixHostInfo(const Driver &D, const llvm::Triple& Triple) { return new MinixHostInfo(D, Triple); diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp index fa7d060..51055e9 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp @@ -1,4 +1,4 @@ -//===--- Job.cpp - Command to Execute -----------------------------------*-===// +//===--- Job.cpp - Command to Execute -------------------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp index 3c36314..c3d3048 100644 --- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp @@ -1,4 +1,4 @@ -//===--- OptTable.cpp - Option Table Implementation ---------------------*-===// +//===--- OptTable.cpp - Option Table Implementation -----------------------===// // // The LLVM Compiler Infrastructure // @@ -226,7 +226,8 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const { return new Arg(TheUnknownOption, Index++, Str); } -InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd, +InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, + const char* const *ArgEnd, unsigned &MissingArgIndex, unsigned &MissingArgCount) const { InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp index 5396250..a992cef 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Option.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Option.cpp @@ -1,4 +1,4 @@ -//===--- Option.cpp - Abstract Driver Options ---------------------------*-===// +//===--- Option.cpp - Abstract Driver Options -----------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp index df4cdee..f360002 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp @@ -1,4 +1,4 @@ -//===--- Phases.cpp - Transformations on Driver Types -------------------*-===// +//===--- Phases.cpp - Transformations on Driver Types ---------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/Tool.cpp b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp index fe01531..b93864f 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tool.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp @@ -1,4 +1,4 @@ -//===--- Tool.cpp - Compilation Tools -----------------------------------*-===// +//===--- Tool.cpp - Compilation Tools -------------------------------------===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 94c1c6b..e4051a1 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -1,4 +1,4 @@ -//===--- ToolChain.cpp - Collections of tools for one platform ----------*-===// +//===--- ToolChain.cpp - Collections of tools for one platform ------------===// // // The LLVM Compiler Infrastructure // @@ -43,6 +43,10 @@ types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { return types::lookupTypeForExtension(Ext); } +bool ToolChain::HasNativeLLVMSupport() const { + return false; +} + /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. // // FIXME: tblgen this. @@ -174,3 +178,52 @@ std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const { return ComputeLLVMTriple(Args); } +ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ + if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { + llvm::StringRef Value = A->getValue(Args); + if (Value == "libc++") + return ToolChain::CST_Libcxx; + if (Value == "libstdc++") + return ToolChain::CST_Libstdcxx; + getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libstdcxx; +} + +void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CXXStdlibType Type = GetCXXStdlibType(Args); + + switch (Type) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-cxx-system-include"); + CmdArgs.push_back("/usr/include/c++/v1"); + break; + + case ToolChain::CST_Libstdcxx: + // Currently handled by the mass of goop in InitHeaderSearch. + break; + } +} + +void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CXXStdlibType Type = GetCXXStdlibType(Args); + + switch (Type) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + break; + + case ToolChain::CST_Libstdcxx: + CmdArgs.push_back("-lstdc++"); + break; + } +} + +void ToolChain::AddCCKextLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CmdArgs.push_back("-lcc_kext"); +} diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 596173d..8028fe0 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -1,4 +1,4 @@ -//===--- ToolChains.cpp - ToolChain Implementations ---------------------*-===// +//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// // // The LLVM Compiler Infrastructure // @@ -23,8 +23,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/system_error.h" #include <cstdlib> // ::getenv @@ -63,6 +66,10 @@ types::ID Darwin::LookupTypeForExtension(const char *Ext) const { return Ty; } +bool Darwin::HasNativeLLVMSupport() const { + return true; +} + // FIXME: Can we tablegen this? static const char *GetArmArchForMArch(llvm::StringRef Value) { if (Value == "armv6k") @@ -146,7 +153,8 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple) // Try the next major version if that tool chain dir is invalid. std::string Tmp = "/usr/lib/gcc/" + ToolChainDir; - if (!llvm::sys::Path(Tmp).exists()) { + bool Exists; + if (llvm::sys::fs::exists(Tmp, Exists) || Exists) { std::string Next = "i686-apple-darwin"; Next += llvm::utostr(DarwinVersion[0] + 1); Next += "/"; @@ -160,7 +168,7 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple) // // FIXME: Drop dependency on gcc's tool chain. Tmp = "/usr/lib/gcc/" + Next; - if (llvm::sys::Path(Tmp).exists()) + if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) ToolChainDir = Next; } @@ -305,19 +313,20 @@ void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args, CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir)); Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir; - if (llvm::sys::Path(Tmp).exists()) + 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::Path(Tmp).exists()) + 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::Path(Tmp).exists()) + if (!llvm::sys::fs::exists(Tmp, Exists) && Exists) CmdArgs.push_back(Args.MakeArgString("-L" + Tmp)); Tmp = getDriver().Dir + "/../lib"; - if (llvm::sys::Path(Tmp).exists()) + 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)); @@ -373,10 +382,30 @@ void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args, DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) : Darwin(Host, Triple) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + getProgramPaths().push_back(getDriver().Dir); + // We expect 'as', 'ld', etc. to be adjacent to our install dir. getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) 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. + std::string ToolChainDir = "i686-apple-darwin"; + ToolChainDir += llvm::utostr(DarwinVersion[0]); + ToolChainDir += "/4.2.1"; + + std::string Path = getDriver().Dir; + Path += "/../libexec/gcc/"; + Path += ToolChainDir; + getProgramPaths().push_back(Path); + + Path = "/usr/libexec/gcc/"; + Path += ToolChainDir; + getProgramPaths().push_back(Path); } void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, @@ -435,12 +464,14 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, if (ArchSpecificDir) { P.appendComponent(ArchSpecificDir); - if (P.exists()) + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) CmdArgs.push_back(Args.MakeArgString("-L" + P.str())); P.eraseComponent(); } - if (P.exists()) + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) CmdArgs.push_back(Args.MakeArgString("-L" + P.str())); } @@ -481,11 +512,20 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, else if (isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lgcc_s.10.5"); - // For OS X, we only need a static runtime library when targetting 10.4, to - // provide versions of the static functions which were omitted from - // 10.4.dylib. - if (isMacosxVersionLT(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 + // omitted from 10.4.dylib. + // + // Unfortunately, that turned out to not be true, because Darwin system + // headers can still use eprintf on i386, and it is not exported from + // libSystem. Therefore, we still must provide a runtime library just for + // the tiny tiny handful of projects that *might* use that symbol. + if (isMacosxVersionLT(10, 5)) { DarwinStaticLib = "libclang_rt.10.4.a"; + } else { + if (getTriple().getArch() == llvm::Triple::x86) + DarwinStaticLib = "libclang_rt.eprintf.a"; + } } /// Add the target specific static library, if needed. @@ -497,10 +537,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build. - if (!P.exists()) - getDriver().Diag(clang::diag::warn_drv_missing_resource_library) - << P.str(); - else + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) CmdArgs.push_back(Args.MakeArgString(P.str())); } } @@ -578,6 +616,72 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { setTarget(iPhoneVersion, Major, Minor, Micro); } +void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CXXStdlibType Type = GetCXXStdlibType(Args); + + switch (Type) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + break; + + case ToolChain::CST_Libstdcxx: { + // Unfortunately, -lstdc++ doesn't always exist in the standard search path; + // it was previously found in the gcc lib dir. However, for all the Darwin + // platforms we care about it was -lstdc++.6, so we search for that + // explicitly if we can't see an obvious -lstdc++ candidate. + + // Check in the sysroot first. + bool Exists; + if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { + llvm::sys::Path P(A->getValue(Args)); + P.appendComponent("usr"); + P.appendComponent("lib"); + P.appendComponent("libstdc++.dylib"); + + if (llvm::sys::fs::exists(P.str(), Exists) || !Exists) { + P.eraseComponent(); + P.appendComponent("libstdc++.6.dylib"); + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) { + CmdArgs.push_back(Args.MakeArgString(P.str())); + return; + } + } + } + + // Otherwise, look in the root. + if ((llvm::sys::fs::exists("/usr/lib/libstdc++.dylib", Exists) || !Exists)&& + (!llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib", Exists) && Exists)){ + CmdArgs.push_back("/usr/lib/libstdc++.6.dylib"); + return; + } + + // Otherwise, let the linker search. + CmdArgs.push_back("-lstdc++"); + break; + } + } +} + +void DarwinClang::AddCCKextLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + + // For Darwin platforms, use the compiler-rt-based support library + // instead of the gcc-provided one (which is also incidentally + // only present in the gcc lib dir, which makes it hard to find). + + llvm::sys::Path P(getDriver().ResourceDir); + P.appendComponent("lib"); + P.appendComponent("darwin"); + P.appendComponent("libclang_rt.cc_kext.a"); + + // For now, allow missing resource libraries to support developers who may + // not have compiler-rt checked out or integrated into their build. + bool Exists; + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) + CmdArgs.push_back(Args.MakeArgString(P.str())); +} + DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const { DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); @@ -599,6 +703,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, if (getArchName() != A->getValue(Args, 0)) continue; + Arg *OriginalArg = A; unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(Args, 1)); unsigned Prev = Index; Arg *XarchArg = Opts.ParseOneArg(Args, Index); @@ -622,6 +727,20 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, A = XarchArg; DAL->AddSynthesizedArg(A); + + // Linker input arguments require custom handling. The problem is that we + // have already constructed the phase actions, so we can not treat them as + // "input arguments". + if (A->getOption().isLinkerInput()) { + // Convert the argument into individual Zlinker_input_args. + for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { + DAL->AddSeparateArg(OriginalArg, + Opts.getOption(options::OPT_Zlinker_input), + A->getValue(Args, i)); + + } + continue; + } } // Sob. These is strictly gcc compatible for the time being. Apple @@ -941,7 +1060,7 @@ Tool &TCEToolChain::SelectTool(const Compilation &C, /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { + : Generic_ELF(Host, Triple) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); } @@ -953,11 +1072,20 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { else Key = JA.getKind(); + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + Tool *&T = Tools[Key]; if (!T) { switch (Key) { - case Action::AssembleJobClass: - T = new tools::openbsd::Assemble(*this); break; + case Action::AssembleJobClass: { + if (UseIntegratedAs) + T = new tools::ClangAs(*this); + else + T = new tools::openbsd::Assemble(*this); + break; + } case Action::LinkJobClass: T = new tools::openbsd::Link(*this); break; default: @@ -971,7 +1099,7 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { + : Generic_ELF(Host, Triple) { // Determine if we are compiling 32-bit code on an x86_64 platform. bool Lib32 = false; @@ -996,11 +1124,19 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { else Key = JA.getKind(); + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + Tool *&T = Tools[Key]; if (!T) { switch (Key) { case Action::AssembleJobClass: - T = new tools::freebsd::Assemble(*this); break; + if (UseIntegratedAs) + T = new tools::ClangAs(*this); + else + T = new tools::freebsd::Assemble(*this); + break; case Action::LinkJobClass: T = new tools::freebsd::Link(*this); break; default: @@ -1011,6 +1147,57 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { return *T; } +/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. + +NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple) + : Generic_ELF(Host, Triple) { + + // Determine if we are compiling 32-bit code on an x86_64 platform. + bool Lib32 = false; + if (Triple.getArch() == llvm::Triple::x86 && + llvm::Triple(getDriver().DefaultHostTriple).getArch() == + 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"); + } +} + +Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const { + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::AssembleJobClass: + if (UseIntegratedAs) + T = new tools::ClangAs(*this); + else + T = new tools::netbsd::Assemble(*this); + break; + case Action::LinkJobClass: + T = new tools::netbsd::Link(*this); break; + default: + T = &Generic_GCC::SelectTool(C, JA); + } + } + + return *T; +} + /// Minix - Minix tool chain which can call as(1) and ld(1) directly. Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple) @@ -1085,28 +1272,253 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { /// Linux toolchain (very bare-bones at the moment). -Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { - getFilePaths().push_back(getDriver().Dir + - "/../lib/clang/" CLANG_VERSION_STRING "/"); - getFilePaths().push_back("/lib/"); - getFilePaths().push_back("/usr/lib/"); - - // Depending on the Linux distribution, any combination of lib{,32,64} is - // possible. E.g. Debian uses lib and lib32 for mixed i386/x86-64 systems, - // openSUSE uses lib and lib64 for the same purpose. - getFilePaths().push_back("/lib32/"); - getFilePaths().push_back("/usr/lib32/"); - getFilePaths().push_back("/lib64/"); - getFilePaths().push_back("/usr/lib64/"); - - // FIXME: Figure out some way to get gcc's libdir - // (e.g. /usr/lib/gcc/i486-linux-gnu/4.3/ for Ubuntu 32-bit); we need - // crtbegin.o/crtend.o/etc., and want static versions of various - // libraries. If we had our own crtbegin.o/crtend.o/etc, we could probably - // get away with using shared versions in /usr/lib, though. - // We could fall back to the approach we used for includes (a massive - // list), but that's messy at best. +enum LinuxDistro { + DebianLenny, + DebianSqueeze, + Exherbo, + Fedora13, + Fedora14, + OpenSuse11_3, + UbuntuJaunty, + UbuntuKarmic, + UbuntuLucid, + UbuntuMaverick, + UnknownDistro +}; + +static bool IsFedora(enum LinuxDistro Distro) { + return Distro == Fedora13 || Distro == Fedora14; +} + +static bool IsOpenSuse(enum LinuxDistro Distro) { + return Distro == OpenSuse11_3; +} + +static bool IsDebian(enum LinuxDistro Distro) { + return Distro == DebianLenny || Distro == DebianSqueeze; +} + +static bool IsUbuntu(enum LinuxDistro Distro) { + return Distro == UbuntuLucid || Distro == UbuntuMaverick || + Distro == UbuntuJaunty || Distro == UbuntuKarmic; +} + +static bool IsDebianBased(enum LinuxDistro Distro) { + return IsDebian(Distro) || IsUbuntu(Distro); +} + +static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { + if (Arch == llvm::Triple::x86_64) { + bool Exists; + if (Distro == Exherbo && + (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists)) + return false; + + return true; + } + if (Arch == llvm::Triple::x86 && IsDebianBased(Distro)) + return true; + return false; +} + +static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { + llvm::OwningPtr<llvm::MemoryBuffer> File; + if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) { + llvm::StringRef Data = File.get()->getBuffer(); + 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; + else if (Lines[i] == "DISTRIB_CODENAME=jaunty") + return UbuntuJaunty; + else if (Lines[i] == "DISTRIB_CODENAME=karmic") + return UbuntuKarmic; + } + return UnknownDistro; + } + + if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { + llvm::StringRef Data = File.get()->getBuffer(); + if (Data.startswith("Fedora release 14 (Laughlin)")) + return Fedora14; + else if (Data.startswith("Fedora release 13 (Goddard)")) + return Fedora13; + return UnknownDistro; + } + + if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) { + llvm::StringRef Data = File.get()->getBuffer(); + if (Data[0] == '5') + return DebianLenny; + else if (Data.startswith("squeeze/sid")) + return DebianSqueeze; + return UnknownDistro; + } + + if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) { + llvm::StringRef Data = File.get()->getBuffer(); + if (Data.startswith("openSUSE 11.3")) + return OpenSuse11_3; + return UnknownDistro; + } + + bool Exists; + if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists) + return Exherbo; + + return UnknownDistro; +} + +Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) + : Generic_ELF(Host, Triple) { + llvm::Triple::ArchType Arch = + llvm::Triple(getDriver().DefaultHostTriple).getArch(); + + std::string Suffix32 = ""; + if (Arch == llvm::Triple::x86_64) + Suffix32 = "/32"; + + std::string Suffix64 = ""; + if (Arch == llvm::Triple::x86) + Suffix64 = "/64"; + + std::string Lib32 = "lib"; + + bool Exists; + if (!llvm::sys::fs::exists("/lib32", Exists) && Exists) + Lib32 = "lib32"; + + std::string Lib64 = "lib"; + bool Symlink; + if (!llvm::sys::fs::exists("/lib64", Exists) && Exists && + (llvm::sys::fs::is_symlink("/lib64", Symlink) || !Symlink)) + Lib64 = "lib64"; + + std::string GccTriple = ""; + if (Arch == llvm::Triple::arm) { + if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) && + Exists) + GccTriple = "arm-linux-gnueabi"; + } else if (Arch == llvm::Triple::x86_64) { + if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-linux-gnu", Exists) && + Exists) + GccTriple = "x86_64-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-unknown-linux-gnu", + Exists) && Exists) + GccTriple = "x86_64-unknown-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-pc-linux-gnu", + Exists) && Exists) + GccTriple = "x86_64-pc-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux", + Exists) && Exists) + GccTriple = "x86_64-redhat-linux"; + else if (!llvm::sys::fs::exists("/usr/lib64/gcc/x86_64-suse-linux", + Exists) && Exists) + GccTriple = "x86_64-suse-linux"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu", + Exists) && Exists) + GccTriple = "x86_64-manbo-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"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-pc-linux-gnu", Exists) && + Exists) + GccTriple = "i686-pc-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-linux-gnu", Exists) && + Exists) + GccTriple = "i486-linux-gnu"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-redhat-linux", Exists) && + Exists) + GccTriple = "i686-redhat-linux"; + else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) && + Exists) + GccTriple = "i586-suse-linux"; + } + + const char* GccVersions[] = {"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"}; + std::string Base = ""; + for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) { + std::string Suffix = GccTriple + "/" + GccVersions[i]; + std::string t1 = "/usr/lib/gcc/" + Suffix; + if (!llvm::sys::fs::exists(t1 + "/crtbegin.o", Exists) && Exists) { + Base = t1; + break; + } + std::string t2 = "/usr/lib64/gcc/" + Suffix; + if (!llvm::sys::fs::exists(t2 + "/crtbegin.o", Exists) && Exists) { + Base = t2; + break; + } + } + + path_list &Paths = getFilePaths(); + bool Is32Bits = getArch() == llvm::Triple::x86; + + std::string Suffix; + std::string Lib; + + if (Is32Bits) { + Suffix = Suffix32; + Lib = Lib32; + } else { + Suffix = Suffix64; + Lib = Lib64; + } + + llvm::sys::Path LinkerPath(Base + "/../../../../" + GccTriple + "/bin/ld"); + if (!llvm::sys::fs::exists(LinkerPath.str(), Exists) && Exists) + Linker = LinkerPath.str(); + else + Linker = GetProgramPath("ld"); + + LinuxDistro Distro = DetectLinuxDistro(Arch); + + if (IsUbuntu(Distro)) { + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("relro"); + } + + if (Arch == llvm::Triple::arm) + ExtraOpts.push_back("-X"); + + if (IsFedora(Distro) || Distro == UbuntuMaverick) + ExtraOpts.push_back("--hash-style=gnu"); + + if (IsDebian(Distro) || Distro == UbuntuLucid || Distro == UbuntuJaunty || + Distro == UbuntuKarmic) + ExtraOpts.push_back("--hash-style=both"); + + if (IsFedora(Distro)) + ExtraOpts.push_back("--no-add-needed"); + + if (Distro == DebianSqueeze || IsOpenSuse(Distro) || + IsFedora(Distro) || Distro == UbuntuLucid || Distro == UbuntuMaverick || + Distro == UbuntuKarmic) + ExtraOpts.push_back("--build-id"); + + Paths.push_back(Base + Suffix); + if (HasMultilib(Arch, Distro)) { + if (IsOpenSuse(Distro) && Is32Bits) + Paths.push_back(Base + "/../../../../" + GccTriple + "/lib/../lib"); + Paths.push_back(Base + "/../../../../" + Lib); + Paths.push_back("/lib/../" + Lib); + Paths.push_back("/usr/lib/../" + Lib); + } + if (!Suffix.empty()) + Paths.push_back(Base); + if (IsOpenSuse(Distro)) + Paths.push_back(Base + "/../../../../" + GccTriple + "/lib"); + Paths.push_back(Base + "/../../.."); + if (Arch == getArch() && IsUbuntu(Distro)) + Paths.push_back("/usr/lib/" + GccTriple); +} + +bool Linux::HasNativeLLVMSupport() const { + return true; } Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { @@ -1116,11 +1528,21 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { else Key = JA.getKind(); + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + Tool *&T = Tools[Key]; if (!T) { switch (Key) { case Action::AssembleJobClass: - T = new tools::linuxtools::Assemble(*this); break; + if (UseIntegratedAs) + T = new tools::ClangAs(*this); + else + T = new tools::linuxtools::Assemble(*this); + break; + case Action::LinkJobClass: + T = new tools::linuxtools::Link(*this); break; default: T = &Generic_GCC::SelectTool(C, JA); } @@ -1132,7 +1554,7 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const { /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { + : Generic_ELF(Host, Triple) { // Path mangling to find libexec getProgramPaths().push_back(getDriver().getInstalledDir()); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index d1f1556..0e3645c 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -155,6 +155,8 @@ public: virtual types::ID LookupTypeForExtension(const char *Ext) const; + virtual bool HasNativeLLVMSupport() const; + virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const; @@ -174,6 +176,18 @@ public: getTriple().getArch() == llvm::Triple::x86_64); #endif } + virtual bool IsStrictAliasingDefault() const { +#ifdef DISABLE_DEFAULT_STRICT_ALIASING + return false; +#else + return ToolChain::IsStrictAliasingDefault(); +#endif + } + + virtual bool IsObjCDefaultSynthPropertiesDefault() const { + return false; + } + virtual bool IsObjCNonFragileABIDefault() const { // Non-fragile ABI is default for everything but i386. return getTriple().getArch() != llvm::Triple::x86; @@ -221,6 +235,12 @@ public: virtual void AddLinkRuntimeLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + virtual void AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const; + + virtual void AddCCKextLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const; + /// } }; @@ -258,6 +278,18 @@ public: virtual const char *GetDefaultRelocationModel() const { return "pic"; } }; +class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { + public: + Generic_ELF(const HostInfo &Host, const llvm::Triple& Triple) + : Generic_GCC(Host, Triple) {} + + virtual bool IsIntegratedAssemblerDefault() const { + // Default integrated assembler to on for x86. + return (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64); + } +}; + class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { public: AuroraUX(const HostInfo &Host, const llvm::Triple& Triple); @@ -265,20 +297,27 @@ public: virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; }; -class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_GCC { +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; }; -class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_GCC { +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; }; +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; +}; + class LLVM_LIBRARY_VISIBILITY Minix : public Generic_GCC { public: Minix(const HostInfo &Host, const llvm::Triple& Triple); @@ -286,18 +325,23 @@ public: virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; }; -class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_GCC { +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; }; -class LLVM_LIBRARY_VISIBILITY Linux : public Generic_GCC { +class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { public: Linux(const HostInfo &Host, const llvm::Triple& Triple); + virtual bool HasNativeLLVMSupport() const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + + std::string Linker; + std::vector<std::string> ExtraOpts; }; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 5c16cd3..5a63213 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -1,4 +1,4 @@ -//===--- Tools.cpp - Tools Implementations ------------------------------*-===// +//===--- Tools.cpp - Tools Implementations --------------------------------===// // // The LLVM Compiler Infrastructure // @@ -25,10 +25,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/System/Host.h" -#include "llvm/System/Process.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Process.h" #include "InputInfo.h" #include "ToolChains.h" @@ -85,6 +86,48 @@ static void QuoteTarget(llvm::StringRef Target, } } +static void AddLinkerInputs(const ToolChain &TC, + const InputInfoList &Inputs, const ArgList &Args, + ArgStringList &CmdArgs) { + const Driver &D = TC.getDriver(); + + // Add extra linker input arguments which are not treated as inputs + // (constructed via -Xarch_). + Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + if (!TC.HasNativeLLVMSupport()) { + // Don't try to pass LLVM inputs unless we have native support. + 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) + << TC.getTripleString(); + } + + // Add filenames immediately. + if (II.isFilename()) { + CmdArgs.push_back(II.getFilename()); + continue; + } + + // Otherwise, this is a linker input argument. + const Arg &A = II.getInputArg(); + + // Handle reserved library options. + if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + } else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) { + TC.AddCCKextLibArgs(Args, CmdArgs); + } else + A.renderAsInput(Args, CmdArgs); + } +} + void Clang::AddPreprocessingOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, @@ -98,8 +141,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, Args.AddLastArg(CmdArgs, options::OPT_CC); // Handle dependency file generation. - if ((A = Args.getLastArg(options::OPT_M)) || - (A = Args.getLastArg(options::OPT_MM)) || + if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) || (A = Args.getLastArg(options::OPT_MD)) || (A = Args.getLastArg(options::OPT_MMD))) { // Determine the output location. @@ -130,11 +172,9 @@ void Clang::AddPreprocessingOptions(const Driver &D, // Otherwise derive from the base input. // // FIXME: This should use the computed output file location. - llvm::sys::Path P(Inputs[0].getBaseInput()); - - P.eraseSuffix(); - P.appendSuffix("o"); - DepTarget = Args.MakeArgString(P.getLast()); + llvm::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"); @@ -174,20 +214,25 @@ void Clang::AddPreprocessingOptions(const Driver &D, // wonky, but we include looking for .gch so we can support seamless // replacement into a build system already set up to be generating // .gch files. + bool RenderedImplicitInclude = false; for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group), ie = Args.filtered_end(); it != ie; ++it) { const Arg *A = it; if (A->getOption().matches(options::OPT_include)) { + bool IsFirstImplicitInclude = !RenderedImplicitInclude; + RenderedImplicitInclude = true; + // Use PCH if the user requested it. bool UsePCH = D.CCCUsePCH; bool FoundPTH = false; bool FoundPCH = false; llvm::sys::Path P(A->getValue(Args)); + bool Exists; if (UsePCH) { P.appendSuffix("pch"); - if (P.exists()) + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) FoundPCH = true; else P.eraseSuffix(); @@ -195,7 +240,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, if (!FoundPCH) { P.appendSuffix("pth"); - if (P.exists()) + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) FoundPTH = true; else P.eraseSuffix(); @@ -203,7 +248,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, if (!FoundPCH && !FoundPTH) { P.appendSuffix("gch"); - if (P.exists()) { + if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) { FoundPCH = UsePCH; FoundPTH = !UsePCH; } @@ -212,13 +257,19 @@ void Clang::AddPreprocessingOptions(const Driver &D, } if (FoundPCH || FoundPTH) { - A->claim(); - if (UsePCH) - CmdArgs.push_back("-include-pch"); - else - CmdArgs.push_back("-include-pth"); - CmdArgs.push_back(Args.MakeArgString(P.str())); - continue; + if (IsFirstImplicitInclude) { + A->claim(); + if (UsePCH) + CmdArgs.push_back("-include-pch"); + else + CmdArgs.push_back("-include-pth"); + CmdArgs.push_back(Args.MakeArgString(P.str())); + continue; + } else { + // Ignore the PCH if not first on command line and emit warning. + D.Diag(clang::diag::warn_drv_pch_not_first_include) + << P.str() << A->getAsString(Args); + } } } @@ -230,6 +281,11 @@ void Clang::AddPreprocessingOptions(const Driver &D, Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F); + // Add C++ include arguments, if needed. + types::ID InputType = Inputs[0].getType(); + if (types::isCXX(InputType)) + getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs); + // Add -Wp, and -Xassembler if using the preprocessor. // FIXME: There is a very unfortunate problem here, some troubled @@ -242,6 +298,15 @@ void Clang::AddPreprocessingOptions(const Driver &D, // -I- is a deprecated GCC feature, reject it. if (Arg *A = Args.getLastArg(options::OPT_I_)) D.Diag(clang::diag::err_drv_I_dash_not_supported) << A->getAsString(Args); + + // If we have a --sysroot, and don't have an explicit -isysroot flag, add an + // -isysroot to the CC1 invocation. + if (Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) { + if (!Args.hasArg(options::OPT_isysroot)) { + CmdArgs.push_back("-isysroot"); + CmdArgs.push_back(A->getValue(Args)); + } + } } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting. @@ -367,13 +432,16 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ABIName = A->getValue(Args); } else { // Select the default based on the platform. - llvm::StringRef env = Triple.getEnvironmentName(); - if (env == "gnueabi") + switch(Triple.getEnvironment()) { + case llvm::Triple::GNUEABI: ABIName = "aapcs-linux"; - else if (env == "eabi") + break; + case llvm::Triple::EABI: ABIName = "aapcs"; - else + break; + default: ABIName = "apcs-gnu"; + } } CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); @@ -420,8 +488,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } case llvm::Triple::Linux: { - llvm::StringRef Env = getToolChain().getTriple().getEnvironmentName(); - if (Env == "gnueabi") { + if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUEABI) { FloatABI = "softfp"; break; } @@ -429,10 +496,20 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // fall through default: - // Assume "soft", but warn the user we are guessing. - FloatABI = "soft"; - D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; - break; + switch(Triple.getEnvironment()) { + case llvm::Triple::GNUEABI: + FloatABI = "softfp"; + break; + case llvm::Triple::EABI: + // EABI is always AAPCS, and if it was not marked 'hard', it's softfp + FloatABI = "softfp"; + break; + default: + // Assume "soft", but warn the user we are guessing. + FloatABI = "soft"; + D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + break; + } } } @@ -557,6 +634,51 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, } } +void Clang::AddSparcTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + llvm::StringRef MArch = A->getValue(Args); + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(MArch.str().c_str()); + } + + // Select the float ABI as determined by -msoft-float, -mhard-float, and + llvm::StringRef FloatABI; + if (Arg *A = Args.getLastArg(options::OPT_msoft_float, + options::OPT_mhard_float)) { + if (A->getOption().matches(options::OPT_msoft_float)) + FloatABI = "soft"; + else if (A->getOption().matches(options::OPT_mhard_float)) + FloatABI = "hard"; + } + + // If unspecified, choose the default based on the platform. + if (FloatABI.empty()) { + switch (getToolChain().getTriple().getOS()) { + default: + // Assume "soft", but warn the user we are guessing. + FloatABI = "soft"; + D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + break; + } + } + + 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"); + CmdArgs.push_back("soft"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+soft-float"); + } else { + assert(FloatABI == "hard" && "Invalid float abi!"); + CmdArgs.push_back("-mhard-float"); + } +} + void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!Args.hasFlag(options::OPT_mred_zone, @@ -604,11 +726,21 @@ void Clang::AddX86TargetArgs(const ArgList &Args, CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; - } else { + } else if (getToolChain().getOS().startswith("netbsd")) { if (getToolChain().getArchName() == "x86_64") CPUName = "x86-64"; else if (getToolChain().getArchName() == "i386") CPUName = "i486"; + } else if (getToolChain().getOS().startswith("freebsd")) { + if (getToolChain().getArchName() == "x86_64") + CPUName = "x86-64"; + else if (getToolChain().getArchName() == "i386") + CPUName = "i486"; + } else { + if (getToolChain().getArchName() == "x86_64") + CPUName = "x86-64"; + else if (getToolChain().getArchName() == "i386") + CPUName = "pentium4"; } } @@ -637,6 +769,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, static bool needsExceptions(const ArgList &Args, types::ID InputType, const llvm::Triple &Triple) { + // Handle -fno-exceptions. if (Arg *A = Args.getLastArg(options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) @@ -644,25 +777,24 @@ static bool needsExceptions(const ArgList &Args, types::ID InputType, else return false; } - switch (InputType) { - case types::TY_CXX: case types::TY_CXXHeader: - case types::TY_PP_CXX: case types::TY_PP_CXXHeader: - case types::TY_ObjCXX: case types::TY_ObjCXXHeader: - case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader: + + // Otherwise, C++ inputs use exceptions. + if (types::isCXX(InputType)) return true; - case types::TY_ObjC: case types::TY_ObjCHeader: - case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader: + // 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); - - default: - return false; + (Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::arm)); } + + return false; } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -709,10 +841,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !IsOpt)) CmdArgs.push_back("-mrelax-all"); - // When using an integrated assembler, we send -Wa, and -Xassembler options - // to -cc1. - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); + // When using an integrated assembler, translate -Wa, and -Xassembler + // options. + for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA, + options::OPT_Xassembler), + ie = Args.filtered_end(); it != ie; ++it) { + const Arg *A = *it; + A->claim(); + + for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { + llvm::StringRef Value = A->getValue(Args, i); + + 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; + } else { + D.Diag(clang::diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Value; + } + } + } + + // Also ignore explicit -force_cpusubtype_ALL option. + (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); } else if (isa<PrecompileJobAction>(JA)) { // Use PCH if the user requested it. bool UsePCH = D.CCCUsePCH; @@ -772,17 +927,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { - CmdArgs.push_back("-analyzer-check-dead-stores"); - // Do not enable the security-syntatic check since it - // it needs to be refined (known issues). - // CmdArgs.push_back("-analyzer-check-security-syntactic"); + types::ID InputType = Inputs[0].getType(); + + // Checks to perform for all language types. + + CmdArgs.push_back("-analyzer-checker=core"); + 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"); - CmdArgs.push_back("-analyzer-check-objc-methodsigs"); - // Do not enable the missing -dealloc check. - // '-analyzer-check-objc-missing-dealloc', - CmdArgs.push_back("-analyzer-check-objc-unused-ivars"); - CmdArgs.push_back("-analyzer-check-idempotent-operations"); } // Set the output format. The default is plist, for (lame) historical @@ -850,6 +1015,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // LLVM Code Generator Options. + if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) { + CmdArgs.push_back("-mregparm"); + CmdArgs.push_back(A->getValue(Args)); + } + // FIXME: Set --enable-unsafe-fp-math. if (Args.hasFlag(options::OPT_fno_omit_frame_pointer, options::OPT_fomit_frame_pointer)) @@ -857,12 +1027,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); + if (!Args.hasFlag(options::OPT_fstrict_aliasing, + options::OPT_fno_strict_aliasing, + getToolChain().IsStrictAliasingDefault())) + CmdArgs.push_back("-relaxed-aliasing"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. bool IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, - IsVerboseAsmDefault) || + IsVerboseAsmDefault) || Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); @@ -880,6 +1054,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getTriple().getOS() != llvm::Triple::Darwin) CmdArgs.push_back("-mconstructor-aliases"); + if (Args.hasArg(options::OPT_mms_bitfields)) { + CmdArgs.push_back("-mms-bitfields"); + } + // This is a coarse approximation of what llvm-gcc actually does, both // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more // complicated ways. @@ -920,6 +1098,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AddMIPSTargetArgs(Args, CmdArgs); break; + case llvm::Triple::sparc: + AddSparcTargetArgs(Args, CmdArgs); + break; + case llvm::Triple::x86: case llvm::Triple::x86_64: AddX86TargetArgs(Args, CmdArgs); @@ -932,9 +1114,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - // -mno-omit-leaf-frame-pointer is default. + // -mno-omit-leaf-frame-pointer is the default on Darwin. if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, - options::OPT_mno_omit_leaf_frame_pointer, false)) + options::OPT_mno_omit_leaf_frame_pointer, + getToolChain().getTriple().getOS() != llvm::Triple::Darwin)) CmdArgs.push_back("-momit-leaf-frame-pointer"); // -fno-math-errno is default. @@ -946,23 +1129,29 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Explicitly error on some things we know we don't support and can't just // ignore. types::ID InputType = Inputs[0].getType(); - Arg *Unsupported; - if ((Unsupported = Args.getLastArg(options::OPT_MG)) || - (Unsupported = Args.getLastArg(options::OPT_iframework)) || - (Unsupported = Args.getLastArg(options::OPT_fshort_enums))) - D.Diag(clang::diag::err_drv_clang_unsupported) - << Unsupported->getOption().getName(); - - if (types::isCXX(InputType) && - getToolChain().getTriple().getOS() == llvm::Triple::Darwin && - getToolChain().getTriple().getArch() == llvm::Triple::x86) { - if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext))) - D.Diag(clang::diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) + if (!Args.hasArg(options::OPT_fallow_unsupported)) { + Arg *Unsupported; + if ((Unsupported = Args.getLastArg(options::OPT_MG)) || + (Unsupported = Args.getLastArg(options::OPT_iframework))) + D.Diag(clang::diag::err_drv_clang_unsupported) << Unsupported->getOption().getName(); + + if (types::isCXX(InputType) && + getToolChain().getTriple().getOS() == llvm::Triple::Darwin && + getToolChain().getTriple().getArch() == llvm::Triple::x86) { + if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext))) + D.Diag(clang::diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) + << Unsupported->getOption().getName(); + } } Args.AddAllArgs(CmdArgs, options::OPT_v); Args.AddLastArg(CmdArgs, options::OPT_H); + if (D.CCPrintHeaders) { + CmdArgs.push_back("-header-include-file"); + CmdArgs.push_back(D.CCPrintHeadersFilename ? + D.CCPrintHeadersFilename : "-"); + } Args.AddLastArg(CmdArgs, options::OPT_P); Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout); @@ -986,6 +1175,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-resource-dir"); CmdArgs.push_back(D.ResourceDir.c_str()); + Args.AddLastArg(CmdArgs, options::OPT_working_directory); + // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // @@ -1001,6 +1192,10 @@ 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); } @@ -1054,6 +1249,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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"); + if (A->getNumValues()) + CmdArgs.push_back(A->getValue(Args)); + else + CmdArgs.push_back("64"); // default value for -Wlarge-by-value-copy. + } + if (Args.hasArg(options::OPT__relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); @@ -1100,7 +1304,7 @@ 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, @@ -1110,8 +1314,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -f (flag) options which we can pass directly. Args.AddLastArg(CmdArgs, options::OPT_fcatch_undefined_behavior); Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); - Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); 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); // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, @@ -1133,12 +1339,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + if (Args.getLastArg(options::OPT_fapple_kext)) + CmdArgs.push_back("-fapple-kext"); + Args.AddLastArg(CmdArgs, options::OPT_fno_show_column); Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); + + if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) { + CmdArgs.push_back("-ftrapv-handler"); + CmdArgs.push_back(A->getValue(Args)); + } + Args.AddLastArg(CmdArgs, options::OPT_fwrapv); Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops); @@ -1164,8 +1379,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -f options with positive and negative forms; we translate // these by hand. + if (Args.hasArg(options::OPT_mkernel)) { + if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType)) + CmdArgs.push_back("-fapple-kext"); + if (!Args.hasArg(options::OPT_fbuiltin)) + CmdArgs.push_back("-fno-builtin"); + } // -fbuiltin is default. - if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) + else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) CmdArgs.push_back("-fno-builtin"); if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, @@ -1184,8 +1405,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fno-access-control"); + // -felide-constructors is the default. + if (Args.hasFlag(options::OPT_fno_elide_constructors, + options::OPT_felide_constructors, + false)) + CmdArgs.push_back("-fno-elide-constructors"); + // -fexceptions=0 is default. - if (needsExceptions(Args, InputType, getToolChain().getTriple())) + if (!KernelOrKext && + needsExceptions(Args, InputType, getToolChain().getTriple())) CmdArgs.push_back("-fexceptions"); if (getToolChain().UseSjLjExceptions()) @@ -1196,19 +1424,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti)) CmdArgs.push_back("-fno-rtti"); + // -fshort-enums=0 is default. + // FIXME: Are there targers where -fshort-enums is on by default ? + if (Args.hasFlag(options::OPT_fshort_enums, + options::OPT_fno_short_enums, false)) + CmdArgs.push_back("-fshort-enums"); + // -fsigned-char is default. if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char, isSignedCharDefault(getToolChain().getTriple()))) CmdArgs.push_back("-fno-signed-char"); // -fthreadsafe-static is default. - if (!Args.hasFlag(options::OPT_fthreadsafe_statics, + if (!Args.hasFlag(options::OPT_fthreadsafe_statics, options::OPT_fno_threadsafe_statics)) 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)) + 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)) CmdArgs.push_back("-fno-use-cxa-atexit"); // -fms-extensions=0 is default. @@ -1216,6 +1452,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) CmdArgs.push_back("-fms-extensions"); + // -fmsc-version=1300 is default. + if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, + getToolChain().getTriple().getOS() == llvm::Triple::Win32) || + Args.hasArg(options::OPT_fmsc_version)) { + llvm::StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); + if (msc_ver.empty()) + CmdArgs.push_back("-fmsc-version=1300"); + else + CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver)); + } + + // -fborland-extensions=0 is default. if (Args.hasFlag(options::OPT_fborland_extensions, options::OPT_fno_borland_extensions, false)) @@ -1229,7 +1477,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fnext-runtime defaults to on Darwin and when rewriting Objective-C, and is // -the -cc1 default. - bool NeXTRuntimeIsDefault = + bool NeXTRuntimeIsDefault = IsRewriter || getToolChain().getTriple().getOS() == llvm::Triple::Darwin; if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, NeXTRuntimeIsDefault)) @@ -1237,20 +1485,52 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fobjc-nonfragile-abi=0 is default. if (types::isObjC(InputType)) { + // Compute the Objective-C ABI "version" to use. Version numbers are + // slightly confusing for historical reasons: + // 1 - Traditional "fragile" ABI + // 2 - Non-fragile ABI, version 1 + // 3 - Non-fragile ABI, version 2 unsigned Version = 1; - if (Args.hasArg(options::OPT_fobjc_nonfragile_abi) || - getToolChain().IsObjCNonFragileABIDefault()) - Version = 2; + // If -fobjc-abi-version= is present, use that to set the version. if (Arg *A = Args.getLastArg(options::OPT_fobjc_abi_version_EQ)) { if (llvm::StringRef(A->getValue(Args)) == "1") Version = 1; else if (llvm::StringRef(A->getValue(Args)) == "2") Version = 2; + else if (llvm::StringRef(A->getValue(Args)) == "3") + Version = 3; else D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + } else { + // Otherwise, determine if we are using the non-fragile ABI. + if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi, + options::OPT_fno_objc_nonfragile_abi, + getToolChain().IsObjCNonFragileABIDefault())) { + // Determine the non-fragile ABI version to use. +#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO + unsigned NonFragileABIVersion = 1; +#else + unsigned NonFragileABIVersion = 2; +#endif + + if (Arg *A = Args.getLastArg( + options::OPT_fobjc_nonfragile_abi_version_EQ)) { + if (llvm::StringRef(A->getValue(Args)) == "1") + NonFragileABIVersion = 1; + else if (llvm::StringRef(A->getValue(Args)) == "2") + NonFragileABIVersion = 2; + else + D.Diag(clang::diag::err_drv_clang_unsupported) + << A->getAsString(Args); + } + + Version = 1 + NonFragileABIVersion; + } else { + Version = 1; + } } - if (Version == 2) { + if (Version == 2 || Version == 3) { CmdArgs.push_back("-fobjc-nonfragile-abi"); // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and @@ -1265,10 +1545,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // FIXME: -fobjc-nonfragile-abi2 is a transient option meant to expose - // features in testing. It will eventually be removed. - if (Args.hasArg(options::OPT_fobjc_nonfragile_abi2)) - CmdArgs.push_back("-fobjc-nonfragile-abi2"); + // -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"); + } + + // -fobjc-exceptions is default. + if (!Args.hasFlag(options::OPT_fobjc_exceptions, + options::OPT_fno_objc_exceptions)) + CmdArgs.push_back("-fno-objc-exceptions"); } if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, @@ -1301,17 +1588,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fpascal-strings"); + if (Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) { + if (!Args.hasArg(options::OPT_fcommon)) + CmdArgs.push_back("-fno-common"); + } // -fcommon is default, only pass non-default. - if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common)) + else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common)) CmdArgs.push_back("-fno-common"); // -fsigned-bitfields is default, and clang doesn't yet support - // --funsigned-bitfields. + // -funsigned-bitfields. if (!Args.hasFlag(options::OPT_fsigned_bitfields, options::OPT_funsigned_bitfields)) D.Diag(clang::diag::warn_drv_clang_unsupported) << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args); + // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope. + if (!Args.hasFlag(options::OPT_ffor_scope, + options::OPT_fno_for_scope)) + D.Diag(clang::diag::err_drv_clang_unsupported) + << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args); + // -fcaret-diagnostics is default. if (!Args.hasFlag(options::OPT_fcaret_diagnostics, options::OPT_fno_caret_diagnostics, true)) @@ -1322,8 +1620,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); - Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_binary); - // Enable -fdiagnostics-show-option by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_option, options::OPT_fno_diagnostics_show_option)) @@ -1338,8 +1634,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Color diagnostics are the default, unless the terminal doesn't support // them. if (Args.hasFlag(options::OPT_fcolor_diagnostics, - options::OPT_fno_color_diagnostics) && - llvm::sys::Process::StandardErrHasColors()) + options::OPT_fno_color_diagnostics, + llvm::sys::Process::StandardErrHasColors())) CmdArgs.push_back("-fcolor-diagnostics"); if (!Args.hasFlag(options::OPT_fshow_source_location, @@ -1350,6 +1646,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_spell_checking)) CmdArgs.push_back("-fno-spell-checking"); + + // Silently ignore -fasm-blocks for now. + (void) Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks, + false); + if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) A->render(Args, CmdArgs); @@ -1451,13 +1752,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); - // Explicitly warn that these options are unsupported, even though - // we are allowing compilation to continue. - for (arg_iterator it = Args.filtered_begin(options::OPT_pg), - ie = Args.filtered_end(); it != ie; ++it) { - (*it)->claim(); - D.Diag(clang::diag::warn_drv_clang_unsupported) << (*it)->getAsString(Args); - } + if (Arg *A = Args.getLastArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_fomit_frame_pointer)) + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << "-fomit-frame-pointer" << A->getAsString(Args); // Claim some arguments which clang supports automatically. @@ -1482,6 +1780,9 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, assert(Inputs.size() == 1 && "Unexpected number of inputs."); const InputInfo &Input = Inputs[0]; + // Don't warn about "clang -w -c foo.s" + Args.ClaimAllArgs(options::OPT_w); + // Invoke ourselves in -cc1as mode. // // FIXME: Implement custom jobs for internal actions. @@ -1615,12 +1916,21 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, if (II.isFilename()) CmdArgs.push_back(II.getFilename()); - else + else { + const Arg &A = II.getInputArg(); + + // Reverse translate some rewritten options. + if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { + CmdArgs.push_back("-lstdc++"); + continue; + } + // Don't render as input, we need gcc to do the translations. - II.getInputArg().render(Args, CmdArgs); + A.render(Args, CmdArgs); + } } - const char *GCCName = getToolChain().getDriver().CCCGenericGCCName.c_str(); + const char *GCCName = getToolChain().getDriver().getCCCGenericGCCName().c_str(); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); @@ -1648,7 +1958,7 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, if (JA.getType() != types::TY_PP_Asm) D.Diag(clang::diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType()); - + CmdArgs.push_back("-S"); } } @@ -1685,15 +1995,15 @@ const char *darwin::CC1::getCC1Name(types::ID Type) const { const char *darwin::CC1::getBaseInputName(const ArgList &Args, const InputInfoList &Inputs) { - llvm::sys::Path P(Inputs[0].getBaseInput()); - return Args.MakeArgString(P.getLast()); + return Args.MakeArgString( + llvm::sys::path::filename(Inputs[0].getBaseInput())); } const char *darwin::CC1::getBaseInputStem(const ArgList &Args, const InputInfoList &Inputs) { const char *Str = getBaseInputName(Args, Inputs); - if (const char *End = strchr(Str, '.')) + if (const char *End = strrchr(Str, '.')) return Args.MakeArgString(std::string(Str, End)); return Str; @@ -2188,7 +2498,8 @@ void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, CmdArgs.push_back("-force_cpusubtype_ALL"); } -void darwin::Link::AddLinkArgs(const ArgList &Args, +void darwin::Link::AddLinkArgs(Compilation &C, + const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -2204,8 +2515,30 @@ void darwin::Link::AddLinkArgs(const ArgList &Args, // Newer linkers support -demangle, pass it if supported and not disabled by // the user. - if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) { - CmdArgs.push_back("-demangle"); + // + // 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) && + !getDarwinToolChain().isTargetIPhoneOS()) { + // Don't pass -demangle to ld_classic. + // + // FIXME: This is a temporary workaround, ld should be handling this. + bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 && + Args.hasArg(options::OPT_static)); + if (getToolChain().getArch() == llvm::Triple::x86) { + for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker, + options::OPT_Wl_COMMA), + ie = Args.filtered_end(); it != ie; ++it) { + const Arg *A = *it; + for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) + if (llvm::StringRef(A->getValue(Args, i)) == "-kext") + UsesLdClassic = true; + } + } + if (!UsesLdClassic) + CmdArgs.push_back("-demangle"); } // Derived from the "link" spec. @@ -2362,7 +2695,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // I'm not sure why this particular decomposition exists in gcc, but // we follow suite for ease of comparison. - AddLinkArgs(Args, CmdArgs); + AddLinkArgs(C, Args, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_d_Flag); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -2374,6 +2707,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_m_Separate); Args.AddAllArgs(CmdArgs, options::OPT_r); + // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading + // members of static archive libraries which implement Objective-C classes or + // categories. + if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX)) + CmdArgs.push_back("-ObjC"); + CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); @@ -2459,14 +2798,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (LinkingOutput) { CmdArgs.push_back("-arch_multiple"); @@ -2485,10 +2817,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { - // FIXME: g++ is more complicated here, it tries to put -lstdc++ - // before -lm, for example. if (getToolChain().getDriver().CCCIsCXX) - CmdArgs.push_back("-lstdc++"); + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); // link_ssp spec is empty. @@ -2583,7 +2913,6 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if ((!Args.hasArg(options::OPT_nostdlib)) && @@ -2638,21 +2967,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Don't try to pass LLVM 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(); - - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -2720,6 +3035,8 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { @@ -2760,26 +3077,12 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Don't try to pass LLVM 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(); - - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { - CmdArgs.push_back("-lstdc++"); + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } @@ -2821,7 +3124,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArchName() == "i386") CmdArgs.push_back("--32"); - + // Set byte order explicitly if (getToolChain().getArchName() == "mips") CmdArgs.push_back("-EB"); @@ -2856,6 +3159,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); @@ -2882,8 +3187,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crt1.o"))); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("gcrt1.o"))); + else + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString( @@ -2897,6 +3206,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); + CmdArgs.push_back("-L/usr/lib"); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); @@ -2904,26 +3214,182 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (D.CCCIsCXX) { + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lm_p"); + else + CmdArgs.push_back("-lm"); + } + // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding + // the default system libraries. Just mimic this for now. + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lgcc_p"); + else + CmdArgs.push_back("-lgcc"); + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-lgcc_eh"); + } else if (Args.hasArg(options::OPT_pg)) { + CmdArgs.push_back("-lgcc_eh_p"); + } else { + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + } + + if (Args.hasArg(options::OPT_pthread)) { + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lpthread_p"); + else + CmdArgs.push_back("-lpthread"); + } + + if (Args.hasArg(options::OPT_pg)) { + if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("-lc"); + else + CmdArgs.push_back("-lc_p"); + CmdArgs.push_back("-lgcc_p"); + } else { + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lgcc"); + } + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-lgcc_eh"); + } else if (Args.hasArg(options::OPT_pg)) { + CmdArgs.push_back("-lgcc_eh_p"); + } else { + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + } + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( + "crtend.o"))); + else + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( + "crtendS.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( + "crtn.o"))); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("ld")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + +void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + // When building 32-bit code on NetBSD/amd64, we have to explicitly + // instruct as in the base system to assemble 32-bit code. + if (getToolChain().getArchName() == "i386") + CmdArgs.push_back("--32"); + + + // Set byte order explicitly + if (getToolChain().getArchName() == "mips") + CmdArgs.push_back("-EB"); + else if (getToolChain().getArchName() == "mipsel") + CmdArgs.push_back("-EL"); + + 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()); + } - // Don't try to pass LLVM 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(); + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("as")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); +void netbsd::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; + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + } else { + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + CmdArgs.push_back("--eh-frame-hdr"); + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-Bshareable"); + } else { + CmdArgs.push_back("-dynamic-linker"); + CmdArgs.push_back("/libexec/ld.elf_so"); + } + } + + // When building 32-bit code on NetBSD/amd64, we have to explicitly + // instruct ld in the base system to link 32-bit code. + if (getToolChain().getArchName() == "i386") { + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf_i386"); + } + + 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( + getToolChain().GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crti.o"))); + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crtbegin.o"))); + } else { + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crti.o"))); + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crtbeginS.o"))); + } + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_s); + Args.AddAllArgs(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); + Args.AddAllArgs(CmdArgs, options::OPT_r); + + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { - CmdArgs.push_back("-lstdc++"); + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding @@ -3004,6 +3470,185 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const toolchains::Linux& ToolChain = + static_cast<const toolchains::Linux&>(getToolChain()); + const Driver &D = ToolChain.getDriver(); + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // 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 (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("-s"); + + for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), + e = ToolChain.ExtraOpts.end(); + i != e; ++i) + CmdArgs.push_back(i->c_str()); + + if (!Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("--eh-frame-hdr"); + } + + CmdArgs.push_back("-m"); + if (ToolChain.getArch() == llvm::Triple::x86) + CmdArgs.push_back("elf_i386"); + else if (ToolChain.getArch() == llvm::Triple::arm) + CmdArgs.push_back("armelf_linux_eabi"); + else + CmdArgs.push_back("elf_x86_64"); + + if (Args.hasArg(options::OPT_static)) { + if (ToolChain.getArch() == llvm::Triple::arm) + CmdArgs.push_back("-Bstatic"); + else + CmdArgs.push_back("-static"); + } else if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-shared"); + } + + if (ToolChain.getArch() == llvm::Triple::arm || + (!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) + CmdArgs.push_back("/lib/ld-linux.so.3"); + else + CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2"); + } + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + const char *crt1 = NULL; + if (!Args.hasArg(options::OPT_shared)){ + if (Args.hasArg(options::OPT_pie)) + crt1 = "Scrt1.o"; + else + crt1 = "crt1.o"; + } + if (crt1) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); + + const char *crtbegin; + if (Args.hasArg(options::OPT_static)) + crtbegin = "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + crtbegin = "crtbeginS.o"; + else + crtbegin = "crtbegin.o"; + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + } + + 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) { + const std::string &s = *i; + CmdArgs.push_back(Args.MakeArgString(std::string("-L") + s)); + } + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) { + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lm"); + } + + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--start-group"); + + if (!Args.hasArg(options::OPT_nostdlib)) { + 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"); + + if (Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads)) + CmdArgs.push_back("-lpthread"); + + CmdArgs.push_back("-lc"); + + 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"); + } + + + if (!Args.hasArg(options::OPT_nostartfiles)) { + const char *crtend; + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + crtend = "crtendS.o"; + else + crtend = "crtend.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); + } + } + + 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)); +} void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -3053,26 +3698,12 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Don't try to pass LLVM 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(); - - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { - CmdArgs.push_back("-lstdc++"); + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } @@ -3184,21 +3815,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Don't try to pass LLVM 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(); - - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -3221,7 +3838,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, } if (D.CCCIsCXX) { - CmdArgs.push_back("-lstdc++"); + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } @@ -3268,11 +3885,11 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if (Output.isFilename()) { - CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + Output.getFilename())); + CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + + Output.getFilename())); } else { assert(Output.isNothing() && "Invalid output."); } @@ -3284,22 +3901,9 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-nologo"); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - - // Don't try to pass LLVM inputs to visual studio linker. - if (II.getType() == types::TY_LLVM_BC) - D.Diag(clang::diag::err_drv_no_linker_llvm_support) - << getToolChain().getTripleString(); - - if (II.isFilename()) - CmdArgs.push_back(II.getFilename()); - else - II.getInputArg().renderAsInput(Args, CmdArgs); - } + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); + Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index b5defa4..10c8839 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -36,6 +36,7 @@ namespace tools { void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) 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; public: @@ -232,7 +233,8 @@ namespace darwin { }; class LLVM_LIBRARY_VISIBILITY Link : public DarwinTool { - void AddLinkArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + void AddLinkArgs(Compilation &C, const ArgList &Args, + ArgStringList &CmdArgs) const; public: Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {} @@ -332,6 +334,35 @@ namespace freebsd { }; } // end namespace freebsd + /// netbsd -- Directly call GNU Binutils assembler and linker +namespace netbsd { + class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("netbsd::Assemble", "assembler", + TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("netbsd::Link", "linker", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} // end namespace netbsd + /// linux -- Directly call GNU Binutils assembler and linker namespace linuxtools { class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { @@ -347,6 +378,18 @@ namespace linuxtools { const ArgList &TCArgs, const char *LinkingOutput) const; }; + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("linux::Link", "linker", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; } /// minix -- Directly call GNU Binutils assembler and linker namespace minix { diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index 3c07cf2..4a4312b 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -1,4 +1,4 @@ -//===--- Types.cpp - Driver input & temporary type information ----------*-===// +//===--- Types.cpp - Driver input & temporary type information ------------===// // // The LLVM Compiler Infrastructure // @@ -78,6 +78,7 @@ bool types::isAcceptedByClang(ID Id) { case TY_Asm: case TY_C: case TY_PP_C: case TY_CL: + case TY_CUDA: case TY_ObjC: case TY_PP_ObjC: case TY_CXX: case TY_PP_CXX: case TY_ObjCXX: case TY_PP_ObjCXX: @@ -151,6 +152,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) { .Case("CC", TY_CXX) .Case("cl", TY_CL) .Case("cp", TY_CXX) + .Case("cu", TY_CUDA) .Case("hh", TY_CXXHeader) .Case("ll", TY_LLVM_IR) .Case("hpp", TY_CXXHeader) |