aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/ArgList.cpp15
-rw-r--r--lib/Driver/Compilation.cpp5
-rw-r--r--lib/Driver/Driver.cpp127
-rw-r--r--lib/Driver/SanitizerArgs.h20
-rw-r--r--lib/Driver/ToolChain.cpp87
-rw-r--r--lib/Driver/ToolChains.cpp780
-rw-r--r--lib/Driver/ToolChains.h121
-rw-r--r--lib/Driver/Tools.cpp629
-rw-r--r--lib/Driver/Tools.h10
-rw-r--r--lib/Driver/Types.cpp3
-rw-r--r--lib/Driver/WindowsToolChain.cpp55
11 files changed, 1072 insertions, 780 deletions
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
index 6c57b622b8..4b8d151d19 100644
--- a/lib/Driver/ArgList.cpp
+++ b/lib/Driver/ArgList.cpp
@@ -206,6 +206,13 @@ bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
return Default;
}
+bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
+ bool Default) const {
+ if (Arg *A = getLastArg(Pos, PosAlias, Neg))
+ return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);
+ return Default;
+}
+
StringRef ArgList::getLastArgValue(OptSpecifier Id,
StringRef Default) const {
if (Arg *A = getLastArg(Id))
@@ -241,6 +248,14 @@ void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
}
}
+void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1) const {
+ if (Arg *A = getLastArg(Id0, Id1)) {
+ A->claim();
+ A->render(*this, Output);
+ }
+}
+
void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
OptSpecifier Id1, OptSpecifier Id2) const {
for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index db948a5bfe..1bff4a3d7a 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -290,11 +290,12 @@ int Compilation::ExecuteCommand(const Command &C,
}
std::string Error;
+ bool ExecutionFailed;
int Res =
llvm::sys::Program::ExecuteAndWait(Prog, Argv,
/*env*/0, Redirects,
/*secondsToWait*/0, /*memoryLimit*/0,
- &Error);
+ &Error, &ExecutionFailed);
if (!Error.empty()) {
assert(Res && "Error string set with 0 result code!");
getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
@@ -304,7 +305,7 @@ int Compilation::ExecuteCommand(const Command &C,
FailingCommand = &C;
delete[] Argv;
- return Res;
+ return ExecutionFailed ? 1 : Res;
}
typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList;
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 652046fce4..1dbbc9a342 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -126,6 +126,7 @@ const {
// -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
@@ -291,6 +292,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (Args->hasArg(options::OPT_nostdlib))
UseStdLib = false;
+ if (const Arg *A = Args->getLastArg(options::OPT_resource_dir))
+ ResourceDir = A->getValue();
+
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
@@ -487,9 +491,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
<< "\n\n********************";
} else {
// Failure, remove preprocessed files.
- if (!C.getArgs().hasArg(options::OPT_save_temps)) {
+ if (!C.getArgs().hasArg(options::OPT_save_temps))
C.CleanupFileList(C.getTempFiles(), true);
- }
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating preprocessed source(s).";
@@ -821,17 +824,6 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
if (!Archs.size())
Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));
- // FIXME: We killed off some others but these aren't yet detected in a
- // functional manner. If we added information to jobs about which "auxiliary"
- // files they wrote then we could detect the conflict these cause downstream.
- if (Archs.size() > 1) {
- // No recovery needed, the point of this is just to prevent
- // overwriting the same files.
- if (const Arg *A = Args.getLastArg(options::OPT_save_temps))
- Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs)
- << A->getAsString(Args);
- }
-
ActionList SingleActions;
BuildActions(TC, Args, BAInputs, SingleActions);
@@ -1167,6 +1159,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
return new MigrateJobAction(Input, types::TY_Remap);
} else if (Args.hasArg(options::OPT_emit_ast)) {
return new CompileJobAction(Input, types::TY_AST);
+ } else if (Args.hasArg(options::OPT_module_file_info)) {
+ return new CompileJobAction(Input, types::TY_ModuleFile);
} else if (IsUsingLTO(Args)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
@@ -1215,6 +1209,17 @@ void Driver::BuildJobs(Compilation &C) const {
}
}
+ // Collect the list of architectures.
+ llvm::StringSet<> ArchNames;
+ if (C.getDefaultToolChain().getTriple().isOSDarwin()) {
+ for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
+ it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().matches(options::OPT_arch))
+ ArchNames.insert(A->getValue());
+ }
+ }
+
for (ActionList::const_iterator it = C.getActions().begin(),
ie = C.getActions().end(); it != ie; ++it) {
Action *A = *it;
@@ -1237,6 +1242,7 @@ void Driver::BuildJobs(Compilation &C) const {
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
/*BoundArch*/0,
/*AtTopLevel*/ true,
+ /*MultipleArchs*/ ArchNames.size() > 1,
/*LinkingOutput*/ LinkingOutput,
II);
}
@@ -1285,7 +1291,7 @@ void Driver::BuildJobs(Compilation &C) const {
}
}
-static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
+static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
const JobAction *JA,
const ActionList *&Inputs) {
const Tool *ToolForJob = 0;
@@ -1294,23 +1300,23 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
// bottom up, so what we are actually looking for is an assembler job with a
// compiler input.
- if (C.getArgs().hasFlag(options::OPT_integrated_as,
- options::OPT_no_integrated_as,
- TC->IsIntegratedAssemblerDefault()) &&
+ if (TC->useIntegratedAs() &&
!C.getArgs().hasArg(options::OPT_save_temps) &&
isa<AssembleJobAction>(JA) &&
Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
- const Tool &Compiler = TC->SelectTool(
- C, cast<JobAction>(**Inputs->begin()), (*Inputs)[0]->getInputs());
- if (Compiler.hasIntegratedAssembler()) {
+ const Tool *Compiler =
+ TC->SelectTool(cast<JobAction>(**Inputs->begin()));
+ if (!Compiler)
+ return NULL;
+ if (Compiler->hasIntegratedAssembler()) {
Inputs = &(*Inputs)[0]->getInputs();
- ToolForJob = &Compiler;
+ ToolForJob = Compiler;
}
}
// Otherwise use the tool for the current job.
if (!ToolForJob)
- ToolForJob = &TC->SelectTool(C, *JA, *Inputs);
+ ToolForJob = TC->SelectTool(*JA);
// See if we should use an integrated preprocessor. We do so when we have
// exactly one input, since this is the only use case we care about
@@ -1323,7 +1329,7 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC,
ToolForJob->hasIntegratedCPP())
Inputs = &(*Inputs)[0]->getInputs();
- return *ToolForJob;
+ return ToolForJob;
}
void Driver::BuildJobsForAction(Compilation &C,
@@ -1331,6 +1337,7 @@ void Driver::BuildJobsForAction(Compilation &C,
const ToolChain *TC,
const char *BoundArch,
bool AtTopLevel,
+ bool MultipleArchs,
const char *LinkingOutput,
InputInfo &Result) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
@@ -1358,14 +1365,16 @@ void Driver::BuildJobsForAction(Compilation &C,
TC = &C.getDefaultToolChain();
BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
- AtTopLevel, LinkingOutput, Result);
+ AtTopLevel, MultipleArchs, LinkingOutput, Result);
return;
}
const ActionList *Inputs = &A->getInputs();
const JobAction *JA = cast<JobAction>(A);
- const Tool &T = SelectToolForJob(C, TC, JA, Inputs);
+ const Tool *T = SelectToolForJob(C, TC, JA, Inputs);
+ if (!T)
+ return;
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
@@ -1379,8 +1388,8 @@ void Driver::BuildJobsForAction(Compilation &C,
SubJobAtTopLevel = true;
InputInfo II;
- BuildJobsForAction(C, *it, TC, BoundArch,
- SubJobAtTopLevel, LinkingOutput, II);
+ BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
+ LinkingOutput, II);
InputInfos.push_back(II);
}
@@ -1396,12 +1405,13 @@ void Driver::BuildJobsForAction(Compilation &C,
if (JA->getType() == types::TY_Nothing)
Result = InputInfo(A->getType(), BaseInput);
else
- Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel),
+ Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
+ AtTopLevel, MultipleArchs),
A->getType(), BaseInput);
if (CCCPrintBindings && !CCGenDiagnostics) {
- llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"'
- << " - \"" << T.getName() << "\", inputs: [";
+ llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
+ << " - \"" << T->getName() << "\", inputs: [";
for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
llvm::errs() << InputInfos[i].getAsString();
if (i + 1 != e)
@@ -1409,15 +1419,17 @@ void Driver::BuildJobsForAction(Compilation &C,
}
llvm::errs() << "], output: " << Result.getAsString() << "\n";
} else {
- T.ConstructJob(C, *JA, Result, InputInfos,
- C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
+ T->ConstructJob(C, *JA, Result, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
}
}
const char *Driver::GetNamedOutputPath(Compilation &C,
const JobAction &JA,
const char *BaseInput,
- bool AtTopLevel) const {
+ const char *BoundArch,
+ bool AtTopLevel,
+ bool MultipleArchs) const {
llvm::PrettyStackTraceString CrashInfo("Computing output path");
// Output to a user requested destination?
if (AtTopLevel && !isa<DsymutilJobAction>(JA) &&
@@ -1427,7 +1439,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
}
// Default to writing to stdout?
- if (AtTopLevel && isa<PreprocessJobAction>(JA) && !CCGenDiagnostics)
+ if (AtTopLevel && !CCGenDiagnostics &&
+ (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
return "-";
// Output to a temporary file?
@@ -1451,8 +1464,14 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
// Determine what the derived output name should be.
const char *NamedOutput;
- if (JA.getType() == types::TY_Image) {
- NamedOutput = DefaultImageName.c_str();
+ if (JA.getType() == types::TY_Image) {
+ if (MultipleArchs && BoundArch) {
+ SmallString<128> Output(DefaultImageName.c_str());
+ Output += "-";
+ Output.append(BoundArch);
+ NamedOutput = C.getArgs().MakeArgString(Output.c_str());
+ } else
+ NamedOutput = DefaultImageName.c_str();
} else {
const char *Suffix = types::getTypeTempSuffix(JA.getType());
assert(Suffix && "All types used for output should have a suffix.");
@@ -1460,7 +1479,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
std::string::size_type End = std::string::npos;
if (!types::appendSuffixForType(JA.getType()))
End = BaseName.rfind('.');
- std::string Suffixed(BaseName.substr(0, End));
+ SmallString<128> Suffixed(BaseName.substr(0, End));
+ if (MultipleArchs && BoundArch) {
+ Suffixed += "-";
+ Suffixed.append(BoundArch);
+ }
Suffixed += '.';
Suffixed += Suffix;
NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
@@ -1644,6 +1667,21 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
}
}
+ // Handle pseudo-target flags '-EL' and '-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_EL, options::OPT_EB)) {
+ if (A->getOption().matches(options::OPT_EL)) {
+ if (Target.getArch() == llvm::Triple::mips)
+ Target.setArch(llvm::Triple::mipsel);
+ else if (Target.getArch() == llvm::Triple::mips64)
+ Target.setArch(llvm::Triple::mips64el);
+ } else {
+ if (Target.getArch() == llvm::Triple::mipsel)
+ Target.setArch(llvm::Triple::mips);
+ else if (Target.getArch() == llvm::Triple::mips64el)
+ Target.setArch(llvm::Triple::mips64);
+ }
+ }
+
// Skip further flag support on OSes which don't support '-m32' or '-m64'.
if (Target.getArchName() == "tce" ||
Target.getOS() == llvm::Triple::AuroraUX ||
@@ -1687,7 +1725,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
Target.getArch() == llvm::Triple::x86_64 ||
Target.getArch() == llvm::Triple::arm ||
Target.getArch() == llvm::Triple::thumb)
- TC = new toolchains::DarwinClang(*this, Target);
+ TC = new toolchains::DarwinClang(*this, Target, Args);
else
TC = new toolchains::Darwin_Generic_GCC(*this, Target, Args);
break;
@@ -1719,17 +1757,21 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Solaris(*this, Target, Args);
break;
case llvm::Triple::Win32:
- TC = new toolchains::Windows(*this, Target);
+ TC = new toolchains::Windows(*this, Target, Args);
break;
case llvm::Triple::MinGW32:
// FIXME: We need a MinGW toolchain. Fallthrough for now.
default:
// TCE is an OSless target
if (Target.getArchName() == "tce") {
- TC = new toolchains::TCEToolChain(*this, Target);
+ TC = new toolchains::TCEToolChain(*this, Target, Args);
+ break;
+ }
+ // If Hexagon is configured as an OSless target
+ if (Target.getArch() == llvm::Triple::hexagon) {
+ TC = new toolchains::Hexagon_TC(*this, Target, Args);
break;
}
-
TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
}
@@ -1737,8 +1779,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
return *TC;
}
-bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
- const llvm::Triple &Triple) const {
+bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
// Check if user requested no clang, or clang doesn't understand this type (we
// only handle single inputs for now).
if (JA.size() != 1 ||
diff --git a/lib/Driver/SanitizerArgs.h b/lib/Driver/SanitizerArgs.h
index c3d84f9a4f..326d80db72 100644
--- a/lib/Driver/SanitizerArgs.h
+++ b/lib/Driver/SanitizerArgs.h
@@ -38,7 +38,8 @@ class SanitizerArgs {
NeedsTsanRt = Thread,
NeedsMsanRt = Memory,
NeedsUbsanRt = Undefined | Integer,
- NotAllowedWithTrap = Vptr
+ NotAllowedWithTrap = Vptr,
+ HasZeroBaseShadow = Thread | Memory
};
unsigned Kind;
std::string BlacklistFile;
@@ -50,7 +51,7 @@ class SanitizerArgs {
SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
AsanZeroBaseShadow(false), UbsanTrapOnError(false) {}
/// Parses the sanitizer arguments from an argument list.
- SanitizerArgs(const Driver &D, const ArgList &Args);
+ SanitizerArgs(const ToolChain &TC, const ArgList &Args);
bool needsAsanRt() const { return Kind & NeedsAsanRt; }
bool needsTsanRt() const { return Kind & NeedsTsanRt; }
@@ -63,6 +64,9 @@ class SanitizerArgs {
bool sanitizesVptr() const { return Kind & Vptr; }
bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; }
+ bool hasZeroBaseShadow() const {
+ return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow;
+ }
void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
if (!Kind)
@@ -90,14 +94,20 @@ class SanitizerArgs {
private:
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
- /// Returns a member of the \c SanitizeKind enumeration, or \c 0 if \p Value
- /// is not known.
+ /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0
+ /// if \p Value is not known.
static unsigned parse(const char *Value) {
- return llvm::StringSwitch<SanitizeKind>(Value)
+ unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
#define SANITIZER(NAME, ID) .Case(NAME, ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID)
#include "clang/Basic/Sanitizers.def"
.Default(SanitizeKind());
+ // Assume -fsanitize=address implies -fsanitize=init-order.
+ // FIXME: This should be either specified in Sanitizers.def, or go away when
+ // we get rid of "-fsanitize=init-order" flag at all.
+ if (ParsedKind & Address)
+ ParsedKind |= InitOrder;
+ return ParsedKind;
}
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 21015a6c84..71f53933e2 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Tools.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Driver/Action.h"
@@ -18,11 +19,13 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
using namespace clang::driver;
using namespace clang;
-ToolChain::ToolChain(const Driver &D, const llvm::Triple &T)
- : D(D), Triple(T) {
+ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
+ const ArgList &A)
+ : D(D), Triple(T), Args(A) {
}
ToolChain::~ToolChain() {
@@ -32,6 +35,12 @@ const Driver &ToolChain::getDriver() const {
return D;
}
+bool ToolChain::useIntegratedAs() const {
+ return Args.hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+}
+
std::string ToolChain::getDefaultUniversalArchName() const {
// In universal driver terms, the arch name accepted by -arch isn't exactly
// the same as the ones that appear in the triple. Roughly speaking, this is
@@ -51,6 +60,73 @@ bool ToolChain::IsUnwindTablesDefault() const {
return false;
}
+Tool *ToolChain::getClang() const {
+ if (!Clang)
+ Clang.reset(new tools::Clang(*this));
+ return Clang.get();
+}
+
+Tool *ToolChain::buildAssembler() const {
+ return new tools::ClangAs(*this);
+}
+
+Tool *ToolChain::buildLinker() const {
+ llvm_unreachable("Linking is not supported by this toolchain");
+}
+
+Tool *ToolChain::getAssemble() const {
+ if (!Assemble)
+ Assemble.reset(buildAssembler());
+ return Assemble.get();
+}
+
+Tool *ToolChain::getClangAs() const {
+ if (!Assemble)
+ Assemble.reset(new tools::ClangAs(*this));
+ return Assemble.get();
+}
+
+Tool *ToolChain::getLink() const {
+ if (!Link)
+ Link.reset(buildLinker());
+ return Link.get();
+}
+
+Tool *ToolChain::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::AssembleJobClass:
+ return getAssemble();
+
+ case Action::LinkJobClass:
+ return getLink();
+
+ case Action::InputClass:
+ case Action::BindArchClass:
+ case Action::LipoJobClass:
+ case Action::DsymutilJobClass:
+ case Action::VerifyJobClass:
+ llvm_unreachable("Invalid tool kind.");
+
+ case Action::CompileJobClass:
+ case Action::PrecompileJobClass:
+ case Action::PreprocessJobClass:
+ case Action::AnalyzeJobClass:
+ case Action::MigrateJobClass:
+ return getClang();
+ }
+
+ llvm_unreachable("Invalid tool kind.");
+}
+
+Tool *ToolChain::SelectTool(const JobAction &JA) const {
+ if (getDriver().ShouldUseClangCompiler(JA))
+ return getClang();
+ Action::ActionClass AC = JA.getKind();
+ if (AC == Action::AssembleJobClass && useIntegratedAs())
+ return getClangAs();
+ return getTool(AC);
+}
+
std::string ToolChain::GetFilePath(const char *Name) const {
return D.GetFilePath(Name, *this);
@@ -258,6 +334,13 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
+void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ const Twine &Path) {
+ if (llvm::sys::fs::exists(Path))
+ addExternCSystemInclude(DriverArgs, CC1Args, Path);
+}
+
/// \brief Utility function to add a list of system include directories to CC1.
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 035af21975..fffba0e4e5 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -42,8 +42,8 @@ using namespace clang;
/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin::Darwin(const Driver &D, const llvm::Triple& Triple)
- : ToolChain(D, Triple), TargetInitialized(false)
+Darwin::Darwin(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : ToolChain(D, Triple, Args), TargetInitialized(false)
{
// Compute the initial Darwin version from the triple
unsigned Major, Minor, Micro;
@@ -151,10 +151,6 @@ StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
}
Darwin::~Darwin() {
- // Free tool implementations.
- for (llvm::DenseMap<unsigned, Tool*>::iterator
- it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
- delete it->second;
}
std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
@@ -176,55 +172,36 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
void Generic_ELF::anchor() {}
-Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key = JA.getKind();
-
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) {
- // FIXME: This seems like a hacky way to choose clang frontend.
- Key = Action::AnalyzeJobClass;
- }
-
- 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::InputClass:
- case Action::BindArchClass:
- llvm_unreachable("Invalid tool kind.");
- case Action::PreprocessJobClass:
- case Action::AnalyzeJobClass:
- case Action::MigrateJobClass:
- case Action::PrecompileJobClass:
- case Action::CompileJobClass:
- T = new tools::Clang(*this); break;
- case Action::AssembleJobClass: {
- if (UseIntegratedAs)
- T = new tools::ClangAs(*this);
- else
- T = new tools::darwin::Assemble(*this);
- break;
- }
- case Action::LinkJobClass:
- T = new tools::darwin::Link(*this); break;
- case Action::LipoJobClass:
- T = new tools::darwin::Lipo(*this); break;
- case Action::DsymutilJobClass:
- T = new tools::darwin::Dsymutil(*this); break;
- case Action::VerifyJobClass:
- T = new tools::darwin::VerifyDebug(*this); break;
- }
+Tool *Darwin::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::LipoJobClass:
+ if (!Lipo)
+ Lipo.reset(new tools::darwin::Lipo(*this));
+ return Lipo.get();
+ case Action::DsymutilJobClass:
+ if (!Dsymutil)
+ Dsymutil.reset(new tools::darwin::Dsymutil(*this));
+ return Dsymutil.get();
+ case Action::VerifyJobClass:
+ if (!VerifyDebug)
+ VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
+ return VerifyDebug.get();
+ default:
+ return ToolChain::getTool(AC);
}
+}
- return *T;
+Tool *Darwin::buildLinker() const {
+ return new tools::darwin::Link(*this);
}
+Tool *Darwin::buildAssembler() const {
+ return new tools::darwin::Assemble(*this);
+}
-DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple)
- : Darwin(D, Triple)
+DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : Darwin(D, Triple, Args)
{
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -317,7 +294,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
- SanitizerArgs Sanitize(getDriver(), Args);
+ SanitizerArgs Sanitize(*this, Args);
// Add Ubsan runtime library, if required.
if (Sanitize.needsUbsanRt()) {
@@ -335,17 +312,19 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
// Add ASAN runtime library, if required. Dynamic libraries and bundles
// should not be linked with the runtime library.
if (Sanitize.needsAsanRt()) {
- if (Args.hasArg(options::OPT_dynamiclib) ||
- Args.hasArg(options::OPT_bundle)) {
- // Assume the binary will provide the ASan runtime.
- } else if (isTargetIPhoneOS()) {
+ if (isTargetIPhoneOS() && !isTargetIOSSimulator()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
<< "-fsanitize=address";
} else {
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_osx_dynamic.dylib", true);
-
- // The ASAN runtime library requires C++.
- AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_dynamiclib) ||
+ Args.hasArg(options::OPT_bundle)) {
+ // Assume the binary will provide the ASan runtime.
+ } else {
+ AddLinkRuntimeLib(Args, CmdArgs,
+ "libclang_rt.asan_osx_dynamic.dylib", true);
+ // The ASAN runtime library requires C++.
+ AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
}
}
@@ -899,6 +878,10 @@ bool Darwin::isPICDefault() const {
return true;
}
+bool Darwin::isPIEDefault() const {
+ return false;
+}
+
bool Darwin::isPICDefaultForced() const {
return getArch() == llvm::Triple::x86_64;
}
@@ -1103,6 +1086,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
};
static const char *const ARMHFTriples[] = {
"arm-linux-gnueabihf",
+ "armv7hl-redhat-linux-gnueabi"
};
static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
@@ -1137,7 +1121,8 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
static const char *const MIPSELLibDirs[] = { "/lib" };
static const char *const MIPSELTriples[] = {
"mipsel-linux-gnu",
- "mipsel-linux-android"
+ "mipsel-linux-android",
+ "mips-linux-gnu"
};
static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
@@ -1149,6 +1134,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
static const char *const PPCTriples[] = {
"powerpc-linux-gnu",
"powerpc-unknown-linux-gnu",
+ "powerpc-linux-gnuspe",
"powerpc-suse-linux",
"powerpc-montavista-linuxspe"
};
@@ -1160,6 +1146,15 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
"ppc64-redhat-linux"
};
+ static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
+ static const char *const SystemZTriples[] = {
+ "s390x-linux-gnu",
+ "s390x-unknown-linux-gnu",
+ "s390x-ibm-linux-gnu",
+ "s390x-suse-linux",
+ "s390x-redhat-linux"
+ };
+
switch (TargetTriple.getArch()) {
case llvm::Triple::aarch64:
LibDirs.append(AArch64LibDirs, AArch64LibDirs
@@ -1260,6 +1255,12 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
MultiarchTripleAliases.append(
PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
break;
+ case llvm::Triple::systemz:
+ LibDirs.append(
+ SystemZLibDirs, SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
+ TripleAliases.append(
+ SystemZTriples, SystemZTriples + llvm::array_lengthof(SystemZTriples));
+ break;
default:
// By default, just rely on the standard lib directories and the original
@@ -1276,29 +1277,102 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
MultiarchTripleAliases.push_back(MultiarchTriple.str());
}
+static bool isSoftFloatABI(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ);
+ if (!A) return false;
+
+ return A->getOption().matches(options::OPT_msoft_float) ||
+ (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
+ A->getValue() == StringRef("soft"));
+}
+
+static bool isMipsArch(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mips ||
+ Arch == llvm::Triple::mipsel ||
+ Arch == llvm::Triple::mips64 ||
+ Arch == llvm::Triple::mips64el;
+}
+
+static bool isMips16(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mips16,
+ options::OPT_mno_mips16);
+ return A && A->getOption().matches(options::OPT_mips16);
+}
+
+static bool isMicroMips(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mmicromips,
+ options::OPT_mno_micromips);
+ return A && A->getOption().matches(options::OPT_mmicromips);
+}
+
// FIXME: There is the same routine in the Tools.cpp.
static bool hasMipsN32ABIArg(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
return A && (A->getValue() == StringRef("n32"));
}
-static StringRef getTargetMultiarchSuffix(llvm::Triple::ArchType TargetArch,
- const ArgList &Args) {
- if (TargetArch == llvm::Triple::x86_64 ||
- TargetArch == llvm::Triple::ppc64)
- return "/64";
+static void appendMipsTargetSuffix(std::string &Path,
+ llvm::Triple::ArchType TargetArch,
+ const ArgList &Args) {
+ if (isMips16(Args))
+ Path += "/mips16";
+ else if (isMicroMips(Args))
+ Path += "/micromips";
+
+ if (isSoftFloatABI(Args))
+ Path += "/soft-float";
+ if (TargetArch == llvm::Triple::mipsel ||
+ TargetArch == llvm::Triple::mips64el)
+ Path += "/el";
+}
+
+static StringRef getMipsTargetABISuffix(llvm::Triple::ArchType TargetArch,
+ const ArgList &Args) {
if (TargetArch == llvm::Triple::mips64 ||
- TargetArch == llvm::Triple::mips64el) {
- if (hasMipsN32ABIArg(Args))
- return "/n32";
- else
- return "/64";
- }
+ TargetArch == llvm::Triple::mips64el)
+ return hasMipsN32ABIArg(Args) ? "/n32" : "/64";
return "/32";
}
+static bool findTargetMultiarchSuffix(std::string &Suffix,
+ StringRef Path,
+ llvm::Triple::ArchType TargetArch,
+ const ArgList &Args) {
+ if (isMipsArch(TargetArch)) {
+ StringRef ABISuffix = getMipsTargetABISuffix(TargetArch, Args);
+
+ // First build and check a complex path to crtbegin.o
+ // depends on command line options (-mips16, -msoft-float, ...)
+ // like mips-linux-gnu/4.7/mips16/soft-float/el/crtbegin.o
+ appendMipsTargetSuffix(Suffix, TargetArch, Args);
+
+ if (TargetArch == llvm::Triple::mips64 ||
+ TargetArch == llvm::Triple::mips64el)
+ Suffix += ABISuffix;
+
+ if (llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o"))
+ return true;
+
+ // Then fall back and probe a simple case like
+ // mips-linux-gnu/4.7/32/crtbegin.o
+ Suffix = ABISuffix;
+ return llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o");
+ }
+
+ if (TargetArch == llvm::Triple::x86_64 ||
+ TargetArch == llvm::Triple::ppc64 ||
+ TargetArch == llvm::Triple::systemz)
+ Suffix = "/64";
+ else
+ Suffix = "/32";
+
+ return llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o");
+}
+
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
llvm::Triple::ArchType TargetArch, const ArgList &Args,
const std::string &LibDir,
@@ -1348,9 +1422,11 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// *if* there is a subdirectory of the right name with crtbegin.o in it,
// we use that. If not, and if not a multiarch triple, we look for
// crtbegin.o without the subdirectory.
- StringRef MultiarchSuffix = getTargetMultiarchSuffix(TargetArch, Args);
- if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) {
- GCCMultiarchSuffix = MultiarchSuffix.str();
+
+ std::string MultiarchSuffix;
+ if (findTargetMultiarchSuffix(MultiarchSuffix,
+ LI->path(), TargetArch, Args)) {
+ GCCMultiarchSuffix = MultiarchSuffix;
} else {
if (NeedsMultiarchSuffix ||
!llvm::sys::fs::exists(LI->path() + "/crtbegin.o"))
@@ -1372,60 +1448,40 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
- : ToolChain(D, Triple), GCCInstallation(getDriver(), Triple, Args) {
+ : ToolChain(D, Triple, Args), GCCInstallation(getDriver(), Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
Generic_GCC::~Generic_GCC() {
- // Free tool implementations.
- for (llvm::DenseMap<unsigned, Tool*>::iterator
- it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
- delete it->second;
-}
-
-Tool &Generic_GCC::SelectTool(const Compilation &C,
- const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::InputClass:
- case Action::BindArchClass:
- llvm_unreachable("Invalid tool kind.");
- case Action::PreprocessJobClass:
- T = new tools::gcc::Preprocess(*this); break;
- case Action::PrecompileJobClass:
- T = new tools::gcc::Precompile(*this); break;
- case Action::AnalyzeJobClass:
- case Action::MigrateJobClass:
- T = new tools::Clang(*this); break;
- case Action::CompileJobClass:
- T = new tools::gcc::Compile(*this); break;
- case Action::AssembleJobClass:
- T = new tools::gcc::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::gcc::Link(*this); break;
-
- // This is a bit ungeneric, but the only platform using a driver
- // driver is Darwin.
- case Action::LipoJobClass:
- T = new tools::darwin::Lipo(*this); break;
- case Action::DsymutilJobClass:
- T = new tools::darwin::Dsymutil(*this); break;
- case Action::VerifyJobClass:
- T = new tools::darwin::VerifyDebug(*this); break;
- }
+}
+
+Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::PreprocessJobClass:
+ if (!Preprocess)
+ Preprocess.reset(new tools::gcc::Preprocess(*this));
+ return Preprocess.get();
+ case Action::PrecompileJobClass:
+ if (!Precompile)
+ Precompile.reset(new tools::gcc::Precompile(*this));
+ return Precompile.get();
+ case Action::CompileJobClass:
+ if (!Compile)
+ Compile.reset(new tools::gcc::Compile(*this));
+ return Compile.get();
+ default:
+ return ToolChain::getTool(AC);
}
+}
- return *T;
+Tool *Generic_GCC::buildAssembler() const {
+ return new tools::gcc::Assemble(*this);
+}
+
+Tool *Generic_GCC::buildLinker() const {
+ return new tools::gcc::Link(*this);
}
bool Generic_GCC::IsUnwindTablesDefault() const {
@@ -1436,6 +1492,10 @@ bool Generic_GCC::isPICDefault() const {
return false;
}
+bool Generic_GCC::isPIEDefault() const {
+ return false;
+}
+
bool Generic_GCC::isPICDefaultForced() const {
return false;
}
@@ -1550,47 +1610,14 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
}
Hexagon_TC::~Hexagon_TC() {
- // Free tool implementations.
- for (llvm::DenseMap<unsigned, Tool*>::iterator
- it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
- delete it->second;
-}
-
-Tool &Hexagon_TC::SelectTool(const Compilation &C,
- const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- // if (JA.getKind () == Action::CompileJobClass)
- // Key = JA.getKind ();
- // else
-
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
- // if ((JA.getKind () == Action::CompileJobClass)
- // && (JA.getType () != types::TY_LTO_BC)) {
- // Key = JA.getKind ();
- // }
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::InputClass:
- case Action::BindArchClass:
- assert(0 && "Invalid tool kind.");
- case Action::AnalyzeJobClass:
- T = new tools::Clang(*this); break;
- case Action::AssembleJobClass:
- T = new tools::hexagon::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::hexagon::Link(*this); break;
- default:
- assert(false && "Unsupported action for Hexagon target.");
- }
- }
+}
+
+Tool *Hexagon_TC::buildAssembler() const {
+ return new tools::hexagon::Assemble(*this);
+}
- return *T;
+Tool *Hexagon_TC::buildLinker() const {
+ return new tools::hexagon::Link(*this);
}
void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -1682,8 +1709,9 @@ StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
/// Currently does not support anything else but compilation.
-TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple)
- : ToolChain(D, Triple) {
+TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
// Path mangling to find libexec
std::string Path(getDriver().Dir);
@@ -1692,9 +1720,6 @@ TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple)
}
TCEToolChain::~TCEToolChain() {
- for (llvm::DenseMap<unsigned, Tool*>::iterator
- it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
- delete it->second;
}
bool TCEToolChain::IsMathErrnoDefault() const {
@@ -1705,28 +1730,12 @@ bool TCEToolChain::isPICDefault() const {
return false;
}
-bool TCEToolChain::isPICDefaultForced() const {
+bool TCEToolChain::isPIEDefault() const {
return false;
}
-Tool &TCEToolChain::SelectTool(const Compilation &C,
- const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- Key = Action::AnalyzeJobClass;
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::PreprocessJobClass:
- T = new tools::gcc::Preprocess(*this); break;
- case Action::AnalyzeJobClass:
- T = new tools::Clang(*this); break;
- default:
- llvm_unreachable("Unsupported action for TCE target.");
- }
- }
- return *T;
+bool TCEToolChain::isPICDefaultForced() const {
+ return false;
}
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
@@ -1737,36 +1746,12 @@ OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg
getFilePaths().push_back("/usr/lib");
}
-Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- 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::openbsd::Assemble(*this);
- break;
- }
- case Action::LinkJobClass:
- T = new tools::openbsd::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *OpenBSD::buildAssembler() const {
+ return new tools::openbsd::Assemble(*this);
+}
- return *T;
+Tool *OpenBSD::buildLinker() const {
+ return new tools::openbsd::Link(*this);
}
/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
@@ -1777,36 +1762,12 @@ Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
getFilePaths().push_back("/usr/lib");
}
-Tool &Bitrig::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) 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::bitrig::Assemble(*this);
- break;
- }
- case Action::LinkJobClass:
- T = new tools::bitrig::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *Bitrig::buildAssembler() const {
+ return new tools::bitrig::Assemble(*this);
+}
- return *T;
+Tool *Bitrig::buildLinker() const {
+ return new tools::bitrig::Link(*this);
}
void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
@@ -1869,35 +1830,12 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
-Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- 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::freebsd::Assemble(*this);
- break;
- case Action::LinkJobClass:
- T = new tools::freebsd::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *FreeBSD::buildAssembler() const {
+ return new tools::freebsd::Assemble(*this);
+}
- return *T;
+Tool *FreeBSD::buildLinker() const {
+ return new tools::freebsd::Link(*this);
}
bool FreeBSD::UseSjLjExceptions() const {
@@ -1931,36 +1869,48 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
}
}
-Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- 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, Inputs);
- }
+Tool *NetBSD::buildAssembler() const {
+ return new tools::netbsd::Assemble(*this);
+}
+
+Tool *NetBSD::buildLinker() const {
+ return new tools::netbsd::Link(*this);
+}
+
+ToolChain::CXXStdlibType
+NetBSD::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
}
- return *T;
+ return ToolChain::CST_Libstdcxx;
+}
+
+void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/g++");
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/g++/backward");
+ break;
+ }
}
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
@@ -1971,27 +1921,12 @@ Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
getFilePaths().push_back("/usr/lib");
}
-Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::AssembleJobClass:
- T = new tools::minix::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::minix::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *Minix::buildAssembler() const {
+ return new tools::minix::Assemble(*this);
+}
- return *T;
+Tool *Minix::buildLinker() const {
+ return new tools::minix::Link(*this);
}
/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
@@ -2012,27 +1947,12 @@ AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple,
}
-Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::AssembleJobClass:
- T = new tools::auroraux::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::auroraux::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *AuroraUX::buildAssembler() const {
+ return new tools::auroraux::Assemble(*this);
+}
- return *T;
+Tool *AuroraUX::buildLinker() const {
+ return new tools::auroraux::Link(*this);
}
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
@@ -2049,32 +1969,17 @@ Solaris::Solaris(const Driver &D, const llvm::Triple& Triple,
getFilePaths().push_back("/usr/lib");
}
-Tool &Solaris::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::AssembleJobClass:
- T = new tools::solaris::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::solaris::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *Solaris::buildAssembler() const {
+ return new tools::solaris::Assemble(*this);
+}
- return *T;
+Tool *Solaris::buildLinker() const {
+ return new tools::solaris::Link(*this);
}
-/// Linux toolchain (very bare-bones at the moment).
+/// Distribution (very bare-bones at the moment).
-enum LinuxDistro {
+enum Distro {
ArchLinux,
DebianLenny,
DebianSqueeze,
@@ -2107,33 +2012,33 @@ enum LinuxDistro {
UnknownDistro
};
-static bool IsRedhat(enum LinuxDistro Distro) {
+static bool IsRedhat(enum Distro Distro) {
return (Distro >= Fedora13 && Distro <= FedoraRawhide) ||
(Distro >= RHEL4 && Distro <= RHEL6);
}
-static bool IsOpenSuse(enum LinuxDistro Distro) {
+static bool IsOpenSuse(enum Distro Distro) {
return Distro >= OpenSuse11_3 && Distro <= OpenSuse12_2;
}
-static bool IsDebian(enum LinuxDistro Distro) {
+static bool IsDebian(enum Distro Distro) {
return Distro >= DebianLenny && Distro <= DebianJessie;
}
-static bool IsUbuntu(enum LinuxDistro Distro) {
+static bool IsUbuntu(enum Distro Distro) {
return Distro >= UbuntuHardy && Distro <= UbuntuRaring;
}
-static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
+static Distro DetectDistro(llvm::Triple::ArchType Arch) {
OwningPtr<llvm::MemoryBuffer> File;
if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) {
StringRef Data = File.get()->getBuffer();
SmallVector<StringRef, 8> Lines;
Data.split(Lines, "\n");
- LinuxDistro Version = UnknownDistro;
+ Distro Version = UnknownDistro;
for (unsigned i = 0, s = Lines.size(); i != s; ++i)
if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME="))
- Version = llvm::StringSwitch<LinuxDistro>(Lines[i].substr(17))
+ Version = llvm::StringSwitch<Distro>(Lines[i].substr(17))
.Case("hardy", UbuntuHardy)
.Case("intrepid", UbuntuIntrepid)
.Case("jaunty", UbuntuJaunty)
@@ -2190,7 +2095,7 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
}
if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File))
- return llvm::StringSwitch<LinuxDistro>(File.get()->getBuffer())
+ return llvm::StringSwitch<Distro>(File.get()->getBuffer())
.StartsWith("openSUSE 11.3", OpenSuse11_3)
.StartsWith("openSUSE 11.4", OpenSuse11_4)
.StartsWith("openSUSE 12.1", OpenSuse12_1)
@@ -2255,6 +2160,8 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple,
return "mipsel-linux-gnu";
return TargetTriple.str();
case llvm::Triple::ppc:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
+ return "powerpc-linux-gnuspe";
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu"))
return "powerpc-linux-gnu";
return TargetTriple.str();
@@ -2269,13 +2176,6 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
}
-static bool isMipsArch(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips ||
- Arch == llvm::Triple::mipsel ||
- Arch == llvm::Triple::mips64 ||
- Arch == llvm::Triple::mips64el;
-}
-
static bool isMipsR2Arch(llvm::Triple::ArchType Arch,
const ArgList &Args) {
if (Arch != llvm::Triple::mips &&
@@ -2312,7 +2212,7 @@ static StringRef getMultilibDir(const llvm::Triple &Triple,
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
llvm::Triple::ArchType Arch = Triple.getArch();
- const std::string &SysRoot = getDriver().SysRoot;
+ std::string SysRoot = computeSysRoot(Args);
// OpenSuse stores the linker with the compiler, add that to the search
// path.
@@ -2322,7 +2222,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Linker = GetProgramPath("ld");
- LinuxDistro Distro = DetectLinuxDistro(Arch);
+ Distro Distro = DetectDistro(Arch);
if (IsOpenSuse(Distro) || IsUbuntu(Distro)) {
ExtraOpts.push_back("-z");
@@ -2333,13 +2233,17 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("-X");
const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android;
+ const bool IsMips = isMipsArch(Arch);
+
+ if (IsMips && !SysRoot.empty())
+ ExtraOpts.push_back("--sysroot=" + SysRoot);
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
// and the MIPS ABI require .dynsym to be sorted in different ways.
// .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
// ABI requires a mapping between the GOT and the symbol table.
// Android loader does not support .gnu.hash.
- if (!isMipsArch(Arch) && !IsAndroid) {
+ if (!IsMips && !IsAndroid) {
if (IsRedhat(Distro) || IsOpenSuse(Distro) ||
(IsUbuntu(Distro) && Distro >= UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
@@ -2404,6 +2308,15 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (IsAndroid) {
addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths);
}
+ // Sourcery CodeBench MIPS toolchain holds some libraries under
+ // the parent prefix of the GCC installation.
+ if (IsMips) {
+ std::string Suffix;
+ appendMipsTargetSuffix(Suffix, Arch, Args);
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" +
+ Multilib + Suffix,
+ Paths);
+ }
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths);
@@ -2430,41 +2343,20 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
}
addPathIfExists(SysRoot + "/lib", Paths);
addPathIfExists(SysRoot + "/usr/lib", Paths);
+
+ IsPIEDefault = SanitizerArgs(*this, Args).hasZeroBaseShadow();
}
bool Linux::HasNativeLLVMSupport() const {
return true;
}
-Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- 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::linuxtools::Assemble(*this);
- break;
- case Action::LinkJobClass:
- T = new tools::linuxtools::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *Linux::buildLinker() const {
+ return new tools::gnutools::Link(*this);
+}
- return *T;
+Tool *Linux::buildAssembler() const {
+ return new tools::gnutools::Assemble(*this);
}
void Linux::addClangTargetOptions(const ArgList &DriverArgs,
@@ -2480,15 +2372,31 @@ void Linux::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-fuse-init-array");
}
+std::string Linux::computeSysRoot(const ArgList &Args) const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ if (!GCCInstallation.isValid() || !isMipsArch(getTriple().getArch()))
+ return std::string();
+
+ std::string Path =
+ (GCCInstallation.getInstallPath() +
+ "/../../../../" + GCCInstallation.getTriple().str() + "/libc").str();
+ appendMipsTargetSuffix(Path, getTriple().getArch(), Args);
+
+ return llvm::sys::fs::exists(Path) ? Path : "";
+}
+
void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot(DriverArgs);
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
- addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/local/include");
+ addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
llvm::sys::Path P(D.ResourceDir);
@@ -2506,7 +2414,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(dirs, ":");
for (SmallVectorImpl<StringRef>::iterator I = dirs.begin(), E = dirs.end();
I != E; ++I) {
- StringRef Prefix = llvm::sys::path::is_absolute(*I) ? D.SysRoot : "";
+ StringRef Prefix = llvm::sys::path::is_absolute(*I) ? SysRoot : "";
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + *I);
}
return;
@@ -2515,6 +2423,20 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Lacking those, try to detect the correct set of system includes for the
// target triple.
+ // Sourcery CodeBench and modern FSF Mips toolchains put extern C
+ // system includes under three additional directories.
+ if (GCCInstallation.isValid() && isMipsArch(getTriple().getArch())) {
+ addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() +
+ "/include");
+
+ addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() +
+ "/../../../../" +
+ GCCInstallation.getTriple().str() +
+ "/libc/usr/include");
+ }
+
// Implement generic Debian multiarch support.
const StringRef X86_64MultiarchIncludeDirs[] = {
"/usr/include/x86_64-linux-gnu",
@@ -2580,8 +2502,8 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
for (ArrayRef<StringRef>::iterator I = MultiarchIncludeDirs.begin(),
E = MultiarchIncludeDirs.end();
I != E; ++I) {
- if (llvm::sys::fs::exists(D.SysRoot + *I)) {
- addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + *I);
+ if (llvm::sys::fs::exists(SysRoot + *I)) {
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + *I);
break;
}
}
@@ -2592,9 +2514,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
// add even when Clang is acting as-if it were a system compiler.
- addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
- addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
/// \brief Helper to add the three variant paths for a libstdc++ installation.
@@ -2678,6 +2600,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
+bool Linux::isPIEDefault() const {
+ return IsPIEDefault;
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -2690,28 +2616,16 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
- getFilePaths().push_back("/usr/lib/gcc41");
+ if (llvm::sys::fs::exists("/usr/lib/gcc47"))
+ getFilePaths().push_back("/usr/lib/gcc47");
+ else
+ getFilePaths().push_back("/usr/lib/gcc44");
}
-Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- else
- Key = JA.getKind();
-
- Tool *&T = Tools[Key];
- if (!T) {
- switch (Key) {
- case Action::AssembleJobClass:
- T = new tools::dragonfly::Assemble(*this); break;
- case Action::LinkJobClass:
- T = new tools::dragonfly::Link(*this); break;
- default:
- T = &Generic_GCC::SelectTool(C, JA, Inputs);
- }
- }
+Tool *DragonFly::buildAssembler() const {
+ return new tools::dragonfly::Assemble(*this);
+}
- return *T;
+Tool *DragonFly::buildLinker() const {
+ return new tools::dragonfly::Link(*this);
}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 0419a375ea..3afd8dd228 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -117,20 +117,20 @@ protected:
GCCInstallationDetector GCCInstallation;
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
-
public:
Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
~Generic_GCC();
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual bool IsUnwindTablesDefault() const;
virtual bool isPICDefault() const;
+ virtual bool isPIEDefault() const;
virtual bool isPICDefaultForced() const;
protected:
+ virtual Tool *getTool(Action::ActionClass AC) const;
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+
/// \name ToolChain Implementation Helper Functions
/// @{
@@ -141,6 +141,11 @@ protected:
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
/// @}
+
+private:
+ mutable OwningPtr<tools::gcc::Preprocess> Preprocess;
+ mutable OwningPtr<tools::gcc::Precompile> Precompile;
+ mutable OwningPtr<tools::gcc::Compile> Compile;
};
/// Darwin - The base Darwin tool chain.
@@ -149,8 +154,15 @@ public:
/// The host version.
unsigned DarwinVersion[3];
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+ virtual Tool *getTool(Action::ActionClass AC) const;
+
private:
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
+ mutable OwningPtr<tools::darwin::Lipo> Lipo;
+ mutable OwningPtr<tools::darwin::Dsymutil> Dsymutil;
+ mutable OwningPtr<tools::darwin::VerifyDebug> VerifyDebug;
/// Whether the information on the target has been initialized.
//
@@ -181,7 +193,7 @@ private:
void AddDeploymentTarget(DerivedArgList &Args) const;
public:
- Darwin(const Driver &D, const llvm::Triple& Triple);
+ Darwin(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
~Darwin();
std::string ComputeEffectiveClangTriple(const ArgList &Args,
@@ -269,9 +281,6 @@ public:
virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const;
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual bool IsBlocksDefault() const {
// Always allow blocks on Darwin; users interested in versioning are
// expected to use /usr/include/Blocks.h.
@@ -324,6 +333,7 @@ public:
return ToolChain::RLT_CompilerRT;
}
virtual bool isPICDefault() const;
+ virtual bool isPIEDefault() const;
virtual bool isPICDefaultForced() const;
virtual bool SupportsProfiling() const;
@@ -342,7 +352,7 @@ public:
/// DarwinClang - The Darwin toolchain used by Clang.
class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
public:
- DarwinClang(const Driver &D, const llvm::Triple& Triple);
+ DarwinClang(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
/// @name Darwin ToolChain Implementation
/// {
@@ -394,18 +404,20 @@ class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC {
public:
AuroraUX(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
public:
Solaris(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual bool IsIntegratedAssemblerDefault() const { return true; }
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+
};
@@ -416,8 +428,9 @@ public:
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF {
@@ -428,9 +441,6 @@ public:
virtual bool IsObjCNonFragileABIDefault() const { return true; }
virtual bool IsObjCLegacyDispatchDefault() const { return false; }
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddCXXStdlibLibArgs(const ArgList &Args,
@@ -438,6 +448,10 @@ public:
virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
return 1;
}
+
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
@@ -447,9 +461,10 @@ public:
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
virtual bool UseSjLjExceptions() const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
@@ -459,16 +474,23 @@ public:
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+ virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+
+ virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const;
+
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
public:
Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
@@ -477,8 +499,9 @@ public:
virtual bool IsMathErrnoDefault() const { return false; }
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
};
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
@@ -487,18 +510,21 @@ public:
virtual bool HasNativeLLVMSupport() const;
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
+ virtual bool isPIEDefault() const;
std::string Linker;
std::vector<std::string> ExtraOpts;
+ bool IsPIEDefault;
+
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
private:
static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
@@ -509,22 +535,21 @@ private:
static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
const ArgList &DriverArgs,
ArgStringList &CC1Args);
+
+ std::string computeSysRoot(const ArgList &Args) const;
};
class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
protected:
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
-
GCCVersion GCCLibAndIncVersion;
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
public:
Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args);
~Hexagon_TC();
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
-
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
@@ -542,39 +567,33 @@ public:
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
public:
- TCEToolChain(const Driver &D, const llvm::Triple& Triple);
+ TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args);
~TCEToolChain();
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
bool IsMathErrnoDefault() const;
bool isPICDefault() const;
+ bool isPIEDefault() const;
bool isPICDefaultForced() const;
-
-private:
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
-
};
class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
- mutable llvm::DenseMap<unsigned, Tool*> Tools;
-
public:
- Windows(const Driver &D, const llvm::Triple& Triple);
-
- virtual Tool &SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const;
+ Windows(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
virtual bool IsIntegratedAssemblerDefault() const;
virtual bool IsUnwindTablesDefault() const;
virtual bool isPICDefault() const;
+ virtual bool isPIEDefault() const;
virtual bool isPICDefaultForced() const;
virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const;
-
+protected:
+ virtual Tool *buildLinker() const;
+ virtual Tool *buildAssembler() const;
};
} // end namespace toolchains
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index ef759ff6d3..aba1fe4d2d 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include <sys/stat.h>
#include "Tools.h"
#include "InputInfo.h"
#include "SanitizerArgs.h"
@@ -544,6 +545,9 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
if (Triple.isOSDarwin())
return true;
return false;
+
+ case llvm::Triple::systemz:
+ return false;
}
}
@@ -815,7 +819,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mno-global-merge");
}
- if (Args.hasArg(options::OPT_mno_implicit_float))
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float,
+ true))
CmdArgs.push_back("-no-implicit-float");
}
@@ -851,8 +857,15 @@ static void getMipsCPUAndABI(const ArgList &Args,
CPUName = A->getValue();
}
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
+ // Convert a GNU style Mips ABI name to the name
+ // accepted by LLVM Mips backend.
+ ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
+ .Case("32", "o32")
+ .Case("64", "n64")
+ .Default(ABIName);
+ }
// Setup default CPU and ABI names.
if (CPUName.empty() && ABIName.empty()) {
@@ -899,8 +912,6 @@ static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
- // Select the float ABI as determined by -msoft-float, -mhard-float,
- // and -mfloat-abi=.
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float,
@@ -911,7 +922,7 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
FloatABI = "hard";
else {
FloatABI = A->getValue();
- if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") {
+ if (FloatABI != "soft" && FloatABI != "hard") {
D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
FloatABI = "hard";
}
@@ -944,7 +955,7 @@ static void AddTargetFeature(const ArgList &Args,
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+ ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
StringRef CPUName;
StringRef ABIName;
@@ -977,12 +988,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mips16-hard-float");
}
}
- else if (FloatABI == "single") {
- // Restrict the use of hardware floating-point
- // instructions to 32-bit operations.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+single-float");
- }
else {
// Floating point operations and argument passing are hard.
assert(FloatABI == "hard" && "Invalid float abi!");
@@ -991,9 +996,15 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
}
AddTargetFeature(Args, CmdArgs,
+ options::OPT_msingle_float, options::OPT_mdouble_float,
+ "single-float");
+ AddTargetFeature(Args, CmdArgs,
options::OPT_mips16, options::OPT_mno_mips16,
"mips16");
AddTargetFeature(Args, CmdArgs,
+ options::OPT_mmicromips, options::OPT_mno_micromips,
+ "micromips");
+ AddTargetFeature(Args, CmdArgs,
options::OPT_mdsp, options::OPT_mno_dsp,
"dsp");
AddTargetFeature(Args, CmdArgs,
@@ -1097,17 +1108,55 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
// Allow override of the Altivec feature.
- if (Args.hasFlag(options::OPT_fno_altivec, options::OPT_faltivec, false)) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-altivec");
- }
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_faltivec, options::OPT_fno_altivec,
+ "altivec");
+
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mfprnd, options::OPT_mno_fprnd,
+ "fprnd");
+
+ // Note that gcc calls this mfcrf and LLVM calls this mfocrf.
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mmfcrf, options::OPT_mno_mfcrf,
+ "mfocrf");
+
+ AddTargetFeature(Args, CmdArgs,
+ options::OPT_mpopcntd, options::OPT_mno_popcntd,
+ "popcntd");
+ // It is really only possible to turn qpx off because turning qpx on is tied
+ // to using the a2q CPU.
if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-qpx");
}
}
+/// Get the (LLVM) name of the R600 gpu we are targeting.
+static std::string getR600TargetGPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ std::string GPUName = A->getValue();
+ return llvm::StringSwitch<const char *>(GPUName)
+ .Cases("rv630", "rv635", "r600")
+ .Cases("rv610", "rv620", "rs780", "rs880")
+ .Case("rv740", "rv770")
+ .Case("palm", "cedar")
+ .Cases("sumo", "sumo2", "sumo")
+ .Case("hemlock", "cypress")
+ .Case("aruba", "cayman")
+ .Default(GPUName.c_str());
+ }
+ return "";
+}
+
+void Clang::AddR600TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string TargetGPUName = getR600TargetGPU(Args);
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str()));
+}
+
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
@@ -1217,6 +1266,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext));
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mno_soft_float,
+ options::OPT_mimplicit_float,
options::OPT_mno_implicit_float)) {
const Option &O = A->getOption();
NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
@@ -1414,36 +1464,36 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fexceptions");
}
+static bool ShouldDisableAutolink(const ArgList &Args,
+ const ToolChain &TC) {
+ bool Default = true;
+ if (TC.getTriple().isOSDarwin()) {
+ // The native darwin assembler doesn't support the linker_option directives,
+ // so we disable them if we think the .s file will be passed to it.
+ Default = TC.useIntegratedAs();
+ }
+ return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
+ Default);
+}
+
static bool ShouldDisableCFI(const ArgList &Args,
const ToolChain &TC) {
bool Default = true;
if (TC.getTriple().isOSDarwin()) {
// The native darwin assembler doesn't support cfi directives, so
// we disable them if we think the .s file will be passed to it.
- Default = Args.hasFlag(options::OPT_integrated_as,
- options::OPT_no_integrated_as,
- TC.IsIntegratedAssemblerDefault());
+ Default = TC.useIntegratedAs();
}
return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm,
options::OPT_fno_dwarf2_cfi_asm,
Default);
}
-static bool ShouldUseIntegratedAssembler(const ArgList &Args,
- const ToolChain &TC) {
- bool IsIADefault = TC.IsIntegratedAssemblerDefault();
- bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as,
- options::OPT_no_integrated_as,
- IsIADefault);
- return UseIntegratedAs;
-}
-
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
- bool UseIntegratedAs = ShouldUseIntegratedAssembler(Args, TC);
bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
options::OPT_fno_dwarf_directory_asm,
- UseIntegratedAs);
+ TC.useIntegratedAs());
return !UseDwarfDirectory;
}
@@ -1482,11 +1532,12 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
-SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args)
+SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
: Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
AsanZeroBaseShadow(false) {
unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
// at least once (possibly, disabled further).
+ const Driver &D = TC.getDriver();
for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
unsigned Add, Remove;
if (!parse(D, Args, *I, Add, Remove, true))
@@ -1578,40 +1629,61 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args)
/* Default */false);
// Parse -f(no-)sanitize-address-zero-base-shadow options.
- if (NeedsAsan)
+ if (NeedsAsan) {
+ bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ bool ZeroBaseShadowDefault = IsAndroid;
AsanZeroBaseShadow =
- Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow,
- /* Default */false);
+ Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
+ options::OPT_fno_sanitize_address_zero_base_shadow,
+ ZeroBaseShadowDefault);
+ // Zero-base shadow is a requirement on Android.
+ if (IsAndroid && !AsanZeroBaseShadow) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-sanitize-address-zero-base-shadow"
+ << lastArgumentForKind(D, Args, Address);
+ }
+ }
}
static void addSanitizerRTLinkFlagsLinux(
const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
- const StringRef Sanitizer, bool BeforeLibStdCXX) {
+ const StringRef Sanitizer, bool BeforeLibStdCXX,
+ bool ExportSymbols = true) {
// Sanitizer runtime is located in the Linux library directory and
// has name "libclang_rt.<Sanitizer>-<ArchName>.a".
SmallString<128> LibSanitizer(TC.getDriver().ResourceDir);
llvm::sys::path::append(
LibSanitizer, "lib", "linux",
(Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a"));
+
// Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
// etc.) so that the linker picks custom versions of the global 'operator
// new' and 'operator delete' symbols. We take the extreme (but simple)
// strategy of inserting it at the front of the link command. It also
// needs to be forced to end up in the executable, so wrap it in
// whole-archive.
- if (BeforeLibStdCXX) {
- SmallVector<const char *, 3> PrefixArgs;
- PrefixArgs.push_back("-whole-archive");
- PrefixArgs.push_back(Args.MakeArgString(LibSanitizer));
- PrefixArgs.push_back("-no-whole-archive");
- CmdArgs.insert(CmdArgs.begin(), PrefixArgs.begin(), PrefixArgs.end());
- } else {
- CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
- }
+ SmallVector<const char *, 3> LibSanitizerArgs;
+ LibSanitizerArgs.push_back("-whole-archive");
+ LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
+ LibSanitizerArgs.push_back("-no-whole-archive");
+
+ CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
+ LibSanitizerArgs.begin(), LibSanitizerArgs.end());
+
CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lrt");
CmdArgs.push_back("-ldl");
- CmdArgs.push_back("-export-dynamic");
+
+ // If possible, use a dynamic symbols file to export the symbols from the
+ // runtime library. If we can't do so, use -export-dynamic instead to export
+ // all symbols from the binary.
+ if (ExportSymbols) {
+ if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
+ CmdArgs.push_back(
+ Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+ else
+ CmdArgs.push_back("-export-dynamic");
+ }
}
/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
@@ -1619,11 +1691,6 @@ static void addSanitizerRTLinkFlagsLinux(
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if(TC.getTriple().getEnvironment() == llvm::Triple::Android) {
- if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_asan_android_requires_pie);
- }
-
SmallString<128> LibAsan(TC.getDriver().ResourceDir);
llvm::sys::path::append(LibAsan, "lib", "linux",
(Twine("libclang_rt.asan-") +
@@ -1631,13 +1698,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
} else {
if (!Args.hasArg(options::OPT_shared)) {
- bool ZeroBaseShadow = Args.hasFlag(
- options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow, false);
- if (ZeroBaseShadow && !Args.hasArg(options::OPT_pie)) {
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize-address-zero-base-shadow" << "-pie";
- }
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
}
}
@@ -1648,9 +1708,6 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize=thread" << "-pie";
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
}
}
@@ -1660,9 +1717,6 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
if (!Args.hasArg(options::OPT_shared)) {
- if (!Args.hasArg(options::OPT_pie))
- TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) <<
- "-fsanitize=memory" << "-pie";
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
}
}
@@ -1670,8 +1724,22 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
/// (Linux).
static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs, bool IsCXX,
+ bool HasOtherSanitizerRt) {
+ if (Args.hasArg(options::OPT_shared))
+ return;
+
+ // Need a copy of sanitizer_common. This could come from another sanitizer
+ // runtime; if we're not including one, include our own copy.
+ if (!HasOtherSanitizerRt)
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false);
+
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false);
+
+ // Only include the bits of the runtime which need a C++ ABI library if
+ // we're linking in C++ mode.
+ if (IsCXX)
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
}
static bool shouldUseFramePointer(const ArgList &Args,
@@ -1692,17 +1760,48 @@ static bool shouldUseFramePointer(const ArgList &Args,
return true;
}
+static bool shouldUseLeafFramePointer(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
+ options::OPT_momit_leaf_frame_pointer))
+ return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+
+ // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing.
+ if ((Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::x86) &&
+ Triple.getOS() == llvm::Triple::Linux) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (!A->getOption().matches(options::OPT_O0))
+ return false;
+ }
+
+ return true;
+}
+
/// If the PWD environment variable is set, add a CC1 option to specify the
/// debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
- if (const char *pwd = ::getenv("PWD")) {
- // GCC also verifies that stat(pwd) and stat(".") have the same inode
- // number. Not doing those because stats are slow, but we could.
- if (llvm::sys::path::is_absolute(pwd)) {
- std::string CompDir = pwd;
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(Args.MakeArgString(CompDir));
- }
+ struct stat StatPWDBuf, StatDotBuf;
+
+ const char *pwd = ::getenv("PWD");
+ if (!pwd)
+ return;
+
+ if (llvm::sys::path::is_absolute(pwd) &&
+ stat(pwd, &StatPWDBuf) == 0 &&
+ stat(".", &StatDotBuf) == 0 &&
+ StatPWDBuf.st_ino == StatDotBuf.st_ino &&
+ StatPWDBuf.st_dev == StatDotBuf.st_dev) {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Args.MakeArgString(pwd));
+ return;
+ }
+
+ // Fall back to using getcwd.
+ SmallString<128> cwd;
+ if (!llvm::sys::fs::current_path(cwd)) {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Args.MakeArgString(cwd));
}
}
@@ -1748,6 +1847,13 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
C.addCommand(new Command(JA, T, Exec, StripArgs));
}
+static bool isOptimizationLevelFast(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (A->getOption().matches(options::OPT_Ofast))
+ return true;
+ return false;
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -1781,8 +1887,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (isa<PreprocessJobAction>(JA)) {
if (Output.getType() == types::TY_Dependencies)
CmdArgs.push_back("-Eonly");
- else
+ else {
CmdArgs.push_back("-E");
+ if (Args.hasArg(options::OPT_rewrite_objc) &&
+ !Args.hasArg(options::OPT_g_Group))
+ CmdArgs.push_back("-P");
+ }
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
@@ -1843,6 +1953,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-S");
} else if (JA.getType() == types::TY_AST) {
CmdArgs.push_back("-emit-pch");
+ } else if (JA.getType() == types::TY_ModuleFile) {
+ CmdArgs.push_back("-module-file-info");
} else if (JA.getType() == types::TY_RewrittenObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_NonFragile;
@@ -1894,6 +2006,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-analyzer-checker=deadcode");
+ if (types::isCXX(Inputs[0].getType()))
+ CmdArgs.push_back("-analyzer-checker=cplusplus");
+
// Enable the following experimental checkers for testing.
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
@@ -1922,37 +2037,38 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CheckCodeGenerationOptions(D, Args);
- // For the PIC and PIE flag options, this logic is different from the legacy
- // logic in very old versions of GCC, as that logic was just a bug no one had
- // ever fixed. This logic is both more rational and consistent with GCC's new
- // logic now that the bugs are fixed. The last argument relating to either
- // PIC or PIE wins, and no other argument is used. If the last argument is
- // any flavor of the '-fno-...' arguments, both PIC and PIE are disabled. Any
- // PIE option implicitly enables PIC at the same level.
- bool PIE = false;
- bool PIC = getToolChain().isPICDefault();
+ bool PIE = getToolChain().isPIEDefault();
+ bool PIC = PIE || getToolChain().isPICDefault();
bool IsPICLevelTwo = PIC;
- if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
- options::OPT_fpic, options::OPT_fno_pic,
- options::OPT_fPIE, options::OPT_fno_PIE,
- options::OPT_fpie, options::OPT_fno_pie)) {
- Option O = A->getOption();
- if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
- O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
- PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
- PIC = PIE || O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic);
- IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
- O.matches(options::OPT_fPIC);
- } else {
- PIE = PIC = false;
- }
- }
+
+ // For the PIC and PIE flag options, this logic is different from the
+ // legacy logic in very old versions of GCC, as that logic was just
+ // a bug no one had ever fixed. This logic is both more rational and
+ // consistent with GCC's new logic now that the bugs are fixed. The last
+ // argument relating to either PIC or PIE wins, and no other argument is
+ // used. If the last argument is any flavor of the '-fno-...' arguments,
+ // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
+ // at the same level.
+ Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
// is forced, then neither PIC nor PIE flags will have no effect.
- if (getToolChain().isPICDefaultForced()) {
- PIE = false;
- PIC = getToolChain().isPICDefault();
- IsPICLevelTwo = PIC;
+ if (!getToolChain().isPICDefaultForced()) {
+ if (LastPICArg) {
+ Option O = LastPICArg->getOption();
+ if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
+ PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
+ PIC = PIE || O.matches(options::OPT_fPIC) ||
+ O.matches(options::OPT_fpic);
+ IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
+ O.matches(options::OPT_fPIC);
+ } else {
+ PIE = PIC = false;
+ }
+ }
}
// Inroduce a Darwin-specific hack. If the default is PIC but the flags
@@ -2026,10 +2142,18 @@ 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,
+
+ bool OFastEnabled = isOptimizationLevelFast(Args);
+ // If -Ofast is the optimization level, then -fstrict-aliasing should be
+ // enabled. This alias option is being used to simplify the hasFlag logic.
+ OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_fstrict_aliasing;
+ if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
options::OPT_fno_strict_aliasing,
getToolChain().IsStrictAliasingDefault()))
CmdArgs.push_back("-relaxed-aliasing");
+ if (Args.hasArg(options::OPT_fstruct_path_tbaa))
+ CmdArgs.push_back("-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
@@ -2037,12 +2161,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
+ // Handle segmented stacks.
+ if (Args.hasArg(options::OPT_fsplit_stack))
+ CmdArgs.push_back("-split-stacks");
+
+ // If -Ofast is the optimization level, then -ffast-math should be enabled.
+ // This alias option is being used to simplify the getLastArg logic.
+ OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_ffast_math;
+
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. The pattern for all of these is to
// default off the codegen optimizations, and if any flag enables them and no
// flag disables them after the flag enabling them, enable the codegen
// optimization. This is complicated by several "umbrella" flags.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffinite_math_only,
options::OPT_fno_finite_math_only,
@@ -2052,7 +2185,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_finite_math_only &&
A->getOption().getID() != options::OPT_fhonor_infinities)
CmdArgs.push_back("-menable-no-infs");
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffinite_math_only,
options::OPT_fno_finite_math_only,
@@ -2065,7 +2198,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
bool MathErrno = getToolChain().IsMathErrnoDefault();
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_fmath_errno,
options::OPT_fno_math_errno))
@@ -2078,7 +2211,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// entire set of LLVM optimizations, so collect them through all the flag
// madness.
bool AssociativeMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2089,7 +2222,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_associative_math)
AssociativeMath = true;
bool ReciprocalMath = false;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2100,7 +2233,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fno_reciprocal_math)
ReciprocalMath = true;
bool SignedZeros = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2111,7 +2244,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().getID() != options::OPT_fsigned_zeros)
SignedZeros = false;
bool TrappingMath = true;
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_funsafe_math_optimizations,
options::OPT_fno_unsafe_math_optimizations,
@@ -2127,7 +2260,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Validate and pass through -fp-contract option.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math,
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffp_contract)) {
if (A->getOption().getID() == options::OPT_ffp_contract) {
@@ -2138,7 +2271,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
- } else if (A->getOption().getID() == options::OPT_ffast_math) {
+ } else if (A->getOption().matches(options::OPT_ffast_math) ||
+ (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
// If fast-math is set then set the fp-contract mode to fast.
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
}
@@ -2149,9 +2283,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// preprocessor macros. This is distinct from enabling any optimizations as
// these options induce language changes which must survive serialization
// and deserialization, etc.
- if (Arg *A = Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math))
- if (A->getOption().matches(options::OPT_ffast_math))
- CmdArgs.push_back("-ffast-math");
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math))
+ if (!A->getOption().matches(options::OPT_fno_fast_math))
+ CmdArgs.push_back("-ffast-math");
if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math))
if (A->getOption().matches(options::OPT_ffinite_math_only))
CmdArgs.push_back("-ffinite-math-only");
@@ -2236,6 +2371,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddPPCTargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::r600:
+ AddR600TargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::sparc:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -2258,10 +2397,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- // -mno-omit-leaf-frame-pointer is the default on Darwin.
- if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
- options::OPT_mno_omit_leaf_frame_pointer,
- !getToolChain().getTriple().isOSDarwin()))
+ if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
CmdArgs.push_back("-momit-leaf-frame-pointer");
// Explicitly error on some things we know we don't support and can't just
@@ -2515,6 +2651,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (ShouldDisableDwarfDirectory(Args, getToolChain()))
CmdArgs.push_back("-fno-dwarf-directory-asm");
+ if (ShouldDisableAutolink(Args, getToolChain()))
+ CmdArgs.push_back("-fno-autolink");
+
// Add in -fdebug-compilation-dir if necessary.
addDebugCompDirArg(Args, CmdArgs);
@@ -2623,7 +2762,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
- SanitizerArgs Sanitize(D, Args);
+ SanitizerArgs Sanitize(getToolChain(), Args);
Sanitize.addArgs(Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fsanitize_recover,
@@ -2784,12 +2923,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fmodules");
HaveModules = true;
}
-
- if (HaveModules && !ShouldUseIntegratedAssembler(Args, getToolChain())) {
- D.Diag(diag::err_drv_modules_integrated_as);
- D.Diag(diag::note_drv_modules_integrated_as);
- return;
- }
}
// If a module path was provided, pass it along. Otherwise, use a temporary
@@ -2803,7 +2936,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
SmallString<128> DefaultModuleCache;
llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
DefaultModuleCache);
- llvm::sys::path::append(DefaultModuleCache, "clang-module-cache");
+ llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
+ llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
const char Arg[] = "-fmodules-cache-path=";
DefaultModuleCache.insert(DefaultModuleCache.begin(),
Arg, Arg + strlen(Arg));
@@ -2812,15 +2946,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Pass through all -fmodules-ignore-macro arguments.
Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
-
- // -fmodules-autolink (on by default when modules is enabled) automatically
- // links against libraries for imported modules.
- if (HaveModules &&
- Args.hasFlag(options::OPT_fmodules_autolink,
- options::OPT_fno_modules_autolink,
- true)) {
- CmdArgs.push_back("-fmodules-autolink");
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
@@ -3118,9 +3245,42 @@ 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()))
+ // Support both clang's -f[no-]color-diagnostics and gcc's
+ // -f[no-]diagnostics-colors[=never|always|auto].
+ enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ it != ie; ++it) {
+ const Option &O = (*it)->getOption();
+ if (!O.matches(options::OPT_fcolor_diagnostics) &&
+ !O.matches(options::OPT_fdiagnostics_color) &&
+ !O.matches(options::OPT_fno_color_diagnostics) &&
+ !O.matches(options::OPT_fno_diagnostics_color) &&
+ !O.matches(options::OPT_fdiagnostics_color_EQ))
+ continue;
+
+ (*it)->claim();
+ if (O.matches(options::OPT_fcolor_diagnostics) ||
+ O.matches(options::OPT_fdiagnostics_color)) {
+ ShowColors = Colors_On;
+ } else if (O.matches(options::OPT_fno_color_diagnostics) ||
+ O.matches(options::OPT_fno_diagnostics_color)) {
+ ShowColors = Colors_Off;
+ } else {
+ assert(O.matches(options::OPT_fdiagnostics_color_EQ));
+ StringRef value((*it)->getValue());
+ if (value == "always")
+ ShowColors = Colors_On;
+ else if (value == "never")
+ ShowColors = Colors_Off;
+ else if (value == "auto")
+ ShowColors = Colors_Auto;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << ("-fdiagnostics-color=" + value).str();
+ }
+ }
+ if (ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
CmdArgs.push_back("-fcolor-diagnostics");
if (!Args.hasFlag(options::OPT_fshow_source_location,
@@ -3142,8 +3302,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fasm-blocks");
+ // If -Ofast is the optimization level, then -fvectorize should be enabled.
+ // This alias option is being used to simplify the hasFlag logic.
+ OptSpecifier VectorizeAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_fvectorize;
+
// -fvectorize is default.
- if (Args.hasFlag(options::OPT_fvectorize,
+ if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, true)) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-vectorize-loops");
@@ -3153,7 +3318,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fslp_vectorize,
options::OPT_fno_slp_vectorize, false)) {
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-vectorize");
+ CmdArgs.push_back("-vectorize-slp");
+ }
+
+ // -fno-slp-vectorize-aggressive is default.
+ if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
+ options::OPT_fno_slp_vectorize_aggressive, false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-vectorize-slp-aggressive");
}
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
@@ -3218,6 +3390,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -fcomment-block-commands to -cc1.
Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
+ // Forward -fparse-all-comments to -cc1.
+ Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
@@ -3593,6 +3767,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec = getToolChain().getDriver().getClangProgramPath();
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ // Handle the debug info splitting at object creation time if we're
+ // creating an object.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ (getToolChain().getTriple().getOS() == llvm::Triple::Linux))
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs));
}
void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
@@ -3644,7 +3826,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
// here.
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
CmdArgs.push_back("-m32");
- else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86_64)
+ else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64)
CmdArgs.push_back("-m64");
if (Output.isFilename()) {
@@ -3678,6 +3860,9 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
else if (II.getType() == types::TY_AST)
D.Diag(diag::err_drv_no_ast_support)
<< getToolChain().getTripleString();
+ else if (II.getType() == types::TY_ModuleFile)
+ D.Diag(diag::err_drv_no_module_support)
+ << getToolChain().getTripleString();
if (types::canTypeBeUserSpecified(II.getType())) {
CmdArgs.push_back("-x");
@@ -3784,7 +3969,6 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString(std::string("-G") + SmallDataThreshold));
- Args.AddAllArgs(CmdArgs, options::OPT_g_Group);
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -3808,6 +3992,9 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
else if (II.getType() == types::TY_AST)
D.Diag(clang::diag::err_drv_no_ast_support)
<< getToolChain().getTripleString();
+ else if (II.getType() == types::TY_ModuleFile)
+ D.Diag(diag::err_drv_no_module_support)
+ << getToolChain().getTripleString();
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
@@ -4493,7 +4680,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
- SanitizerArgs Sanitize(getToolChain().getDriver(), Args);
+ SanitizerArgs Sanitize(getToolChain(), Args);
// If we're building a dynamic lib with -fsanitize=address,
// unresolved symbols may appear. Mark all
// of them as dynamic_lookup. Linking executables is handled in
@@ -5217,6 +5404,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
switch(getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
+ CmdArgs.push_back("-meabi=5");
break;
default:
@@ -5566,11 +5754,11 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
-void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
// Add --32/--64 to make sure we get the format we want.
@@ -5619,6 +5807,12 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
+ Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16);
+ Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
+ options::OPT_mno_micromips);
+ Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
+ Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);
+
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
options::OPT_fpic, options::OPT_fno_pic,
options::OPT_fPIE, options::OPT_fno_PIE,
@@ -5630,6 +5824,9 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
LastPICArg->getOption().matches(options::OPT_fpie))) {
CmdArgs.push_back("-KPIC");
}
+ } else if (getToolChain().getArch() == llvm::Triple::systemz) {
+ // At the moment we always produce z10 code.
+ CmdArgs.push_back("-march=z10");
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -5687,16 +5884,20 @@ static bool hasMipsN32ABIArg(const ArgList &Args) {
return A && (A->getValue() == StringRef("n32"));
}
-void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const toolchains::Linux& ToolChain =
static_cast<const toolchains::Linux&>(getToolChain());
const Driver &D = ToolChain.getDriver();
const bool isAndroid =
ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
+ SanitizerArgs Sanitize(getToolChain(), Args);
+ const bool IsPIE =
+ !Args.hasArg(options::OPT_shared) &&
+ (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow());
ArgStringList CmdArgs;
@@ -5711,7 +5912,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
- if (Args.hasArg(options::OPT_pie) && !Args.hasArg(options::OPT_shared))
+ if (IsPIE)
CmdArgs.push_back("-pie");
if (Args.hasArg(options::OPT_rdynamic))
@@ -5757,6 +5958,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("elf64ltsmip");
}
+ else if (ToolChain.getArch() == llvm::Triple::systemz)
+ CmdArgs.push_back("elf64_s390");
else
CmdArgs.push_back("elf_x86_64");
@@ -5803,7 +6006,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
else if (ToolChain.getArch() == llvm::Triple::ppc)
CmdArgs.push_back("/lib/ld.so.1");
- else if (ToolChain.getArch() == llvm::Triple::ppc64)
+ else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
+ ToolChain.getArch() == llvm::Triple::systemz)
CmdArgs.push_back("/lib64/ld64.so.1");
else
CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2");
@@ -5817,7 +6021,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!isAndroid) {
const char *crt1 = NULL;
if (!Args.hasArg(options::OPT_shared)){
- if (Args.hasArg(options::OPT_pie))
+ if (IsPIE)
crt1 = "Scrt1.o";
else
crt1 = "crt1.o";
@@ -5833,7 +6037,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
else if (Args.hasArg(options::OPT_shared))
crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
- else if (Args.hasArg(options::OPT_pie))
+ else if (IsPIE)
crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
else
crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
@@ -5884,11 +6088,11 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
- SanitizerArgs Sanitize(D, Args);
-
// Call these before we add the C++ ABI library.
if (Sanitize.needsUbsanRt())
- addUbsanRTLinux(getToolChain(), Args, CmdArgs);
+ addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX,
+ Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
+ Sanitize.needsMsanRt());
if (Sanitize.needsAsanRt())
addAsanRTLinux(getToolChain(), Args, CmdArgs);
if (Sanitize.needsTsanRt())
@@ -5941,7 +6145,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *crtend;
if (Args.hasArg(options::OPT_shared))
crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
- else if (Args.hasArg(options::OPT_pie))
+ else if (IsPIE)
crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
else
crtend = isAndroid ? "crtend_android.o" : "crtend.o";
@@ -6073,21 +6277,29 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ bool UseGCC47 = false;
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
+ if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47))
+ UseGCC47 = false;
+
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+ CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
} else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-Bshareable");
else {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
}
+ CmdArgs.push_back("--hash-style=both");
}
// When building 32-bit code on DragonFly/pc64, we have to explicitly
@@ -6107,18 +6319,26 @@ void dragonfly::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")));
- 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")));
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt1.o")));
+ else {
+ if (Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("Scrt1.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ }
}
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -6131,20 +6351,19 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nodefaultlibs)) {
// FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
// rpaths
- CmdArgs.push_back("-L/usr/lib/gcc41");
+ if (UseGCC47)
+ CmdArgs.push_back("-L/usr/lib/gcc47");
+ else
+ CmdArgs.push_back("-L/usr/lib/gcc44");
if (!Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-rpath");
- CmdArgs.push_back("/usr/lib/gcc41");
-
- CmdArgs.push_back("-rpath-link");
- CmdArgs.push_back("/usr/lib/gcc41");
-
- CmdArgs.push_back("-rpath");
- CmdArgs.push_back("/usr/lib");
-
- CmdArgs.push_back("-rpath-link");
- CmdArgs.push_back("/usr/lib");
+ if (UseGCC47) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc47");
+ } else {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc44");
+ }
}
if (D.CCCIsCXX) {
@@ -6152,13 +6371,6 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lm");
}
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-lgcc_pic");
- } else {
- CmdArgs.push_back("-lgcc");
- }
-
-
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
@@ -6166,23 +6378,42 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-lgcc_pic");
+ if (UseGCC47) {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_static_libgcc)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lgcc_eh");
+ } else {
+ if (Args.hasArg(options::OPT_shared_libgcc)) {
+ CmdArgs.push_back("-lgcc_pic");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lgcc");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_pic");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
} else {
- CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-lgcc_pic");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ }
}
}
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared))
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtend.o")));
+ getToolChain().GetFilePath("crtendS.o")));
else
CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtendS.o")));
+ getToolChain().GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crtn.o")));
+ getToolChain().GetFilePath("crtn.o")));
}
addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 846c834034..d6471716e6 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -51,6 +51,7 @@ namespace tools {
bool KernelOrKext) const;
void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
void AddPPCTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddR600TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
void AddHexagonTargetArgs (const ArgList &Args, ArgStringList &CmdArgs) const;
@@ -427,12 +428,11 @@ namespace netbsd {
};
} // end namespace netbsd
- /// linux -- Directly call GNU Binutils assembler and linker
-namespace linuxtools {
+ /// Directly call GNU Binutils' assembler and linker.
+namespace gnutools {
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
public:
- Assemble(const ToolChain &TC) : Tool("linux::Assemble", "assembler",
- TC) {}
+ Assemble(const ToolChain &TC) : Tool("GNU::Assemble", "assembler", TC) {}
virtual bool hasIntegratedCPP() const { return false; }
@@ -444,7 +444,7 @@ namespace linuxtools {
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
- Link(const ToolChain &TC) : Tool("linux::Link", "linker", TC) {}
+ Link(const ToolChain &TC) : Tool("GNU::Link", "linker", TC) {}
virtual bool hasIntegratedCPP() const { return false; }
virtual bool isLinkJob() const { return true; }
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 9665095b00..7d22596a17 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -87,7 +87,7 @@ bool types::isAcceptedByClang(ID Id) {
case TY_ObjCHeader: case TY_PP_ObjCHeader:
case TY_CXXHeader: case TY_PP_CXXHeader:
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
- case TY_AST:
+ case TY_AST: case TY_ModuleFile:
case TY_LLVM_IR: case TY_LLVM_BC:
return true;
}
@@ -164,6 +164,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
.Case("F90", TY_Fortran)
.Case("F95", TY_Fortran)
.Case("mii", TY_PP_ObjCXX)
+ .Case("pcm", TY_ModuleFile)
.Default(TY_INVALID);
}
diff --git a/lib/Driver/WindowsToolChain.cpp b/lib/Driver/WindowsToolChain.cpp
index e7ab4ced87..622c49296d 100644
--- a/lib/Driver/WindowsToolChain.cpp
+++ b/lib/Driver/WindowsToolChain.cpp
@@ -14,6 +14,7 @@
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
@@ -31,48 +32,20 @@ using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
-Windows::Windows(const Driver &D, const llvm::Triple& Triple)
- : ToolChain(D, Triple) {
+Windows::Windows(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
}
-Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA,
- const ActionList &Inputs) const {
- Action::ActionClass Key;
- if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
- Key = Action::AnalyzeJobClass;
- 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::InputClass:
- case Action::BindArchClass:
- case Action::LipoJobClass:
- case Action::DsymutilJobClass:
- case Action::VerifyJobClass:
- case Action::PreprocessJobClass:
- case Action::PrecompileJobClass:
- case Action::AnalyzeJobClass:
- case Action::MigrateJobClass:
- case Action::CompileJobClass:
- T = new tools::Clang(*this); break;
- case Action::AssembleJobClass:
- if (!UseIntegratedAs && getTriple().getEnvironment() == llvm::Triple::MachO)
- T = new tools::darwin::Assemble(*this);
- else
- T = new tools::ClangAs(*this);
- break;
- case Action::LinkJobClass:
- T = new tools::visualstudio::Link(*this); break;
- }
- }
+Tool *Windows::buildLinker() const {
+ return new tools::visualstudio::Link(*this);
+}
- return *T;
+Tool *Windows::buildAssembler() const {
+ if (getTriple().getEnvironment() == llvm::Triple::MachO)
+ return new tools::darwin::Assemble(*this);
+ getDriver().Diag(clang::diag::err_no_external_windows_assembler);
+ return NULL;
}
bool Windows::IsIntegratedAssemblerDefault() const {
@@ -87,6 +60,10 @@ bool Windows::isPICDefault() const {
return getArch() == llvm::Triple::x86_64;
}
+bool Windows::isPIEDefault() const {
+ return false;
+}
+
bool Windows::isPICDefaultForced() const {
return getArch() == llvm::Triple::x86_64;
}