summaryrefslogtreecommitdiffstats
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/Action.cpp2
-rw-r--r--lib/Driver/Arg.cpp2
-rw-r--r--lib/Driver/ArgList.cpp40
-rw-r--r--lib/Driver/CMakeLists.txt2
-rw-r--r--lib/Driver/Compilation.cpp20
-rw-r--r--lib/Driver/Driver.cpp153
-rw-r--r--lib/Driver/DriverOptions.cpp2
-rw-r--r--lib/Driver/HostInfo.cpp68
-rw-r--r--lib/Driver/Job.cpp2
-rw-r--r--lib/Driver/OptTable.cpp5
-rw-r--r--lib/Driver/Option.cpp2
-rw-r--r--lib/Driver/Phases.cpp2
-rw-r--r--lib/Driver/Tool.cpp2
-rw-r--r--lib/Driver/ToolChain.cpp55
-rw-r--r--lib/Driver/ToolChains.cpp516
-rw-r--r--lib/Driver/ToolChains.h52
-rw-r--r--lib/Driver/Tools.cpp1025
-rw-r--r--lib/Driver/Tools.h45
-rw-r--r--lib/Driver/Types.cpp4
19 files changed, 1647 insertions, 352 deletions
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index f34971b..549ce0a 100644
--- a/lib/Driver/Action.cpp
+++ b/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/lib/Driver/Arg.cpp b/lib/Driver/Arg.cpp
index 83d0d26..f1177cf 100644
--- a/lib/Driver/Arg.cpp
+++ b/lib/Driver/Arg.cpp
@@ -1,4 +1,4 @@
-//===--- Arg.cpp - Argument Implementations -----------------------------*-===//
+//===--- Arg.cpp - Argument Implementations -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
index 9101523..596e2a7 100644
--- a/lib/Driver/ArgList.cpp
+++ b/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/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 00d076b..ee7ded9 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_NO_RTTI 1)
+set(LLVM_USED_LIBS clangBasic clangAST clangParse)
add_clang_library(clangDriver
Action.cpp
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index c059afd..5619212 100644
--- a/lib/Driver/Compilation.cpp
+++ b/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/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 82f9134..5a5986b 100644
--- a/lib/Driver/Driver.cpp
+++ b/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/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp
index 72aaf56..f2d9af8 100644
--- a/lib/Driver/DriverOptions.cpp
+++ b/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/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 7c5e430..cd413180 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/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/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index fa7d060..51055e9 100644
--- a/lib/Driver/Job.cpp
+++ b/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/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index 3c36314..c3d3048 100644
--- a/lib/Driver/OptTable.cpp
+++ b/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/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
index 5396250..a992cef 100644
--- a/lib/Driver/Option.cpp
+++ b/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/lib/Driver/Phases.cpp b/lib/Driver/Phases.cpp
index df4cdee..f360002 100644
--- a/lib/Driver/Phases.cpp
+++ b/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/lib/Driver/Tool.cpp b/lib/Driver/Tool.cpp
index fe01531..b93864f 100644
--- a/lib/Driver/Tool.cpp
+++ b/lib/Driver/Tool.cpp
@@ -1,4 +1,4 @@
-//===--- Tool.cpp - Compilation Tools -----------------------------------*-===//
+//===--- Tool.cpp - Compilation Tools -------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 94c1c6b..e4051a1 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/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/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 471c47d..13b8b46 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/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
@@ -59,6 +62,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")
@@ -142,7 +149,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 += "/";
@@ -156,7 +164,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;
}
@@ -301,19 +309,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));
@@ -369,10 +378,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,
@@ -431,12 +460,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()));
}
@@ -477,11 +508,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.
@@ -493,10 +533,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()));
}
}
@@ -574,6 +612,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());
@@ -595,6 +699,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);
@@ -618,6 +723,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
@@ -937,7 +1056,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");
}
@@ -949,11 +1068,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:
@@ -967,7 +1095,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;
@@ -994,11 +1122,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:
@@ -1009,6 +1145,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)
@@ -1083,28 +1270,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 {
@@ -1114,11 +1526,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);
}
@@ -1130,7 +1552,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/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index d1f1556..0e3645c 100644
--- a/lib/Driver/ToolChains.h
+++ b/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/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 8436561..6717349 100644
--- a/lib/Driver/Tools.cpp
+++ b/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,6 +726,11 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
CPUName = "x86-64";
else if (getToolChain().getArchName() == "i386")
CPUName = "i486";
+ } else if (getToolChain().getOS().startswith("netbsd")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i486";
} else {
if (getToolChain().getArchName() == "x86_64")
CPUName = "x86-64";
@@ -637,6 +764,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 +772,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 +836,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 +922,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 +1010,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 +1022,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 +1049,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 +1093,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 +1109,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 +1124,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 +1170,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 +1187,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 +1244,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 +1299,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,
@@ -1111,6 +1310,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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_flimit_debug_info);
+ Args.AddLastArg(CmdArgs, options::OPT_pg);
// -flax-vector-conversions is default.
if (!Args.hasFlag(options::OPT_flax_vector_conversions,
@@ -1132,12 +1333,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);
@@ -1163,8 +1373,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,
@@ -1183,8 +1399,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())
@@ -1195,19 +1418,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.
@@ -1215,6 +1446,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))
@@ -1228,7 +1471,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))
@@ -1236,20 +1479,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
@@ -1264,10 +1539,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,
@@ -1300,17 +1582,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))
@@ -1321,8 +1614,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))
@@ -1337,8 +1628,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,
@@ -1349,6 +1640,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);
@@ -1450,13 +1746,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.
@@ -1481,6 +1774,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.
@@ -1614,12 +1910,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));
@@ -1647,7 +1952,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");
}
}
@@ -1684,15 +1989,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;
@@ -2187,7 +2492,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();
@@ -2203,8 +2509,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.
@@ -2361,7 +2689,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);
@@ -2373,6 +2701,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());
@@ -2458,14 +2792,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");
@@ -2484,10 +2811,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.
@@ -2582,7 +2907,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)) &&
@@ -2637,21 +2961,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)) {
@@ -2719,6 +3029,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)) {
@@ -2759,26 +3071,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");
}
@@ -2820,7 +3118,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");
@@ -2855,6 +3153,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");
@@ -2881,8 +3181,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(
@@ -2896,6 +3200,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);
@@ -2903,26 +3208,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
@@ -3003,6 +3464,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,
@@ -3052,26 +3692,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");
}
@@ -3183,21 +3809,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)) {
@@ -3220,7 +3832,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");
}
@@ -3267,11 +3879,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.");
}
@@ -3283,22 +3895,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/lib/Driver/Tools.h b/lib/Driver/Tools.h
index b5defa4..10c8839 100644
--- a/lib/Driver/Tools.h
+++ b/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/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 3c07cf2..4a4312b 100644
--- a/lib/Driver/Types.cpp
+++ b/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)
OpenPOWER on IntegriCloud