aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/Action.cpp12
-rw-r--r--lib/Driver/Arg.cpp23
-rw-r--r--lib/Driver/ArgList.cpp54
-rw-r--r--lib/Driver/Compilation.cpp46
-rw-r--r--lib/Driver/Driver.cpp580
-rw-r--r--lib/Driver/HostInfo.cpp257
-rw-r--r--lib/Driver/Job.cpp6
-rw-r--r--lib/Driver/Makefile16
-rw-r--r--lib/Driver/OptTable.cpp18
-rw-r--r--lib/Driver/Option.cpp57
-rw-r--r--lib/Driver/Tool.cpp2
-rw-r--r--lib/Driver/ToolChain.cpp12
-rw-r--r--lib/Driver/ToolChains.cpp392
-rw-r--r--lib/Driver/ToolChains.h138
-rw-r--r--lib/Driver/Tools.cpp1082
-rw-r--r--lib/Driver/Tools.h174
-rw-r--r--lib/Driver/Types.cpp48
17 files changed, 1929 insertions, 988 deletions
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index cabc33eaec28..62434893f939 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -29,16 +29,16 @@ const char *Action::getClassName(ActionClass AC) {
case LinkJobClass: return "linker";
case LipoJobClass: return "lipo";
}
-
+
assert(0 && "invalid class");
return 0;
}
-InputAction::InputAction(const Arg &_Input, types::ID _Type)
+InputAction::InputAction(const Arg &_Input, types::ID _Type)
: Action(InputClass, _Type), Input(_Input) {
}
-BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
+BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
: Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) {
}
@@ -46,7 +46,7 @@ JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
: Action(Kind, Input, Type) {
}
-JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
+JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
: Action(Kind, Inputs, Type) {
}
@@ -70,10 +70,10 @@ AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
: JobAction(AssembleJobClass, Input, OutputType) {
}
-LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
+LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
: JobAction(LinkJobClass, Inputs, Type) {
}
-LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
+LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
: JobAction(LipoJobClass, Inputs, Type) {
}
diff --git a/lib/Driver/Arg.cpp b/lib/Driver/Arg.cpp
index e227d7e2ea15..a09ba095f119 100644
--- a/lib/Driver/Arg.cpp
+++ b/lib/Driver/Arg.cpp
@@ -14,10 +14,9 @@
using namespace clang::driver;
-Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index,
- const Arg *_BaseArg)
- : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false)
-{
+Arg::Arg(ArgClass _Kind, const Option *_Opt, unsigned _Index,
+ const Arg *_BaseArg)
+ : Kind(_Kind), Opt(_Opt), BaseArg(_BaseArg), Index(_Index), Claimed(false) {
}
Arg::~Arg() { }
@@ -54,7 +53,7 @@ std::string Arg::getAsString(const ArgList &Args) const {
ArgStringList ASL;
render(Args, ASL);
- for (ArgStringList::iterator
+ for (ArgStringList::iterator
it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
if (it != ASL.begin())
OS << ' ';
@@ -87,7 +86,7 @@ const char *FlagArg::getValue(const ArgList &Args, unsigned N) const {
return 0;
}
-PositionalArg::PositionalArg(const Option *Opt, unsigned Index,
+PositionalArg::PositionalArg(const Option *Opt, unsigned Index,
const Arg *BaseArg)
: Arg(PositionalClass, Opt, Index, BaseArg) {
}
@@ -120,10 +119,10 @@ const char *JoinedArg::getValue(const ArgList &Args, unsigned N) const {
return Args.getArgString(getIndex()) + strlen(getOption().getName());
}
-CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
+CommaJoinedArg::CommaJoinedArg(const Option *Opt, unsigned Index,
const char *Str, const Arg *BaseArg)
: Arg(CommaJoinedClass, Opt, Index, BaseArg) {
- const char *Prev = Str;
+ const char *Prev = Str;
for (;; ++Str) {
char c = *Str;
@@ -167,23 +166,23 @@ void SeparateArg::render(const ArgList &Args, ArgStringList &Output) const {
}
}
-const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
+const char *SeparateArg::getValue(const ArgList &Args, unsigned N) const {
assert(N < getNumValues() && "Invalid index.");
return Args.getArgString(getIndex() + 1 + N);
}
-JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index,
+JoinedAndSeparateArg::JoinedAndSeparateArg(const Option *Opt, unsigned Index,
const Arg *BaseArg)
: Arg(JoinedAndSeparateClass, Opt, Index, BaseArg) {
}
-void JoinedAndSeparateArg::render(const ArgList &Args,
+void JoinedAndSeparateArg::render(const ArgList &Args,
ArgStringList &Output) const {
Output.push_back(Args.getArgString(getIndex()));
Output.push_back(Args.getArgString(getIndex() + 1));
}
-const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
+const char *JoinedAndSeparateArg::getValue(const ArgList &Args,
unsigned N) const {
assert(N < getNumValues() && "Invalid index.");
if (N == 0)
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
index 54dd4bb77538..8d2138df85e8 100644
--- a/lib/Driver/ArgList.cpp
+++ b/lib/Driver/ArgList.cpp
@@ -11,6 +11,10 @@
#include "clang/Driver/Arg.h"
#include "clang/Driver/Option.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
using namespace clang::driver;
ArgList::ArgList(arglist_type &_Args) : Args(_Args) {
@@ -31,13 +35,13 @@ Arg *ArgList::getLastArg(options::ID Id, bool Claim) const {
return *it;
}
}
-
+
return 0;
}
Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const {
Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false);
-
+
if (A0 && A1)
Res = A0->getIndex() > A1->getIndex() ? A0 : A1;
else
@@ -102,7 +106,7 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const {
}
}
-void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
+void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
options::ID Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
@@ -114,7 +118,7 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
}
}
-void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
+void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
options::ID Id1, options::ID Id2) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
@@ -139,7 +143,7 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const {
}
}
-void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,
+void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,
options::ID Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
@@ -182,11 +186,16 @@ void ArgList::ClaimAllArgs(options::ID Id0) const {
}
}
+const char *ArgList::MakeArgString(const llvm::Twine &T) const {
+ llvm::SmallString<256> Str;
+ T.toVector(Str);
+ return MakeArgString(Str.str());
+}
+
//
-InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
- : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin)
-{
+InputArgList::InputArgList(const char **ArgBegin, const char **ArgEnd)
+ : ArgList(ActualArgs), NumInputArgStrings(ArgEnd - ArgBegin) {
ArgStrings.append(ArgBegin, ArgEnd);
}
@@ -196,7 +205,7 @@ InputArgList::~InputArgList() {
delete *it;
}
-unsigned InputArgList::MakeIndex(const char *String0) const {
+unsigned InputArgList::MakeIndex(llvm::StringRef String0) const {
unsigned Index = ArgStrings.size();
// Tuck away so we have a reliable const char *.
@@ -206,8 +215,8 @@ unsigned InputArgList::MakeIndex(const char *String0) const {
return Index;
}
-unsigned InputArgList::MakeIndex(const char *String0,
- const char *String1) const {
+unsigned InputArgList::MakeIndex(llvm::StringRef String0,
+ llvm::StringRef String1) const {
unsigned Index0 = MakeIndex(String0);
unsigned Index1 = MakeIndex(String1);
assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
@@ -215,7 +224,7 @@ unsigned InputArgList::MakeIndex(const char *String0,
return Index0;
}
-const char *InputArgList::MakeArgString(const char *Str) const {
+const char *InputArgList::MakeArgString(llvm::StringRef Str) const {
return getArgString(MakeIndex(Str));
}
@@ -223,18 +232,17 @@ const char *InputArgList::MakeArgString(const char *Str) const {
DerivedArgList::DerivedArgList(InputArgList &_BaseArgs, bool _OnlyProxy)
: ArgList(_OnlyProxy ? _BaseArgs.getArgs() : ActualArgs),
- BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy)
-{
+ BaseArgs(_BaseArgs), OnlyProxy(_OnlyProxy) {
}
DerivedArgList::~DerivedArgList() {
// We only own the arguments we explicitly synthesized.
- for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
+ for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
it != ie; ++it)
delete *it;
}
-const char *DerivedArgList::MakeArgString(const char *Str) const {
+const char *DerivedArgList::MakeArgString(llvm::StringRef Str) const {
return BaseArgs.MakeArgString(Str);
}
@@ -242,19 +250,19 @@ Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option *Opt) const {
return new FlagArg(Opt, BaseArgs.MakeIndex(Opt->getName()), BaseArg);
}
-Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
- const char *Value) const {
+Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
return new PositionalArg(Opt, BaseArgs.MakeIndex(Value), BaseArg);
}
-Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
- const char *Value) const {
- return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
+Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
+ return new SeparateArg(Opt, BaseArgs.MakeIndex(Opt->getName(), Value), 1,
BaseArg);
}
-Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
- const char *Value) const {
+Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option *Opt,
+ llvm::StringRef Value) const {
std::string Joined(Opt->getName());
Joined += Value;
return new JoinedArg(Opt, BaseArgs.MakeIndex(Joined.c_str()), BaseArg);
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 7e29b67769d3..c12f5aa88195 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -23,36 +23,38 @@ using namespace clang::driver;
Compilation::Compilation(const Driver &D,
const ToolChain &_DefaultToolChain,
- InputArgList *_Args)
+ InputArgList *_Args)
: TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args) {
}
-Compilation::~Compilation() {
+Compilation::~Compilation() {
delete Args;
-
+
// Free any derived arg lists.
- for (llvm::DenseMap<const ToolChain*, DerivedArgList*>::iterator
- it = TCArgs.begin(), ie = TCArgs.end(); it != ie; ++it)
+ for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+ DerivedArgList*>::iterator it = TCArgs.begin(),
+ ie = TCArgs.end(); it != ie; ++it)
delete it->second;
// Free the actions, if built.
- for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
+ for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
it != ie; ++it)
delete *it;
}
-const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC) {
+const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
+ const char *BoundArch) {
if (!TC)
TC = &DefaultToolChain;
- DerivedArgList *&Entry = TCArgs[TC];
+ DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
if (!Entry)
- Entry = TC->TranslateArgs(*Args);
+ Entry = TC->TranslateArgs(*Args, BoundArch);
return *Entry;
}
-void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
+void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
const char *Terminator, bool Quote) const {
if (const Command *C = dyn_cast<Command>(&J)) {
OS << " \"" << C->getExecutable() << '"';
@@ -65,22 +67,22 @@ void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
}
OS << Terminator;
} else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
- for (PipedJob::const_iterator
+ for (PipedJob::const_iterator
it = PJ->begin(), ie = PJ->end(); it != ie; ++it)
PrintJob(OS, **it, (it + 1 != PJ->end()) ? " |\n" : "\n", Quote);
} else {
const JobList *Jobs = cast<JobList>(&J);
- for (JobList::const_iterator
+ for (JobList::const_iterator
it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
PrintJob(OS, **it, Terminator, Quote);
}
}
-bool Compilation::CleanupFileList(const ArgStringList &Files,
+bool Compilation::CleanupFileList(const ArgStringList &Files,
bool IssueErrors) const {
bool Success = true;
- for (ArgStringList::const_iterator
+ for (ArgStringList::const_iterator
it = Files.begin(), ie = Files.end(); it != ie; ++it) {
llvm::sys::Path P(*it);
std::string Error;
@@ -92,7 +94,7 @@ bool Compilation::CleanupFileList(const ArgStringList &Files,
// FIXME: Grumble, P.exists() is broken. PR3837.
struct stat buf;
- if (::stat(P.c_str(), &buf) == 0
+ if (::stat(P.c_str(), &buf) == 0
|| errno != ENOENT) {
if (IssueErrors)
getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
@@ -112,12 +114,12 @@ int Compilation::ExecuteCommand(const Command &C,
Argv[0] = C.getExecutable();
std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
Argv[C.getArguments().size() + 1] = 0;
-
+
if (getDriver().CCCEcho || getArgs().hasArg(options::OPT_v))
PrintJob(llvm::errs(), C, "\n", false);
-
+
std::string Error;
- int Res =
+ int Res =
llvm::sys::Program::ExecuteAndWait(Prog, Argv,
/*env*/0, /*redirects*/0,
/*secondsToWait*/0, /*memoryLimit*/0,
@@ -126,7 +128,7 @@ int Compilation::ExecuteCommand(const Command &C,
assert(Res && "Error string set with 0 result code!");
getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
}
-
+
if (Res)
FailingCommand = &C;
@@ -134,7 +136,7 @@ int Compilation::ExecuteCommand(const Command &C,
return Res;
}
-int Compilation::ExecuteJob(const Job &J,
+int Compilation::ExecuteJob(const Job &J,
const Command *&FailingCommand) const {
if (const Command *C = dyn_cast<Command>(&J)) {
return ExecuteCommand(*C, FailingCommand);
@@ -142,13 +144,13 @@ int Compilation::ExecuteJob(const Job &J,
// Piped commands with a single job are easy.
if (PJ->size() == 1)
return ExecuteCommand(**PJ->begin(), FailingCommand);
-
+
FailingCommand = *PJ->begin();
getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe";
return 1;
} else {
const JobList *Jobs = cast<JobList>(&J);
- for (JobList::const_iterator
+ for (JobList::const_iterator
it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
if (int Res = ExecuteJob(**it, FailingCommand))
return Res;
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 1b0b5615dfbc..b4693f2ac986 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -37,22 +37,34 @@
using namespace clang::driver;
using namespace clang;
+// Used to set values for "production" clang, for releases.
+// #define USE_PRODUCTION_CLANG
+
Driver::Driver(const char *_Name, const char *_Dir,
const char *_DefaultHostTriple,
const char *_DefaultImageName,
- Diagnostic &_Diags)
- : Opts(new OptTable()), Diags(_Diags),
+ bool IsProduction, Diagnostic &_Diags)
+ : Opts(new OptTable()), Diags(_Diags),
Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
DefaultImageName(_DefaultImageName),
Host(0),
CCCIsCXX(false), CCCEcho(false), CCCPrintBindings(false),
- CCCGenericGCCName("gcc"), CCCUseClang(true), CCCUseClangCXX(false),
- CCCUseClangCPP(true), CCCUsePCH(true),
- SuppressMissingInputWarning(false)
-{
- // Only use clang on i386 and x86_64 by default.
- CCCClangArchs.insert("i386");
- CCCClangArchs.insert("x86_64");
+ CCCGenericGCCName("gcc"), CCCUseClang(true),
+ CCCUseClangCXX(true), CCCUseClangCPP(true), CCCUsePCH(true),
+ SuppressMissingInputWarning(false) {
+ if (IsProduction) {
+ // In a "production" build, only use clang on architectures we expect to
+ // work, and don't use clang C++.
+ //
+ // During development its more convenient to always have the driver use
+ // clang, but we don't want users to be confused when things don't work, or
+ // to file bugs for things we don't support.
+ CCCClangArchs.insert(llvm::Triple::x86);
+ CCCClangArchs.insert(llvm::Triple::x86_64);
+ CCCClangArchs.insert(llvm::Triple::arm);
+
+ CCCUseClangCXX = false;
+ }
}
Driver::~Driver() {
@@ -60,20 +72,20 @@ Driver::~Driver() {
delete Host;
}
-InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
+InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
const char **ArgEnd) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
-
+
// FIXME: Handle '@' args (or at least error on them).
unsigned Index = 0, End = ArgEnd - ArgBegin;
while (Index < End) {
- // gcc's handling of empty arguments doesn't make
- // sense, but this is not a common use case. :)
+ // gcc's handling of empty arguments doesn't make sense, but this is not a
+ // common use case. :)
//
- // We just ignore them here (note that other things may
- // still take them as arguments).
+ // We just ignore them here (note that other things may still take them as
+ // arguments).
if (Args->getArgString(Index)[0] == '\0') {
++Index;
continue;
@@ -105,28 +117,27 @@ InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
Compilation *Driver::BuildCompilation(int argc, const char **argv) {
llvm::PrettyStackTraceString CrashInfo("Compilation construction");
- // FIXME: Handle environment options which effect driver behavior,
- // somewhere (client?). GCC_EXEC_PREFIX, COMPILER_PATH,
- // LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS, QA_OVERRIDE_GCC3_OPTIONS.
+ // FIXME: Handle environment options which effect driver behavior, somewhere
+ // (client?). GCC_EXEC_PREFIX, COMPILER_PATH, LIBRARY_PATH, LPATH,
+ // CC_PRINT_OPTIONS.
// FIXME: What are we going to do with -V and -b?
- // FIXME: This stuff needs to go into the Compilation, not the
- // driver.
+ // FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintOptions = false, CCCPrintActions = false;
const char **Start = argv + 1, **End = argv + argc;
const char *HostTriple = DefaultHostTriple.c_str();
- // Read -ccc args.
+ // Read -ccc args.
//
- // FIXME: We need to figure out where this behavior should
- // live. Most of it should be outside in the client; the parts that
- // aren't should have proper options, either by introducing new ones
- // or by overloading gcc ones like -V or -b.
+ // FIXME: We need to figure out where this behavior should live. Most of it
+ // should be outside in the client; the parts that aren't should have proper
+ // options, either by introducing new ones or by overloading gcc ones like -V
+ // or -b.
for (; Start != End && memcmp(*Start, "-ccc-", 5) == 0; ++Start) {
const char *Opt = *Start + 5;
-
+
if (!strcmp(Opt, "print-options")) {
CCCPrintOptions = true;
} else if (!strcmp(Opt, "print-phases")) {
@@ -137,13 +148,15 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
CCCIsCXX = true;
} else if (!strcmp(Opt, "echo")) {
CCCEcho = true;
-
+
} else if (!strcmp(Opt, "gcc-name")) {
assert(Start+1 < End && "FIXME: -ccc- argument handling.");
CCCGenericGCCName = *++Start;
} else if (!strcmp(Opt, "clang-cxx")) {
CCCUseClangCXX = true;
+ } else if (!strcmp(Opt, "no-clang-cxx")) {
+ CCCUseClangCXX = false;
} else if (!strcmp(Opt, "pch-is-pch")) {
CCCUsePCH = true;
} else if (!strcmp(Opt, "pch-is-pth")) {
@@ -154,27 +167,35 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
CCCUseClangCPP = false;
} else if (!strcmp(Opt, "clang-archs")) {
assert(Start+1 < End && "FIXME: -ccc- argument handling.");
- const char *Cur = *++Start;
-
+ llvm::StringRef Cur = *++Start;
+
CCCClangArchs.clear();
- for (;;) {
- const char *Next = strchr(Cur, ',');
+ while (!Cur.empty()) {
+ std::pair<llvm::StringRef, llvm::StringRef> Split = Cur.split(',');
- if (Next) {
- if (Cur != Next)
- CCCClangArchs.insert(std::string(Cur, Next));
- Cur = Next + 1;
- } else {
- if (*Cur != '\0')
- CCCClangArchs.insert(std::string(Cur));
- break;
+ if (!Split.first.empty()) {
+ llvm::Triple::ArchType Arch =
+ llvm::Triple(Split.first, "", "").getArch();
+
+ if (Arch == llvm::Triple::UnknownArch) {
+ // FIXME: Error handling.
+ llvm::errs() << "invalid arch name: " << Split.first << "\n";
+ exit(1);
+ }
+
+ CCCClangArchs.insert(Arch);
}
- }
+ Cur = Split.second;
+ }
} else if (!strcmp(Opt, "host-triple")) {
assert(Start+1 < End && "FIXME: -ccc- argument handling.");
HostTriple = *++Start;
+ } else if (!strcmp(Opt, "install-dir")) {
+ assert(Start+1 < End && "FIXME: -ccc- argument handling.");
+ Dir = *++Start;
+
} else {
// FIXME: Error handling.
llvm::errs() << "invalid option: " << *Start << "\n";
@@ -187,7 +208,7 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
Host = GetHostInfo(HostTriple);
// The compilation takes ownership of Args.
- Compilation *C = new Compilation(*this, *Host->getToolChain(*Args), Args);
+ Compilation *C = new Compilation(*this, *Host->CreateToolChain(*Args), Args);
// FIXME: This behavior shouldn't be here.
if (CCCPrintOptions) {
@@ -198,10 +219,10 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
if (!HandleImmediateArgs(*C))
return C;
- // Construct the list of abstract actions to perform for this
- // compilation. We avoid passing a Compilation here simply to
- // enforce the abstraction that pipelining is not host or toolchain
- // dependent (other than the driver driver test).
+ // Construct the list of abstract actions to perform for this compilation. We
+ // avoid passing a Compilation here simply to enforce the abstraction that
+ // pipelining is not host or toolchain dependent (other than the driver driver
+ // test).
if (Host->useDriverDriver())
BuildUniversalActions(C->getArgs(), C->getActions());
else
@@ -230,7 +251,7 @@ int Driver::ExecuteCompilation(const Compilation &C) const {
const Command *FailingCommand = 0;
int Res = C.ExecuteJob(C.getJobs(), FailingCommand);
-
+
// Remove temp files.
C.CleanupFileList(C.getTempFiles());
@@ -254,10 +275,10 @@ int Driver::ExecuteCompilation(const Compilation &C) const {
if (!IsFriendlyTool || Res != 1) {
// FIXME: See FIXME above regarding result code interpretation.
if (Res < 0)
- Diag(clang::diag::err_drv_command_signalled)
+ Diag(clang::diag::err_drv_command_signalled)
<< Source.getClassName() << -Res;
else
- Diag(clang::diag::err_drv_command_failed)
+ Diag(clang::diag::err_drv_command_failed)
<< Source.getClassName() << Res;
}
}
@@ -267,7 +288,7 @@ int Driver::ExecuteCompilation(const Compilation &C) const {
void Driver::PrintOptions(const ArgList &Args) const {
unsigned i = 0;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
it != ie; ++it, ++i) {
Arg *A = *it;
llvm::errs() << "Option " << i << " - "
@@ -284,10 +305,10 @@ void Driver::PrintOptions(const ArgList &Args) const {
static std::string getOptionHelpName(const OptTable &Opts, options::ID Id) {
std::string Name = Opts.getOptionName(Id);
-
+
// Add metavar, if used.
switch (Opts.getOptionKind(Id)) {
- case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
+ case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
assert(0 && "Invalid option with help text.");
case Option::MultiArgClass: case Option::JoinedAndSeparateClass:
@@ -333,11 +354,13 @@ void Driver::PrintHelp(bool ShowHidden) const {
OptionHelp.push_back(std::make_pair("-ccc-gcc-name",
"Name for native GCC compiler"));
OptionHelp.push_back(std::make_pair("-ccc-clang-cxx",
- "Use the clang compiler for C++"));
+ "Enable the clang compiler for C++"));
+ OptionHelp.push_back(std::make_pair("-ccc-no-clang-cxx",
+ "Disable the clang compiler for C++"));
OptionHelp.push_back(std::make_pair("-ccc-no-clang",
- "Never use the clang compiler"));
+ "Disable the clang compiler"));
OptionHelp.push_back(std::make_pair("-ccc-no-clang-cpp",
- "Never use the clang preprocessor"));
+ "Disable the clang preprocessor"));
OptionHelp.push_back(std::make_pair("-ccc-clang-archs",
"Comma separate list of architectures "
"to use the clang compiler for"));
@@ -348,7 +371,9 @@ void Driver::PrintHelp(bool ShowHidden) const {
OptionHelp.push_back(std::make_pair("\nDEBUG/DEVELOPMENT OPTIONS:",""));
OptionHelp.push_back(std::make_pair("-ccc-host-triple",
- "Simulate running on the given target"));
+ "Simulate running on the given target"));
+ OptionHelp.push_back(std::make_pair("-ccc-install-dir",
+ "Simulate installation in the given directory"));
OptionHelp.push_back(std::make_pair("-ccc-print-options",
"Dump parsed command line arguments"));
OptionHelp.push_back(std::make_pair("-ccc-print-phases",
@@ -360,15 +385,14 @@ void Driver::PrintHelp(bool ShowHidden) const {
"arguments to prepend to the command line"));
}
- // Find the maximum option length.
+ // Find the maximum option length.
unsigned OptionFieldWidth = 0;
for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
// Skip titles.
if (!OptionHelp[i].second)
continue;
- // Limit the amount of padding we are willing to give up for
- // alignment.
+ // Limit the amount of padding we are willing to give up for alignment.
unsigned Length = OptionHelp[i].first.size();
if (Length <= 23)
OptionFieldWidth = std::max(OptionFieldWidth, Length);
@@ -385,60 +409,51 @@ void Driver::PrintHelp(bool ShowHidden) const {
OS.flush();
}
-void Driver::PrintVersion(const Compilation &C) const {
- static char buf[] = "$URL: https://ed@llvm.org/svn/llvm-project/cfe/trunk/lib/Driver/Driver.cpp $";
- char *zap = strstr(buf, "/lib/Driver");
- if (zap)
- *zap = 0;
- zap = strstr(buf, "/clang/tools/clang");
- if (zap)
- *zap = 0;
- const char *vers = buf+6;
- // FIXME: Add cmake support and remove #ifdef
-#ifdef SVN_REVISION
- const char *revision = SVN_REVISION;
-#else
- const char *revision = "";
+void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
+#ifdef CLANG_VENDOR
+ OS << CLANG_VENDOR;
#endif
- // FIXME: The following handlers should use a callback mechanism, we
- // don't know what the client would like to do.
-
- llvm::errs() << "clang version " CLANG_VERSION_STRING " ("
- << vers << " " << revision << ")" << '\n';
+ OS << "clang version " CLANG_VERSION_STRING " ("
+ << getClangSubversionPath();
+ if (unsigned Revision = getClangSubversionRevision())
+ OS << " " << Revision;
+ OS << ")" << '\n';
const ToolChain &TC = C.getDefaultToolChain();
- llvm::errs() << "Target: " << TC.getTripleString() << '\n';
+ OS << "Target: " << TC.getTripleString() << '\n';
// Print the threading model.
//
// FIXME: Implement correctly.
- llvm::errs() << "Thread model: " << "posix" << '\n';
+ OS << "Thread model: " << "posix" << '\n';
}
bool Driver::HandleImmediateArgs(const Compilation &C) {
- // The order these options are handled in in gcc is all over the
- // place, but we don't expect inconsistencies w.r.t. that to matter
- // in practice.
+ // The order these options are handled in in gcc is all over the place, but we
+ // don't expect inconsistencies w.r.t. that to matter in practice.
if (C.getArgs().hasArg(options::OPT_dumpversion)) {
llvm::outs() << CLANG_VERSION_STRING "\n";
return false;
}
- if (C.getArgs().hasArg(options::OPT__help) ||
+ if (C.getArgs().hasArg(options::OPT__help) ||
C.getArgs().hasArg(options::OPT__help_hidden)) {
PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
return false;
}
if (C.getArgs().hasArg(options::OPT__version)) {
- PrintVersion(C);
+ // Follow gcc behavior and use stdout for --version and stderr for -v.
+ PrintVersion(C, llvm::outs());
return false;
}
- if (C.getArgs().hasArg(options::OPT_v) ||
+ if (C.getArgs().hasArg(options::OPT_v) ||
C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
- PrintVersion(C);
+ PrintVersion(C, llvm::errs());
SuppressMissingInputWarning = true;
}
@@ -453,7 +468,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
llvm::outs() << "\n";
llvm::outs() << "libraries: =";
- for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
+ for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
ie = TC.getFilePaths().end(); it != ie; ++it) {
if (it != TC.getFilePaths().begin())
llvm::outs() << ':';
@@ -463,22 +478,20 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
- // FIXME: The following handlers should use a callback mechanism, we
- // don't know what the client would like to do.
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
- llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC).toString()
- << "\n";
+ llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC) << "\n";
return false;
}
if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
- llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC).toString()
- << "\n";
+ llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC) << "\n";
return false;
}
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
- llvm::outs() << GetFilePath("libgcc.a", TC).toString() << "\n";
+ llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
return false;
}
@@ -489,7 +502,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
switch (C.getDefaultToolChain().getTriple().getArch()) {
default:
break;
-
+
case llvm::Triple::x86_64:
llvm::outs() << "x86_64;@m64" << "\n";
break;
@@ -511,7 +524,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
case llvm::Triple::ppc:
llvm::outs() << "." << "\n";
break;
-
+
case llvm::Triple::x86_64:
llvm::outs() << "x86_64" << "\n";
break;
@@ -526,20 +539,19 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return true;
}
-static unsigned PrintActions1(const Compilation &C,
- Action *A,
+static unsigned PrintActions1(const Compilation &C, Action *A,
std::map<Action*, unsigned> &Ids) {
if (Ids.count(A))
return Ids[A];
-
+
std::string str;
llvm::raw_string_ostream os(str);
-
+
os << Action::getClassName(A->getKind()) << ", ";
- if (InputAction *IA = dyn_cast<InputAction>(A)) {
+ if (InputAction *IA = dyn_cast<InputAction>(A)) {
os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\"";
} else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
- os << '"' << (BIA->getArchName() ? BIA->getArchName() :
+ os << '"' << (BIA->getArchName() ? BIA->getArchName() :
C.getDefaultToolChain().getArchName()) << '"'
<< ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
} else {
@@ -555,7 +567,7 @@ static unsigned PrintActions1(const Compilation &C,
unsigned Id = Ids.size();
Ids[A] = Id;
- llvm::errs() << Id << ": " << os.str() << ", "
+ llvm::errs() << Id << ": " << os.str() << ", "
<< types::getTypeName(A->getType()) << "\n";
return Id;
@@ -563,65 +575,66 @@ static unsigned PrintActions1(const Compilation &C,
void Driver::PrintActions(const Compilation &C) const {
std::map<Action*, unsigned> Ids;
- for (ActionList::const_iterator it = C.getActions().begin(),
+ for (ActionList::const_iterator it = C.getActions().begin(),
ie = C.getActions().end(); it != ie; ++it)
PrintActions1(C, *it, Ids);
}
-void Driver::BuildUniversalActions(const ArgList &Args,
+void Driver::BuildUniversalActions(const ArgList &Args,
ActionList &Actions) const {
- llvm::PrettyStackTraceString CrashInfo("Building actions for universal build");
- // Collect the list of architectures. Duplicates are allowed, but
- // should only be handled once (in the order seen).
+ llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
+ // Collect the list of architectures. Duplicates are allowed, but should only
+ // be handled once (in the order seen).
llvm::StringSet<> ArchNames;
llvm::SmallVector<const char *, 4> Archs;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
it != ie; ++it) {
Arg *A = *it;
if (A->getOption().getId() == options::OPT_arch) {
- const char *Name = A->getValue(Args);
-
- // FIXME: We need to handle canonicalization of the specified
- // arch?
+ // Validate the option here; we don't save the type here because its
+ // particular spelling may participate in other driver choices.
+ llvm::Triple::ArchType Arch =
+ llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+ if (Arch == llvm::Triple::UnknownArch) {
+ Diag(clang::diag::err_drv_invalid_arch_name)
+ << A->getAsString(Args);
+ continue;
+ }
A->claim();
- if (ArchNames.insert(Name))
- Archs.push_back(Name);
+ if (ArchNames.insert(A->getValue(Args)))
+ Archs.push_back(A->getValue(Args));
}
}
- // When there is no explicit arch for this platform, make sure we
- // still bind the architecture (to the default) so that -Xarch_ is
- // handled correctly.
+ // When there is no explicit arch for this platform, make sure we still bind
+ // the architecture (to the default) so that -Xarch_ is handled correctly.
if (!Archs.size())
Archs.push_back(0);
- // 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.
+ // 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)
+ Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs)
<< A->getAsString(Args);
}
ActionList SingleActions;
BuildActions(Args, SingleActions);
- // Add in arch binding and lipo (if necessary) for every top level
- // action.
+ // Add in arch binding and lipo (if necessary) for every top level action.
for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) {
Action *Act = SingleActions[i];
- // Make sure we can lipo this kind of output. If not (and it is an
- // actual output) then we disallow, since we can't create an
- // output file with the right name without overwriting it. We
- // could remove this oddity by just changing the output names to
- // include the arch, which would also fix
+ // Make sure we can lipo this kind of output. If not (and it is an actual
+ // output) then we disallow, since we can't create an output file with the
+ // right name without overwriting it. We could remove this oddity by just
+ // changing the output names to include the arch, which would also fix
// -save-temps. Compatibility wins for now.
if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
@@ -632,8 +645,8 @@ void Driver::BuildUniversalActions(const ArgList &Args,
for (unsigned i = 0, e = Archs.size(); i != e; ++i)
Inputs.push_back(new BindArchAction(Act, Archs[i]));
- // Lipo if necessary, We do it this way because we need to set the
- // arch flag so that -Xarch_ gets overwritten.
+ // Lipo if necessary, we do it this way because we need to set the arch flag
+ // so that -Xarch_ gets overwritten.
if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
Actions.append(Inputs.begin(), Inputs.end());
else
@@ -645,15 +658,14 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
// Start by constructing the list of inputs and their types.
- // Track the current user specified (-x) input. We also explicitly
- // track the argument used to set the type; we only want to claim
- // the type when we actually use it, so we warn about unused -x
- // arguments.
+ // Track the current user specified (-x) input. We also explicitly track the
+ // argument used to set the type; we only want to claim the type when we
+ // actually use it, so we warn about unused -x arguments.
types::ID InputType = types::TY_Nothing;
Arg *InputTypeArg = 0;
llvm::SmallVector<std::pair<types::ID, const Arg*>, 16> Inputs;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
it != ie; ++it) {
Arg *A = *it;
@@ -669,19 +681,18 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// stdin must be handled specially.
if (memcmp(Value, "-", 2) == 0) {
- // If running with -E, treat as a C input (this changes the
- // builtin macros, for example). This may be overridden by
- // -ObjC below.
+ // If running with -E, treat as a C input (this changes the builtin
+ // macros, for example). This may be overridden by -ObjC below.
//
- // Otherwise emit an error but still use a valid type to
- // avoid spurious errors (e.g., no inputs).
+ // Otherwise emit an error but still use a valid type to avoid
+ // spurious errors (e.g., no inputs).
if (!Args.hasArg(options::OPT_E, false))
Diag(clang::diag::err_drv_unknown_stdin_type);
Ty = types::TY_C;
} else {
- // Otherwise lookup by extension, and fallback to ObjectType
- // if not found. We use a host hook here because Darwin at
- // least has its own idea of what .s is.
+ // Otherwise lookup by extension, and fallback to ObjectType if not
+ // found. We use a host hook here because Darwin at least has its own
+ // idea of what .s is.
if (const char *Ext = strrchr(Value, '.'))
Ty = Host->lookupTypeForExtension(Ext + 1);
@@ -692,7 +703,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// -ObjC and -ObjC++ override the default language, but only for "source
// files". We just treat everything that isn't a linker input as a
// source file.
- //
+ //
// FIXME: Clean this up if we move the phase sequence into the type.
if (Ty != types::TY_Object) {
if (Args.hasArg(options::OPT_ObjC))
@@ -706,28 +717,26 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
Ty = InputType;
}
- // Check that the file exists. It isn't clear this is worth
- // doing, since the tool presumably does this anyway, and this
- // just adds an extra stat to the equation, but this is gcc
- // compatible.
+ // Check that the file exists. It isn't clear this is worth doing, since
+ // the tool presumably does this anyway, and this just adds an extra stat
+ // to the equation, but this is gcc compatible.
if (memcmp(Value, "-", 2) != 0 && !llvm::sys::Path(Value).exists())
Diag(clang::diag::err_drv_no_such_file) << A->getValue(Args);
else
Inputs.push_back(std::make_pair(Ty, A));
} else if (A->getOption().isLinkerInput()) {
- // Just treat as object type, we could make a special type for
- // this if necessary.
+ // Just treat as object type, we could make a special type for this if
+ // necessary.
Inputs.push_back(std::make_pair(types::TY_Object, A));
} else if (A->getOption().getId() == options::OPT_x) {
- InputTypeArg = A;
+ InputTypeArg = A;
InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args));
// Follow gcc behavior and treat as linker input for invalid -x
- // options. Its not clear why we shouldn't just revert to
- // unknown; but this isn't very important, we might as well be
- // bug comatible.
+ // options. Its not clear why we shouldn't just revert to unknown; but
+ // this isn't very important, we might as well be bug comatible.
if (!InputType) {
Diag(clang::diag::err_drv_unknown_language) << A->getValue(Args);
InputType = types::TY_Object;
@@ -740,9 +749,9 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
return;
}
- // Determine which compilation mode we are in. We look for options
- // which affect the phase, starting with the earliest phases, and
- // record which option we used to determine the final phase.
+ // Determine which compilation mode we are in. We look for options which
+ // affect the phase, starting with the earliest phases, and record which
+ // option we used to determine the final phase.
Arg *FinalPhaseArg = 0;
phases::ID FinalPhase;
@@ -751,24 +760,25 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
(FinalPhaseArg = Args.getLastArg(options::OPT_M)) ||
(FinalPhaseArg = Args.getLastArg(options::OPT_MM))) {
FinalPhase = phases::Preprocess;
-
- // -{fsyntax-only,-analyze,emit-llvm,S} only run up to the compiler.
+
+ // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
} else if ((FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) ||
(FinalPhaseArg = Args.getLastArg(options::OPT__analyze,
options::OPT__analyze_auto)) ||
+ (FinalPhaseArg = Args.getLastArg(options::OPT_emit_ast)) ||
(FinalPhaseArg = Args.getLastArg(options::OPT_S))) {
FinalPhase = phases::Compile;
// -c only runs up to the assembler.
} else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) {
FinalPhase = phases::Assemble;
-
+
// Otherwise do everything.
} else
FinalPhase = phases::Link;
- // Reject -Z* at the top level, these options should never have been
- // exposed by gcc.
+ // Reject -Z* at the top level, these options should never have been exposed
+ // by gcc.
if (Arg *A = Args.getLastArg(options::OPT_Z_Joined))
Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args);
@@ -781,19 +791,28 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
unsigned NumSteps = types::getNumCompilationPhases(InputType);
assert(NumSteps && "Invalid number of steps!");
- // If the first step comes after the final phase we are doing as
- // part of this compilation, warn the user about it.
+ // If the first step comes after the final phase we are doing as part of
+ // this compilation, warn the user about it.
phases::ID InitialPhase = types::getCompilationPhase(InputType, 0);
if (InitialPhase > FinalPhase) {
// Claim here to avoid the more general unused warning.
InputArg->claim();
- Diag(clang::diag::warn_drv_input_file_unused)
- << InputArg->getAsString(Args)
- << getPhaseName(InitialPhase)
- << FinalPhaseArg->getOption().getName();
+
+ // Special case '-E' warning on a previously preprocessed file to make
+ // more sense.
+ if (InitialPhase == phases::Compile && FinalPhase == phases::Preprocess &&
+ getPreprocessedType(InputType) == types::TY_INVALID)
+ Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
+ << InputArg->getAsString(Args)
+ << FinalPhaseArg->getOption().getName();
+ else
+ Diag(clang::diag::warn_drv_input_file_unused)
+ << InputArg->getAsString(Args)
+ << getPhaseName(InitialPhase)
+ << FinalPhaseArg->getOption().getName();
continue;
}
-
+
// Build the pipeline for this file.
Action *Current = new InputAction(*InputArg, InputType);
for (unsigned i = 0; i != NumSteps; ++i) {
@@ -811,9 +830,9 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
break;
}
- // Some types skip the assembler phase (e.g., llvm-bc), but we
- // can't encode this in the steps because the intermediate type
- // depends on arguments. Just special case here.
+ // Some types skip the assembler phase (e.g., llvm-bc), but we can't
+ // encode this in the steps because the intermediate type depends on
+ // arguments. Just special case here.
if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm)
continue;
@@ -852,16 +871,18 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
return new PreprocessJobAction(Input, OutputTy);
}
case phases::Precompile:
- return new PrecompileJobAction(Input, types::TY_PCH);
+ return new PrecompileJobAction(Input, types::TY_PCH);
case phases::Compile: {
if (Args.hasArg(options::OPT_fsyntax_only)) {
return new CompileJobAction(Input, types::TY_Nothing);
} else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) {
return new AnalyzeJobAction(Input, types::TY_Plist);
+ } else if (Args.hasArg(options::OPT_emit_ast)) {
+ return new CompileJobAction(Input, types::TY_AST);
} else if (Args.hasArg(options::OPT_emit_llvm) ||
Args.hasArg(options::OPT_flto) ||
Args.hasArg(options::OPT_O4)) {
- types::ID Output =
+ types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVMAsm : types::TY_LLVMBC;
return new CompileJobAction(Input, Output);
} else {
@@ -881,11 +902,10 @@ void Driver::BuildJobs(Compilation &C) const {
bool SaveTemps = C.getArgs().hasArg(options::OPT_save_temps);
bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
- // FIXME: Pipes are forcibly disabled until we support executing
- // them.
+ // FIXME: Pipes are forcibly disabled until we support executing them.
if (!CCCPrintBindings)
UsePipes = false;
-
+
// -save-temps inhibits pipes.
if (SaveTemps && UsePipes) {
Diag(clang::diag::warn_drv_pipe_ignored_with_save_temps);
@@ -894,32 +914,31 @@ void Driver::BuildJobs(Compilation &C) const {
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
- // It is an error to provide a -o option if we are making multiple
- // output files.
+ // It is an error to provide a -o option if we are making multiple output
+ // files.
if (FinalOutput) {
unsigned NumOutputs = 0;
- for (ActionList::const_iterator it = C.getActions().begin(),
+ for (ActionList::const_iterator it = C.getActions().begin(),
ie = C.getActions().end(); it != ie; ++it)
if ((*it)->getType() != types::TY_Nothing)
++NumOutputs;
-
+
if (NumOutputs > 1) {
Diag(clang::diag::err_drv_output_argument_with_multiple_files);
FinalOutput = 0;
}
}
- for (ActionList::const_iterator it = C.getActions().begin(),
+ for (ActionList::const_iterator it = C.getActions().begin(),
ie = C.getActions().end(); it != ie; ++it) {
Action *A = *it;
- // If we are linking an image for multiple archs then the linker
- // wants -arch_multiple and -final_output <final image
- // name>. Unfortunately, this doesn't fit in cleanly because we
- // have to pass this information down.
+ // If we are linking an image for multiple archs then the linker wants
+ // -arch_multiple and -final_output <final image name>. Unfortunately, this
+ // doesn't fit in cleanly because we have to pass this information down.
//
- // FIXME: This is a hack; find a cleaner way to integrate this
- // into the process.
+ // FIXME: This is a hack; find a cleaner way to integrate this into the
+ // process.
const char *LinkingOutput = 0;
if (isa<LipoJobAction>(A)) {
if (FinalOutput)
@@ -929,41 +948,41 @@ void Driver::BuildJobs(Compilation &C) const {
}
InputInfo II;
- BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+ BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+ /*BoundArch*/0,
/*CanAcceptPipe*/ true,
/*AtTopLevel*/ true,
/*LinkingOutput*/ LinkingOutput,
II);
}
- // If the user passed -Qunused-arguments or there were errors, don't
- // warn about any unused arguments.
- if (Diags.getNumErrors() ||
+ // If the user passed -Qunused-arguments or there were errors, don't warn
+ // about any unused arguments.
+ if (Diags.getNumErrors() ||
C.getArgs().hasArg(options::OPT_Qunused_arguments))
return;
// Claim -### here.
(void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
-
+
for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
it != ie; ++it) {
Arg *A = *it;
-
+
// FIXME: It would be nice to be able to send the argument to the
- // Diagnostic, so that extra values, position, and so on could be
- // printed.
+ // Diagnostic, so that extra values, position, and so on could be printed.
if (!A->isClaimed()) {
if (A->getOption().hasNoArgumentUnused())
continue;
- // Suppress the warning automatically if this is just a flag,
- // and it is an instance of an argument we already claimed.
+ // Suppress the warning automatically if this is just a flag, and it is an
+ // instance of an argument we already claimed.
const Option &Opt = A->getOption();
if (isa<FlagOption>(Opt)) {
bool DuplicateClaimed = false;
// FIXME: Use iterator.
- for (ArgList::const_iterator it = C.getArgs().begin(),
+ for (ArgList::const_iterator it = C.getArgs().begin(),
ie = C.getArgs().end(); it != ie; ++it) {
if ((*it)->isClaimed() && (*it)->getOption().matches(Opt.getId())) {
DuplicateClaimed = true;
@@ -975,7 +994,7 @@ void Driver::BuildJobs(Compilation &C) const {
continue;
}
- Diag(clang::diag::warn_drv_unused_argument)
+ Diag(clang::diag::warn_drv_unused_argument)
<< A->getAsString(C.getArgs());
}
}
@@ -984,21 +1003,21 @@ void Driver::BuildJobs(Compilation &C) const {
void Driver::BuildJobsForAction(Compilation &C,
const Action *A,
const ToolChain *TC,
+ const char *BoundArch,
bool CanAcceptPipe,
bool AtTopLevel,
const char *LinkingOutput,
InputInfo &Result) const {
- llvm::PrettyStackTraceString CrashInfo("Building compilation jobs for action");
+ llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
- // FIXME: Pipes are forcibly disabled until we support executing
- // them.
+ // FIXME: Pipes are forcibly disabled until we support executing them.
if (!CCCPrintBindings)
UsePipes = false;
if (const InputAction *IA = dyn_cast<InputAction>(A)) {
- // FIXME: It would be nice to not claim this here; maybe the old
- // scheme of just using Args was better?
+ // FIXME: It would be nice to not claim this here; maybe the old scheme of
+ // just using Args was better?
const Arg &Input = IA->getInputArg();
Input.claim();
if (isa<PositionalArg>(Input)) {
@@ -1010,28 +1029,23 @@ void Driver::BuildJobsForAction(Compilation &C,
}
if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
- const char *ArchName = BAA->getArchName();
+ const ToolChain *TC = &C.getDefaultToolChain();
+
std::string Arch;
- if (!ArchName) {
- Arch = C.getDefaultToolChain().getArchName();
- ArchName = Arch.c_str();
- }
- BuildJobsForAction(C,
- *BAA->begin(),
- Host->getToolChain(C.getArgs(), ArchName),
- CanAcceptPipe,
- AtTopLevel,
- LinkingOutput,
- Result);
+ if (BAA->getArchName())
+ TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName());
+
+ BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
+ CanAcceptPipe, AtTopLevel, LinkingOutput, Result);
return;
}
const JobAction *JA = cast<JobAction>(A);
const Tool &T = TC->SelectTool(C, *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 (irrelevant since we don't support combine yet).
+
+ // 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
+ // (irrelevant since we don't support combine yet).
bool UseIntegratedCPP = false;
const ActionList *Inputs = &A->getInputs();
if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin())) {
@@ -1050,18 +1064,16 @@ void Driver::BuildJobsForAction(Compilation &C,
for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
it != ie; ++it) {
InputInfo II;
- BuildJobsForAction(C, *it, TC, TryToUsePipeInput,
- /*AtTopLevel*/false,
- LinkingOutput,
- II);
+ BuildJobsForAction(C, *it, TC, BoundArch, TryToUsePipeInput,
+ /*AtTopLevel*/false, LinkingOutput, II);
InputInfos.push_back(II);
}
// Determine if we should output to a pipe.
bool OutputToPipe = false;
if (CanAcceptPipe && T.canPipeOutput()) {
- // Some actions default to writing to a pipe if they are the top
- // level phase and there was no user override.
+ // Some actions default to writing to a pipe if they are the top level phase
+ // and there was no user override.
//
// FIXME: Is there a better way to handle this?
if (AtTopLevel) {
@@ -1082,8 +1094,8 @@ void Driver::BuildJobsForAction(Compilation &C,
// Always use the first input as the base input.
const char *BaseInput = InputInfos[0].getBaseInput();
- // Determine the place to write output to (nothing, pipe, or
- // filename) and where to put the new job.
+ // Determine the place to write output to (nothing, pipe, or filename) and
+ // where to put the new job.
if (JA->getType() == types::TY_Nothing) {
Result = InputInfo(A->getType(), BaseInput);
} else if (OutputToPipe) {
@@ -1091,8 +1103,8 @@ void Driver::BuildJobsForAction(Compilation &C,
PipedJob *PJ = dyn_cast<PipedJob>(Dest);
if (!PJ) {
PJ = new PipedJob();
- // FIXME: Temporary hack so that -ccc-print-bindings work until
- // we have pipe support. Please remove later.
+ // FIXME: Temporary hack so that -ccc-print-bindings work until we have
+ // pipe support. Please remove later.
if (!CCCPrintBindings)
cast<JobList>(Dest)->addJob(PJ);
Dest = PJ;
@@ -1113,12 +1125,12 @@ void Driver::BuildJobsForAction(Compilation &C,
}
llvm::errs() << "], output: " << Result.getAsString() << "\n";
} else {
- T.ConstructJob(C, *JA, *Dest, Result, InputInfos,
- C.getArgsForToolChain(TC), LinkingOutput);
+ T.ConstructJob(C, *JA, *Dest, Result, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
}
}
-const char *Driver::GetNamedOutputPath(Compilation &C,
+const char *Driver::GetNamedOutputPath(Compilation &C,
const JobAction &JA,
const char *BaseInput,
bool AtTopLevel) const {
@@ -1131,7 +1143,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
// Output to a temporary file?
if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) {
- std::string TmpName =
+ std::string TmpName =
GetTemporaryPath(types::getTypeTempSuffix(JA.getType()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
@@ -1156,8 +1168,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
}
- // As an annoying special case, PCH generation doesn't strip the
- // pathname.
+ // As an annoying special case, PCH generation doesn't strip the pathname.
if (JA.getType() == types::TY_PCH) {
BasePath.eraseComponent();
if (BasePath.isEmpty())
@@ -1170,43 +1181,41 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
}
}
-llvm::sys::Path Driver::GetFilePath(const char *Name,
- const ToolChain &TC) const {
+std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
const ToolChain::path_list &List = TC.getFilePaths();
- for (ToolChain::path_list::const_iterator
+ for (ToolChain::path_list::const_iterator
it = List.begin(), ie = List.end(); it != ie; ++it) {
llvm::sys::Path P(*it);
P.appendComponent(Name);
if (P.exists())
- return P;
+ return P.str();
}
- return llvm::sys::Path(Name);
+ return Name;
}
-llvm::sys::Path Driver::GetProgramPath(const char *Name,
- const ToolChain &TC,
- bool WantFile) const {
+std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC,
+ bool WantFile) const {
const ToolChain::path_list &List = TC.getProgramPaths();
- for (ToolChain::path_list::const_iterator
+ for (ToolChain::path_list::const_iterator
it = List.begin(), ie = List.end(); it != ie; ++it) {
llvm::sys::Path P(*it);
P.appendComponent(Name);
if (WantFile ? P.exists() : P.canExecute())
- return P;
+ return P.str();
}
// If all else failed, search the path.
llvm::sys::Path P(llvm::sys::Program::FindProgramByName(Name));
if (!P.empty())
- return P;
+ return P.str();
- return llvm::sys::Path(Name);
+ return Name;
}
std::string Driver::GetTemporaryPath(const char *Suffix) const {
- // FIXME: This is lame; sys::Path should provide this function (in
- // particular, it should know how to find the temporary files dir).
+ // FIXME: This is lame; sys::Path should provide this function (in particular,
+ // it should know how to find the temporary files dir).
std::string Error;
const char *TmpDir = ::getenv("TMPDIR");
if (!TmpDir)
@@ -1222,33 +1231,20 @@ std::string Driver::GetTemporaryPath(const char *Suffix) const {
return "";
}
- // FIXME: Grumble, makeUnique sometimes leaves the file around!?
- // PR3837.
+ // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837.
P.eraseFromDisk(false, 0);
P.appendSuffix(Suffix);
- return P.toString();
+ return P.str();
}
const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
llvm::PrettyStackTraceString CrashInfo("Constructing host");
llvm::Triple Triple(TripleStr);
- // Normalize Arch a bit.
- //
- // FIXME: We shouldn't need to do this once everything goes through the triple
- // interface.
- if (Triple.getArchName() == "i686")
- Triple.setArchName("i386");
- else if (Triple.getArchName() == "amd64")
- Triple.setArchName("x86_64");
- else if (Triple.getArchName() == "ppc" ||
- Triple.getArchName() == "Power Macintosh")
- Triple.setArchName("powerpc");
- else if (Triple.getArchName() == "ppc64")
- Triple.setArchName("powerpc64");
-
switch (Triple.getOS()) {
+ case llvm::Triple::AuroraUX:
+ return createAuroraUXHostInfo(*this, Triple);
case llvm::Triple::Darwin:
return createDarwinHostInfo(*this, Triple);
case llvm::Triple::DragonFly:
@@ -1265,17 +1261,10 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
}
bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
- const std::string &ArchNameStr) const {
- // FIXME: Remove this hack.
- const char *ArchName = ArchNameStr.c_str();
- if (ArchNameStr == "powerpc")
- ArchName = "ppc";
- else if (ArchNameStr == "powerpc64")
- ArchName = "ppc64";
-
- // Check if user requested no clang, or clang doesn't understand
- // this type (we only handle single inputs for now).
- if (!CCCUseClang || JA.size() != 1 ||
+ const llvm::Triple &Triple) const {
+ // Check if user requested no clang, or clang doesn't understand this type (we
+ // only handle single inputs for now).
+ if (!CCCUseClang || JA.size() != 1 ||
!types::isAcceptedByClang((*JA.begin())->getType()))
return false;
@@ -1294,35 +1283,32 @@ bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA,
return false;
}
- // Always use clang for precompiling, regardless of archs. PTH is
- // platform independent, and this allows the use of the static
- // analyzer on platforms we don't have full IRgen support for.
- if (isa<PrecompileJobAction>(JA))
+ // Always use clang for precompiling and AST generation, regardless of archs.
+ if (isa<PrecompileJobAction>(JA) || JA.getType() == types::TY_AST)
return true;
- // Finally, don't use clang if this isn't one of the user specified
- // archs to build.
- if (!CCCClangArchs.empty() && !CCCClangArchs.count(ArchName)) {
- Diag(clang::diag::warn_drv_not_using_clang_arch) << ArchName;
+ // Finally, don't use clang if this isn't one of the user specified archs to
+ // build.
+ if (!CCCClangArchs.empty() && !CCCClangArchs.count(Triple.getArch())) {
+ Diag(clang::diag::warn_drv_not_using_clang_arch) << Triple.getArchName();
return false;
}
return true;
}
-/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
-/// return the grouped values as integers. Numbers which are not
-/// provided are set to 0.
+/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
+/// grouped values as integers. Numbers which are not provided are set to 0.
///
-/// \return True if the entire string was parsed (9.2), or all groups
-/// were parsed (10.3.5extrastuff).
-bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
+/// \return True if the entire string was parsed (9.2), or all groups were
+/// parsed (10.3.5extrastuff).
+bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
unsigned &Minor, unsigned &Micro,
bool &HadExtra) {
HadExtra = false;
Major = Minor = Micro = 0;
- if (*Str == '\0')
+ if (*Str == '\0')
return true;
char *End;
@@ -1331,7 +1317,7 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
return true;
if (*End != '.')
return false;
-
+
Str = End+1;
Minor = (unsigned) strtol(Str, &End, 10);
if (*Str != '\0' && *End == '\0')
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 602a97713505..08c4ef490017 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -22,13 +22,11 @@
#include "ToolChains.h"
#include <cassert>
-
+
using namespace clang::driver;
HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple)
- : TheDriver(D), Triple(_Triple)
-{
-
+ : TheDriver(D), Triple(_Triple) {
}
HostInfo::~HostInfo() {
@@ -47,7 +45,7 @@ class DarwinHostInfo : public HostInfo {
unsigned GCCVersion[3];
/// Cache of tool chains we have created.
- mutable llvm::StringMap<ToolChain *> ToolChains;
+ mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains;
public:
DarwinHostInfo(const Driver &D, const llvm::Triple &Triple);
@@ -66,28 +64,22 @@ public:
return Ty;
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
: HostInfo(D, Triple) {
-
- assert((getArchName() == "i386" || getArchName() == "x86_64" ||
- getArchName() == "powerpc" || getArchName() == "powerpc64" ||
- getArchName() == "arm") &&
- "Unknown Darwin arch.");
+ assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!");
assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
"Unknown Darwin platform.");
bool HadExtra;
- if (!Driver::GetReleaseVersion(&getOSName()[6],
- DarwinVersion[0], DarwinVersion[1],
- DarwinVersion[2], HadExtra)) {
- D.Diag(clang::diag::err_drv_invalid_darwin_version)
- << getOSName();
- }
-
+ if (!Driver::GetReleaseVersion(&getOSName()[6],
+ DarwinVersion[0], DarwinVersion[1],
+ DarwinVersion[2], HadExtra))
+ D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName();
+
// We can only call 4.2.1 for now.
GCCVersion[0] = 4;
GCCVersion[1] = 2;
@@ -95,73 +87,71 @@ DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
}
DarwinHostInfo::~DarwinHostInfo() {
- for (llvm::StringMap<ToolChain*>::iterator
+ for (llvm::DenseMap<unsigned, ToolChain*>::iterator
it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
delete it->second;
}
-bool DarwinHostInfo::useDriverDriver() const {
+bool DarwinHostInfo::useDriverDriver() const {
return true;
}
-ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
- std::string Arch;
+ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ llvm::Triple::ArchType Arch;
+
if (!ArchName) {
// If we aren't looking for a specific arch, infer the default architecture
// based on -arch and -m32/-m64 command line options.
if (Arg *A = Args.getLastArg(options::OPT_arch)) {
// The gcc driver behavior with multiple -arch flags wasn't consistent for
// things which rely on a default architecture. We just use the last -arch
- // to find the default tool chain.
- Arch = A->getValue(Args);
-
- // Normalize arch name; we shouldn't be doing this here.
- //
- // FIXME: This should be unnecessary once everything moves over to using
- // the ID based Triple interface.
- if (Arch == "ppc")
- Arch = "powerpc";
- else if (Arch == "ppc64")
- Arch = "powerpc64";
+ // to find the default tool chain (assuming it is valid..
+ Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args));
+
+ // If it was invalid just use the host, we will reject this command line
+ // later.
+ if (Arch == llvm::Triple::UnknownArch)
+ Arch = getTriple().getArch();
} else {
// Otherwise default to the arch of the host.
- Arch = getArchName();
+ Arch = getTriple().getArch();
}
- ArchName = Arch.c_str();
-
+
// Honor -m32 and -m64 when finding the default tool chain.
+ //
+ // FIXME: Should this information be in llvm::Triple?
if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
- if (Arch == "i386" || Arch == "x86_64") {
- ArchName = (A->getOption().getId() == options::OPT_m32) ? "i386" :
- "x86_64";
- } else if (Arch == "powerpc" || Arch == "powerpc64") {
- ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" :
- "powerpc64";
+ if (A->getOption().getId() == options::OPT_m32) {
+ if (Arch == llvm::Triple::x86_64)
+ Arch = llvm::Triple::x86;
+ if (Arch == llvm::Triple::ppc64)
+ Arch = llvm::Triple::ppc;
+ } else {
+ if (Arch == llvm::Triple::x86)
+ Arch = llvm::Triple::x86_64;
+ if (Arch == llvm::Triple::ppc)
+ Arch = llvm::Triple::ppc64;
}
- }
- } else {
- // Normalize arch name; we shouldn't be doing this here.
- //
- // FIXME: This should be unnecessary once everything moves over to using the
- // ID based Triple interface.
- if (strcmp(ArchName, "ppc") == 0)
- ArchName = "powerpc";
- else if (strcmp(ArchName, "ppc64") == 0)
- ArchName = "powerpc64";
- }
+ }
+ } else
+ Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName);
- ToolChain *&TC = ToolChains[ArchName];
+ assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!");
+ ToolChain *&TC = ToolChains[Arch];
if (!TC) {
llvm::Triple TCTriple(getTriple());
- TCTriple.setArchName(ArchName);
-
- if (strcmp(ArchName, "i386") == 0 || strcmp(ArchName, "x86_64") == 0)
- TC = new toolchains::Darwin_X86(*this, TCTriple,
- DarwinVersion,
- GCCVersion);
+ TCTriple.setArch(Arch);
+
+ // If we recognized the arch, match it to the toolchains we support.
+ if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ // We still use the legacy DarwinGCC toolchain on X86.
+ TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion, GCCVersion,
+ false);
+ } else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
+ TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion, true);
else
- TC = new toolchains::Darwin_GCC(*this, TCTriple);
+ TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
}
return TC;
@@ -185,11 +175,11 @@ public:
return types::lookupTypeForExtension(Ext);
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
-UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple)
+UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple)
: HostInfo(D, Triple) {
}
@@ -199,15 +189,15 @@ UnknownHostInfo::~UnknownHostInfo() {
delete it->second;
}
-bool UnknownHostInfo::useDriverDriver() const {
+bool UnknownHostInfo::useDriverDriver() const {
return false;
}
-ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
- assert(!ArchName &&
+ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
-
+
// Automatically handle some instances of -m32/-m64 we know about.
std::string Arch = getArchName();
ArchName = Arch.c_str();
@@ -221,8 +211,8 @@ ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args,
ArchName =
(A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
}
- }
-
+ }
+
ToolChain *&TC = ToolChains[ArchName];
if (!TC) {
llvm::Triple TCTriple(getTriple());
@@ -242,7 +232,7 @@ class OpenBSDHostInfo : public HostInfo {
mutable llvm::StringMap<ToolChain*> ToolChains;
public:
- OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+ OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
: HostInfo(D, Triple) {}
~OpenBSDHostInfo();
@@ -252,8 +242,8 @@ public:
return types::lookupTypeForExtension(Ext);
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
OpenBSDHostInfo::~OpenBSDHostInfo() {
@@ -262,18 +252,18 @@ OpenBSDHostInfo::~OpenBSDHostInfo() {
delete it->second;
}
-bool OpenBSDHostInfo::useDriverDriver() const {
+bool OpenBSDHostInfo::useDriverDriver() const {
return false;
}
-ToolChain *OpenBSDHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
- assert(!ArchName &&
+ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
-
+
std::string Arch = getArchName();
ArchName = Arch.c_str();
-
+
ToolChain *&TC = ToolChains[ArchName];
if (!TC) {
llvm::Triple TCTriple(getTriple());
@@ -285,6 +275,55 @@ ToolChain *OpenBSDHostInfo::getToolChain(const ArgList &Args,
return TC;
}
+// AuroraUX Host Info
+
+/// AuroraUXHostInfo - AuroraUX host information implementation.
+class AuroraUXHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {}
+ ~AuroraUXHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual types::ID lookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+ }
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+AuroraUXHostInfo::~AuroraUXHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool AuroraUXHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ ToolChain *&TC = ToolChains[getArchName()];
+
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(getArchName());
+
+ TC = new toolchains::AuroraUX(*this, TCTriple);
+ }
+
+ return TC;
+}
+
// FreeBSD Host Info
/// FreeBSDHostInfo - FreeBSD host information implementation.
@@ -293,7 +332,7 @@ class FreeBSDHostInfo : public HostInfo {
mutable llvm::StringMap<ToolChain*> ToolChains;
public:
- FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
+ FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple)
: HostInfo(D, Triple) {}
~FreeBSDHostInfo();
@@ -303,8 +342,8 @@ public:
return types::lookupTypeForExtension(Ext);
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
FreeBSDHostInfo::~FreeBSDHostInfo() {
@@ -313,17 +352,17 @@ FreeBSDHostInfo::~FreeBSDHostInfo() {
delete it->second;
}
-bool FreeBSDHostInfo::useDriverDriver() const {
+bool FreeBSDHostInfo::useDriverDriver() const {
return false;
}
-ToolChain *FreeBSDHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
+ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
bool Lib32 = false;
- assert(!ArchName &&
+ assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
-
+
// On x86_64 we need to be able to compile 32-bits binaries as well.
// Compiling 64-bit binaries on i386 is not supported. We don't have a
// lib64.
@@ -332,8 +371,8 @@ ToolChain *FreeBSDHostInfo::getToolChain(const ArgList &Args,
if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
ArchName = "i386";
Lib32 = true;
- }
-
+ }
+
ToolChain *&TC = ToolChains[ArchName];
if (!TC) {
llvm::Triple TCTriple(getTriple());
@@ -363,8 +402,8 @@ public:
return types::lookupTypeForExtension(Ext);
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
DragonFlyHostInfo::~DragonFlyHostInfo() {
@@ -373,13 +412,13 @@ DragonFlyHostInfo::~DragonFlyHostInfo() {
delete it->second;
}
-bool DragonFlyHostInfo::useDriverDriver() const {
+bool DragonFlyHostInfo::useDriverDriver() const {
return false;
}
-ToolChain *DragonFlyHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
- assert(!ArchName &&
+ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
ToolChain *&TC = ToolChains[getArchName()];
@@ -412,8 +451,8 @@ public:
return types::lookupTypeForExtension(Ext);
}
- virtual ToolChain *getToolChain(const ArgList &Args,
- const char *ArchName) const;
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
};
LinuxHostInfo::~LinuxHostInfo() {
@@ -422,14 +461,14 @@ LinuxHostInfo::~LinuxHostInfo() {
delete it->second;
}
-bool LinuxHostInfo::useDriverDriver() const {
+bool LinuxHostInfo::useDriverDriver() const {
return false;
}
-ToolChain *LinuxHostInfo::getToolChain(const ArgList &Args,
- const char *ArchName) const {
+ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
- assert(!ArchName &&
+ assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
// Automatically handle some instances of -m32/-m64 we know about.
@@ -462,19 +501,25 @@ ToolChain *LinuxHostInfo::getToolChain(const ArgList &Args,
}
const HostInfo *
+clang::driver::createAuroraUXHostInfo(const Driver &D,
+ const llvm::Triple& Triple){
+ return new AuroraUXHostInfo(D, Triple);
+}
+
+const HostInfo *
clang::driver::createDarwinHostInfo(const Driver &D,
const llvm::Triple& Triple){
return new DarwinHostInfo(D, Triple);
}
const HostInfo *
-clang::driver::createOpenBSDHostInfo(const Driver &D,
+clang::driver::createOpenBSDHostInfo(const Driver &D,
const llvm::Triple& Triple) {
return new OpenBSDHostInfo(D, Triple);
}
const HostInfo *
-clang::driver::createFreeBSDHostInfo(const Driver &D,
+clang::driver::createFreeBSDHostInfo(const Driver &D,
const llvm::Triple& Triple) {
return new FreeBSDHostInfo(D, Triple);
}
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 1b0ea18453d0..280e7c4a5a09 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -14,9 +14,9 @@ using namespace clang::driver;
Job::~Job() {}
-Command::Command(const Action &_Source, const char *_Executable,
+Command::Command(const Action &_Source, const char *_Executable,
const ArgStringList &_Arguments)
- : Job(CommandClass), Source(_Source), Executable(_Executable),
+ : Job(CommandClass), Source(_Source), Executable(_Executable),
Arguments(_Arguments) {
}
@@ -30,4 +30,4 @@ void Job::addCommand(Command *C) {
else
cast<JobList>(this)->addJob(C);
}
-
+
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
index d163f0fe9efc..4c3ca5ca8446 100644
--- a/lib/Driver/Makefile
+++ b/lib/Driver/Makefile
@@ -12,17 +12,9 @@ LIBRARYNAME := clangDriver
BUILD_ARCHIVE = 1
CXXFLAGS = -fno-rtti
+CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+ifdef CLANG_VENDOR
+CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "'
+endif
include $(LEVEL)/Makefile.common
-
-SVN_REVISION := $(shell cd $(PROJ_SRC_DIR)/../.. && svnversion)
-
-CPP.Defines += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include \
- -DSVN_REVISION='"$(SVN_REVISION)"'
-
-$(ObjDir)/.ver-svn .ver: $(ObjDir)/.dir
- @if [ '$(SVN_REVISION)' != '$(shell cat $(ObjDir)/.ver-svn 2>/dev/null)' ]; then\
- echo '$(SVN_REVISION)' > $(ObjDir)/.ver-svn; \
- fi
-$(ObjDir)/.ver-svn: .ver
-$(ObjDir)/Driver.o: $(ObjDir)/.ver-svn
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index 7ea6a8b0d9f4..affd1c5aa9e5 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -77,7 +77,7 @@ static Info OptionInfos[] = {
{ "<input>", "d", 0, 0, Option::InputClass, OPT_INVALID, OPT_INVALID, 0 },
// The UnknownOption info
{ "<unknown>", "", 0, 0, Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 },
-
+
#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
HELPTEXT, METAVAR) \
{ NAME, FLAGS, HELPTEXT, METAVAR, \
@@ -91,7 +91,11 @@ static Info &getInfo(unsigned id) {
return OptionInfos[id - 1];
}
-OptTable::OptTable() : Options(new Option*[numOptions]()) {
+OptTable::OptTable() : Options(new Option*[numOptions]) {
+ // Explicitly zero initialize the error to work around a bug in array
+ // value-initialization on MinGW with gcc 4.3.5.
+ memset(Options, 0, sizeof(*Options) * numOptions);
+
// Find start of normal options.
FirstSearchableOption = 0;
for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) {
@@ -120,10 +124,10 @@ OptTable::OptTable() : Options(new Option*[numOptions]()) {
assert(0 && "Options are not in order!");
}
}
-#endif
+#endif
}
-OptTable::~OptTable() {
+OptTable::~OptTable() {
for (unsigned i = 0; i < numOptions; ++i)
delete Options[i];
delete[] Options;
@@ -164,7 +168,7 @@ const Option *OptTable::getOption(options::ID id) const {
Option *OptTable::constructOption(options::ID id) const {
Info &info = getInfo(id);
- const OptionGroup *Group =
+ const OptionGroup *Group =
cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
const Option *Alias = getOption((options::ID) info.AliasID);
@@ -195,10 +199,10 @@ Option *OptTable::constructOption(options::ID id) const {
for (const char *s = info.Flags; *s; ++s) {
switch (*s) {
default: assert(0 && "Invalid option flag.");
- case 'J':
+ case 'J':
assert(info.Kind == Option::SeparateClass && "Invalid option.");
Opt->setForceJoinedRender(true); break;
- case 'S':
+ case 'S':
assert(info.Kind == Option::JoinedClass && "Invalid option.");
Opt->setForceSeparateRender(true); break;
case 'd': Opt->setDriverOption(true); break;
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
index cad2bbf2b75e..c2ace05aa4d1 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -17,18 +17,17 @@
using namespace clang::driver;
Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name,
- const OptionGroup *_Group, const Option *_Alias)
+ const OptionGroup *_Group, const Option *_Alias)
: Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias),
Unsupported(false), LinkerInput(false), NoOptAsInput(false),
ForceSeparateRender(false), ForceJoinedRender(false),
- DriverOption(false), NoArgumentUnused(false)
-{
+ DriverOption(false), NoArgumentUnused(false) {
// Multi-level aliases are not supported, and alias options cannot
// have groups. This just simplifies option tracking, it is not an
// inherent limitation.
assert((!Alias || (!Alias->Alias && !Group)) &&
- "Multi-level aliases and aliases with groups are unsupported.");
+ "Multi-level aliases and aliases with groups are unsupported.");
}
Option::~Option() {
@@ -59,12 +58,12 @@ void Option::dump() const {
llvm::errs() << " Group:";
Group->dump();
}
-
+
if (Alias) {
llvm::errs() << " Alias:";
Alias->dump();
}
-
+
if (const MultiArgOption *MOA = dyn_cast<MultiArgOption>(this))
llvm::errs() << " NumArgs:" << MOA->getNumArgs();
@@ -77,10 +76,10 @@ bool Option::matches(const Option *Opt) const {
return matches(Opt->getAlias());
if (Alias)
return Alias->matches(Opt);
-
+
if (this == Opt)
return true;
-
+
if (Group)
return Group->matches(Opt);
return false;
@@ -93,16 +92,16 @@ bool Option::matches(options::ID Id) const {
// the option table).
if (Alias)
return Alias->matches(Id);
-
+
if (ID == Id)
return true;
-
+
if (Group)
return Group->matches(Id);
return false;
}
-OptionGroup::OptionGroup(options::ID ID, const char *Name,
+OptionGroup::OptionGroup(options::ID ID, const char *Name,
const OptionGroup *Group)
: Option(Option::GroupClass, ID, Name, Group, 0) {
}
@@ -130,13 +129,13 @@ Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
return 0;
}
-FlagOption::FlagOption(options::ID ID, const char *Name,
+FlagOption::FlagOption(options::ID ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::FlagClass, ID, Name, Group, Alias) {
}
Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
- // Matches iff this is an exact match.
+ // Matches iff this is an exact match.
// FIXME: Avoid strlen.
if (strlen(getName()) != strlen(Args.getArgString(Index)))
return 0;
@@ -144,7 +143,7 @@ Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
return new FlagArg(this, Index++);
}
-JoinedOption::JoinedOption(options::ID ID, const char *Name,
+JoinedOption::JoinedOption(options::ID ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::JoinedClass, ID, Name, Group, Alias) {
}
@@ -154,30 +153,30 @@ Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
return new JoinedArg(this, Index++);
}
-CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name,
- const OptionGroup *Group,
+CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name,
+ const OptionGroup *Group,
const Option *Alias)
: Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
}
-Arg *CommaJoinedOption::accept(const InputArgList &Args,
+Arg *CommaJoinedOption::accept(const InputArgList &Args,
unsigned &Index) const {
// Always matches. We count the commas now so we can answer
// getNumValues easily.
-
+
// Get the suffix string.
// FIXME: Avoid strlen, and move to helper method?
const char *Suffix = Args.getArgString(Index) + strlen(getName());
return new CommaJoinedArg(this, Index++, Suffix);
}
-SeparateOption::SeparateOption(options::ID ID, const char *Name,
+SeparateOption::SeparateOption(options::ID ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::SeparateClass, ID, Name, Group, Alias) {
}
Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
- // Matches iff this is an exact match.
+ // Matches iff this is an exact match.
// FIXME: Avoid strlen.
if (strlen(getName()) != strlen(Args.getArgString(Index)))
return 0;
@@ -189,15 +188,15 @@ Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
return new SeparateArg(this, Index - 2, 1);
}
-MultiArgOption::MultiArgOption(options::ID ID, const char *Name,
- const OptionGroup *Group, const Option *Alias,
+MultiArgOption::MultiArgOption(options::ID ID, const char *Name,
+ const OptionGroup *Group, const Option *Alias,
unsigned _NumArgs)
: Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
assert(NumArgs > 1 && "Invalid MultiArgOption!");
}
Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
- // Matches iff this is an exact match.
+ // Matches iff this is an exact match.
// FIXME: Avoid strlen.
if (strlen(getName()) != strlen(Args.getArgString(Index)))
return 0;
@@ -210,12 +209,12 @@ Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
}
JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name,
- const OptionGroup *Group,
+ const OptionGroup *Group,
const Option *Alias)
: Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
}
-Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
+Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
unsigned &Index) const {
// If this is not an exact match, it is a joined arg.
// FIXME: Avoid strlen.
@@ -227,17 +226,17 @@ Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
if (Index > Args.getNumInputArgStrings())
return 0;
- return new SeparateArg(this, Index - 2, 1);
+ return new SeparateArg(this, Index - 2, 1);
}
JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID,
- const char *Name,
- const OptionGroup *Group,
+ const char *Name,
+ const OptionGroup *Group,
const Option *Alias)
: Option(Option::JoinedAndSeparateClass, ID, Name, Group, Alias) {
}
-Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
+Arg *JoinedAndSeparateOption::accept(const InputArgList &Args,
unsigned &Index) const {
// Always matches.
diff --git a/lib/Driver/Tool.cpp b/lib/Driver/Tool.cpp
index 6f6589ab1327..781e0a702060 100644
--- a/lib/Driver/Tool.cpp
+++ b/lib/Driver/Tool.cpp
@@ -11,7 +11,7 @@
using namespace clang::driver;
-Tool::Tool(const char *_Name, const ToolChain &TC) : Name(_Name),
+Tool::Tool(const char *_Name, const ToolChain &TC) : Name(_Name),
TheToolChain(TC) {
}
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 20ed31bd6e02..abe9c8178a63 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -22,14 +22,14 @@ ToolChain::ToolChain(const HostInfo &_Host, const llvm::Triple &_Triple)
ToolChain::~ToolChain() {
}
-llvm::sys::Path ToolChain::GetFilePath(const Compilation &C,
- const char *Name) const {
+std::string ToolChain::GetFilePath(const Compilation &C,
+ const char *Name) const {
return Host.getDriver().GetFilePath(Name, *this);
-
+
}
-llvm::sys::Path ToolChain::GetProgramPath(const Compilation &C,
- const char *Name,
- bool WantFile) const {
+std::string ToolChain::GetProgramPath(const Compilation &C,
+ const char *Name,
+ bool WantFile) const {
return Host.getDriver().GetProgramPath(Name, *this, WantFile);
}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index f663ed49536e..a5a48adcf028 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/Option.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
@@ -25,21 +26,34 @@
using namespace clang::driver;
using namespace clang::driver::toolchains;
-/// Darwin_X86 - Darwin tool chain for i386 and x86_64.
+/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin_X86::Darwin_X86(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&_DarwinVersion)[3],
- const unsigned (&_GCCVersion)[3])
- : ToolChain(Host, Triple) {
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&_DarwinVersion)[3], bool _IsIPhoneOS)
+ : ToolChain(Host, Triple),
+ IsIPhoneOS(_IsIPhoneOS)
+{
DarwinVersion[0] = _DarwinVersion[0];
DarwinVersion[1] = _DarwinVersion[1];
DarwinVersion[2] = _DarwinVersion[2];
+
+ llvm::raw_string_ostream(MacosxVersionMin)
+ << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1];
+
+ // FIXME: Lift default up.
+ IPhoneOSVersionMin = "3.0";
+}
+
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&DarwinVersion)[3],
+ const unsigned (&_GCCVersion)[3], bool IsIPhoneOS)
+ : Darwin(Host, Triple, DarwinVersion, IsIPhoneOS)
+{
GCCVersion[0] = _GCCVersion[0];
GCCVersion[1] = _GCCVersion[1];
GCCVersion[2] = _GCCVersion[2];
- llvm::raw_string_ostream(MacosxVersionMin)
- << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1];
+ // Set up the tool chain paths to match gcc.
ToolChainDir = "i686-apple-darwin";
ToolChainDir += llvm::utostr(DarwinVersion[0]);
@@ -54,32 +68,32 @@ Darwin_X86::Darwin_X86(const HostInfo &Host, const llvm::Triple& Triple,
if (getArchName() == "x86_64") {
Path = getHost().getDriver().Dir;
Path += "/../lib/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
Path += "/x86_64";
getFilePaths().push_back(Path);
Path = "/usr/lib/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
Path += "/x86_64";
getFilePaths().push_back(Path);
}
-
+
Path = getHost().getDriver().Dir;
Path += "/../lib/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
getFilePaths().push_back(Path);
Path = "/usr/lib/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
getFilePaths().push_back(Path);
Path = getHost().getDriver().Dir;
Path += "/../libexec/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
getProgramPaths().push_back(Path);
Path = "/usr/libexec/gcc/";
- Path += getToolChainDir();
+ Path += ToolChainDir;
getProgramPaths().push_back(Path);
Path = getHost().getDriver().Dir;
@@ -89,17 +103,16 @@ Darwin_X86::Darwin_X86(const HostInfo &Host, const llvm::Triple& Triple,
getProgramPaths().push_back(getHost().getDriver().Dir);
}
-Darwin_X86::~Darwin_X86() {
+Darwin::~Darwin() {
// Free tool implementations.
for (llvm::DenseMap<unsigned, Tool*>::iterator
it = Tools.begin(), ie = Tools.end(); it != ie; ++it)
delete it->second;
}
-Tool &Darwin_X86::SelectTool(const Compilation &C,
- const JobAction &JA) const {
+Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
- if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
+ if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
Key = Action::AnalyzeJobClass;
else
Key = JA.getKind();
@@ -120,7 +133,7 @@ Tool &Darwin_X86::SelectTool(const Compilation &C,
case Action::AssembleJobClass:
T = new tools::darwin::Assemble(*this); break;
case Action::LinkJobClass:
- T = new tools::darwin::Link(*this, MacosxVersionMin.c_str()); break;
+ T = new tools::darwin::Link(*this); break;
case Action::LipoJobClass:
T = new tools::darwin::Lipo(*this); break;
}
@@ -129,7 +142,136 @@ Tool &Darwin_X86::SelectTool(const Compilation &C,
return *T;
}
-DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
+void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // FIXME: Derive these correctly.
+ if (getArchName() == "x86_64") {
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/x86_64"));
+ // Intentionally duplicated for (temporary) gcc bug compatibility.
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/x86_64"));
+ }
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+ // Intentionally duplicated for (temporary) gcc bug compatibility.
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/../../../" + ToolChainDir));
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
+ "/../../.."));
+}
+
+void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ unsigned MacosxVersionMin[3];
+ getMacosxVersionMin(Args, MacosxVersionMin);
+
+ // Derived from libgcc and lib specs but refactored.
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_static");
+ } else {
+ if (Args.hasArg(options::OPT_static_libgcc)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
+ // Derived from darwin_iphoneos_libgcc spec.
+ if (isIPhoneOS()) {
+ CmdArgs.push_back("-lgcc_s.1");
+ } else {
+ CmdArgs.push_back("-lgcc_s.10.5");
+ }
+ } else if (Args.hasArg(options::OPT_shared_libgcc) ||
+ // FIXME: -fexceptions -fno-exceptions means no exceptions
+ Args.hasArg(options::OPT_fexceptions) ||
+ Args.hasArg(options::OPT_fgnu_runtime)) {
+ // FIXME: This is probably broken on 10.3?
+ if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(MacosxVersionMin, 10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+ } else {
+ if (isMacosxVersionLT(MacosxVersionMin, 10, 3, 9))
+ ; // Do nothing.
+ else if (isMacosxVersionLT(MacosxVersionMin, 10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(MacosxVersionMin, 10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+ }
+
+ if (isIPhoneOS() || isMacosxVersionLT(MacosxVersionMin, 10, 6)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lSystem");
+ } else {
+ CmdArgs.push_back("-lSystem");
+ CmdArgs.push_back("-lgcc");
+ }
+ }
+}
+
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&DarwinVersion)[3],
+ bool IsIPhoneOS)
+ : Darwin(Host, Triple, DarwinVersion, IsIPhoneOS)
+{
+ // Add the relative libexec dir (for clang-cc).
+ //
+ // FIXME: We should sink clang-cc into libexec/clang/<version>/.
+ std::string Path = getHost().getDriver().Dir;
+ Path += "/../libexec";
+ getProgramPaths().push_back(Path);
+
+ // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+ getProgramPaths().push_back(getHost().getDriver().Dir);
+}
+
+void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // The Clang toolchain uses explicit paths for internal libraries.
+}
+
+void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Check for static linking.
+ if (Args.hasArg(options::OPT_static)) {
+ // FIXME: We need to have compiler-rt available (perhaps as
+ // libclang_static.a) to link against.
+ return;
+ }
+
+ // Reject -static-libgcc for now, we can deal with this when and if someone
+ // cares. This is useful in situations where someone wants to statically link
+ // something like libstdc++, and needs its runtime support routines.
+ if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
+ getHost().getDriver().Diag(clang::diag::err_drv_unsupported_opt)
+ << A->getAsString(Args);
+ return;
+ }
+
+ // Otherwise link libSystem, which should have the support routines.
+ //
+ // FIXME: This is only true for 10.6 and beyond. Legacy support isn't
+ // critical, but it should work... we should just link in the static
+ // compiler-rt library.
+ CmdArgs.push_back("-lSystem");
+}
+
+void Darwin::getMacosxVersionMin(const ArgList &Args,
+ unsigned (&Res)[3]) const {
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ)) {
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Res[0], Res[1], Res[2],
+ HadExtra) ||
+ HadExtra) {
+ const Driver &D = getHost().getDriver();
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ }
+ } else
+ return getMacosxVersion(Res);
+}
+
+DerivedArgList *Darwin::TranslateArgs(InputArgList &Args,
+ const char *BoundArch) const {
DerivedArgList *DAL = new DerivedArgList(Args, false);
const OptTable &Opts = getHost().getDriver().getOpts();
@@ -138,30 +280,36 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
// more opaque. For now, we follow gcc closely solely for the
// purpose of easily achieving feature parity & testability. Once we
// have something that works, we should reevaluate each translation
- // and try to push it down into tool specific logic.
+ // and try to push it down into tool specific logic.
- Arg *OSXVersion =
+ Arg *OSXVersion =
Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false);
Arg *iPhoneVersion =
- Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false);
+ Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false);
if (OSXVersion && iPhoneVersion) {
getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
- << iPhoneVersion->getAsString(Args);
+ << iPhoneVersion->getAsString(Args);
} else if (!OSXVersion && !iPhoneVersion) {
// Chose the default version based on the arch.
//
- // FIXME: This will need to be fixed when we merge in arm support.
-
- // Look for MACOSX_DEPLOYMENT_TARGET, otherwise use the version
- // from the host.
- const char *Version = ::getenv("MACOSX_DEPLOYMENT_TARGET");
- if (!Version)
- Version = MacosxVersionMin.c_str();
- const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- DAL->append(DAL->MakeJoinedArg(0, O, Version));
+ // FIXME: Are there iPhone overrides for this?
+
+ if (!isIPhoneOS()) {
+ // Look for MACOSX_DEPLOYMENT_TARGET, otherwise use the version
+ // from the host.
+ const char *Version = ::getenv("MACOSX_DEPLOYMENT_TARGET");
+ if (!Version)
+ Version = MacosxVersionMin.c_str();
+ const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ DAL->append(DAL->MakeJoinedArg(0, O, Version));
+ } else {
+ const char *Version = IPhoneOSVersionMin.c_str();
+ const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+ DAL->append(DAL->MakeJoinedArg(0, O, Version));
+ }
}
-
+
for (ArgList::iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) {
Arg *A = *it;
@@ -174,7 +322,7 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
// interface for this.
unsigned Prev, Index = Prev = A->getIndex() + 1;
Arg *XarchArg = Opts.ParseOneArg(Args, Index);
-
+
// If the argument parsing failed or more than one argument was
// consumed, the -Xarch_ argument's parameter tried to consume
// extra arguments. Emit an error and ignore.
@@ -183,7 +331,7 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
// driver behavior; that isn't going to work in our model. We
// use isDriverOption() as an approximation, although things
// like -O4 are going to slip through.
- if (!XarchArg || Index > Prev + 1 ||
+ if (!XarchArg || Index > Prev + 1 ||
XarchArg->getOption().isDriverOption()) {
getHost().getDriver().Diag(clang::diag::err_drv_invalid_Xarch_argument)
<< A->getAsString(Args);
@@ -192,7 +340,7 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
XarchArg->setBaseArg(A);
A = XarchArg;
- }
+ }
// Sob. These is strictly gcc compatible for the time being. Apple
// gcc translates options twice, which means that self-expanding
@@ -209,7 +357,7 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
DAL->append(DAL->MakeFlagArg(A, Opts.getOption(options::OPT_static)));
break;
-
+
case options::OPT_dependency_file:
DAL->append(DAL->MakeSeparateArg(A, Opts.getOption(options::OPT_MF),
A->getValue(Args)));
@@ -270,35 +418,98 @@ DerivedArgList *Darwin_X86::TranslateArgs(InputArgList &Args) const {
}
}
- // FIXME: Actually, gcc always adds this, but it is filtered for
- // duplicates somewhere. This also changes the order of things, so
- // look it up.
- if (getArchName() == "x86_64")
- if (!Args.hasArg(options::OPT_m64, false))
+ if (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64)
+ if (!Args.hasArg(options::OPT_mtune_EQ, false))
+ DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ),
+ "core2"));
+
+ // Add the arch options based on the particular spelling of -arch, to match
+ // how the driver driver works.
+ if (BoundArch) {
+ llvm::StringRef Name = BoundArch;
+ const Option *MCpu = Opts.getOption(options::OPT_mcpu_EQ);
+ const Option *MArch = Opts.getOption(options::OPT_march_EQ);
+
+ // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
+ // which defines the list of which architectures we accept.
+ if (Name == "ppc")
+ ;
+ else if (Name == "ppc601")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "601"));
+ else if (Name == "ppc603")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "603"));
+ else if (Name == "ppc604")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "604"));
+ else if (Name == "ppc604e")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "604e"));
+ else if (Name == "ppc750")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "750"));
+ else if (Name == "ppc7400")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "7400"));
+ else if (Name == "ppc7450")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "7450"));
+ else if (Name == "ppc970")
+ DAL->append(DAL->MakeJoinedArg(0, MCpu, "970"));
+
+ else if (Name == "ppc64")
+ DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64)));
+
+ else if (Name == "i386")
+ ;
+ else if (Name == "i486")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "i486"));
+ else if (Name == "i586")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "i586"));
+ else if (Name == "i686")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "i686"));
+ else if (Name == "pentium")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium"));
+ else if (Name == "pentium2")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium2"));
+ else if (Name == "pentpro")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "pentiumpro"));
+ else if (Name == "pentIIm3")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "pentium2"));
+
+ else if (Name == "x86_64")
DAL->append(DAL->MakeFlagArg(0, Opts.getOption(options::OPT_m64)));
- if (!Args.hasArg(options::OPT_mtune_EQ, false))
- DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ),
- "core2"));
+ else if (Name == "arm")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "armv4t"));
+ else if (Name == "armv4t")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "armv4t"));
+ else if (Name == "armv5")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "armv5tej"));
+ else if (Name == "xscale")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "xscale"));
+ else if (Name == "armv6")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "armv6k"));
+ else if (Name == "armv7")
+ DAL->append(DAL->MakeJoinedArg(0, MArch, "armv7a"));
+
+ else
+ llvm::llvm_unreachable("invalid Darwin arch");
+ }
return DAL;
-}
+}
-bool Darwin_X86::IsMathErrnoDefault() const {
- return false;
+bool Darwin::IsMathErrnoDefault() const {
+ return false;
}
-bool Darwin_X86::IsUnwindTablesDefault() const {
+bool Darwin::IsUnwindTablesDefault() const {
// FIXME: Gross; we should probably have some separate target
// definition, possibly even reusing the one in clang.
return getArchName() == "x86_64";
}
-const char *Darwin_X86::GetDefaultRelocationModel() const {
+const char *Darwin::GetDefaultRelocationModel() const {
return "pic";
}
-const char *Darwin_X86::GetForcedPicModel() const {
+const char *Darwin::GetForcedPicModel() const {
if (getArchName() == "x86_64")
return "pic";
return 0;
@@ -309,13 +520,12 @@ const char *Darwin_X86::GetForcedPicModel() const {
/// command line options.
Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
- : ToolChain(Host, Triple)
-{
+ : ToolChain(Host, Triple) {
std::string Path(getHost().getDriver().Dir);
Path += "/../libexec";
getProgramPaths().push_back(Path);
- getProgramPaths().push_back(getHost().getDriver().Dir);
+ getProgramPaths().push_back(getHost().getDriver().Dir);
}
Generic_GCC::~Generic_GCC() {
@@ -325,10 +535,10 @@ Generic_GCC::~Generic_GCC() {
delete it->second;
}
-Tool &Generic_GCC::SelectTool(const Compilation &C,
+Tool &Generic_GCC::SelectTool(const Compilation &C,
const JobAction &JA) const {
Action::ActionClass Key;
- if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
+ if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
Key = Action::AnalyzeJobClass;
else
Key = JA.getKind();
@@ -351,7 +561,7 @@ Tool &Generic_GCC::SelectTool(const Compilation &C,
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:
@@ -362,8 +572,8 @@ Tool &Generic_GCC::SelectTool(const Compilation &C,
return *T;
}
-bool Generic_GCC::IsMathErrnoDefault() const {
- return true;
+bool Generic_GCC::IsMathErrnoDefault() const {
+ return true;
}
bool Generic_GCC::IsUnwindTablesDefault() const {
@@ -380,7 +590,8 @@ const char *Generic_GCC::GetForcedPicModel() const {
return 0;
}
-DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const {
+DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args,
+ const char *BoundArch) const {
return new DerivedArgList(Args, true);
}
@@ -394,7 +605,7 @@ OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple)
Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
- if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
+ if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
Key = Action::AnalyzeJobClass;
else
Key = JA.getKind();
@@ -429,7 +640,7 @@ FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
- if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
+ if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
Key = Action::AnalyzeJobClass;
else
Key = JA.getKind();
@@ -449,6 +660,48 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
return *T;
}
+/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
+
+AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_GCC(Host, Triple) {
+
+ // Path mangling to find libexec
+ std::string Path(getHost().getDriver().Dir);
+
+ Path += "/../libexec";
+ getProgramPaths().push_back(Path);
+ getProgramPaths().push_back(getHost().getDriver().Dir);
+
+ getFilePaths().push_back(getHost().getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back("/usr/sfw/lib");
+ getFilePaths().push_back("/opt/gcc4/lib");
+
+}
+
+Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getHost().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);
+ }
+ }
+
+ return *T;
+}
+
+
/// Linux toolchain (very bare-bones at the moment).
Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
@@ -456,6 +709,15 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
getFilePaths().push_back(getHost().getDriver().Dir + "/../lib/clang/1.0/");
getFilePaths().push_back("/lib/");
getFilePaths().push_back("/usr/lib/");
+
+ // Depending on the Linux distribution, any combination of lib{,32,64} is
+ // possible. E.g. Debian uses lib and lib32 for mixed i386/x86-64 systems,
+ // openSUSE uses lib and lib64 for the same purpose.
+ getFilePaths().push_back("/lib32/");
+ getFilePaths().push_back("/usr/lib32/");
+ getFilePaths().push_back("/lib64/");
+ getFilePaths().push_back("/usr/lib64/");
+
// FIXME: Figure out some way to get gcc's libdir
// (e.g. /usr/lib/gcc/i486-linux-gnu/4.3/ for Ubuntu 32-bit); we need
// crtbegin.o/crtend.o/etc., and want static versions of various
@@ -475,7 +737,7 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
Path += "/../libexec";
getProgramPaths().push_back(Path);
- getProgramPaths().push_back(getHost().getDriver().Dir);
+ getProgramPaths().push_back(getHost().getDriver().Dir);
getFilePaths().push_back(getHost().getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
@@ -484,7 +746,7 @@ DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
- if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName()))
+ if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
Key = Action::AnalyzeJobClass;
else
Key = JA.getKind();
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index c921d52864f0..6088d9617cf0 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -22,9 +22,9 @@ namespace clang {
namespace driver {
namespace toolchains {
- /// Generic_GCC - A tool chain using the 'gcc' command to perform
- /// all subcommands; this relies on gcc translating the majority of
- /// command line options.
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
class VISIBILITY_HIDDEN Generic_GCC : public ToolChain {
protected:
mutable llvm::DenseMap<unsigned, Tool*> Tools;
@@ -33,7 +33,8 @@ public:
Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple);
~Generic_GCC();
- virtual DerivedArgList *TranslateArgs(InputArgList &Args) const;
+ virtual DerivedArgList *TranslateArgs(InputArgList &Args,
+ const char *BoundArch) const;
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
@@ -43,30 +44,35 @@ public:
virtual const char *GetForcedPicModel() const;
};
- /// Darwin_X86 - Darwin tool chain for i386 an x86_64.
-class VISIBILITY_HIDDEN Darwin_X86 : public ToolChain {
+/// Darwin - The base Darwin tool chain.
+class VISIBILITY_HIDDEN Darwin : public ToolChain {
mutable llvm::DenseMap<unsigned, Tool*> Tools;
/// Darwin version of tool chain.
unsigned DarwinVersion[3];
- /// GCC version to use.
- unsigned GCCVersion[3];
-
- /// The directory suffix for this tool chain.
- std::string ToolChainDir;
+ /// Whether this is this an iPhoneOS toolchain.
+ //
+ // FIXME: This should go away, such differences should be completely
+ // determined by the target triple.
+ bool IsIPhoneOS;
/// The default macosx-version-min of this tool chain; empty until
/// initialized.
mutable std::string MacosxVersionMin;
+ /// The default iphoneos-version-min of this tool chain.
+ std::string IPhoneOSVersionMin;
+
const char *getMacosxVersionMin() const;
public:
- Darwin_X86(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3],
- const unsigned (&GCCVersion)[3]);
- ~Darwin_X86();
+ Darwin(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&DarwinVersion)[3], bool IsIPhoneOS);
+ ~Darwin();
+
+ /// @name Darwin Specific Toolchain API
+ /// {
void getDarwinVersion(unsigned (&Res)[3]) const {
Res[0] = DarwinVersion[0];
@@ -80,15 +86,53 @@ public:
Res[2] = DarwinVersion[1];
}
+ /// getMacosxVersionMin - Get the effective -mmacosx-version-min, which is
+ /// either the -mmacosx-version-min, or the current version if unspecified.
+ void getMacosxVersionMin(const ArgList &Args, unsigned (&Res)[3]) const;
+
+ static bool isMacosxVersionLT(unsigned (&A)[3], unsigned (&B)[3]) {
+ for (unsigned i=0; i < 3; ++i) {
+ if (A[i] > B[i]) return false;
+ if (A[i] < B[i]) return true;
+ }
+ return false;
+ }
+
+ static bool isMacosxVersionLT(unsigned (&A)[3],
+ unsigned V0, unsigned V1=0, unsigned V2=0) {
+ unsigned B[3] = { V0, V1, V2 };
+ return isMacosxVersionLT(A, B);
+ }
+
const char *getMacosxVersionStr() const {
return MacosxVersionMin.c_str();
}
- const std::string &getToolChainDir() const {
- return ToolChainDir;
+ const char *getIPhoneOSVersionStr() const {
+ return IPhoneOSVersionMin.c_str();
}
- virtual DerivedArgList *TranslateArgs(InputArgList &Args) const;
+ /// AddLinkSearchPathArgs - Add the linker search paths to \arg CmdArgs.
+ ///
+ /// \param Args - The input argument list.
+ /// \param CmdArgs [out] - The command argument list to append the paths
+ /// (prefixed by -L) to.
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const = 0;
+
+ /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler
+ /// runtime library.
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const = 0;
+
+ bool isIPhoneOS() const { return IsIPhoneOS; }
+
+ /// }
+ /// @name ToolChain Implementation
+ /// {
+
+ virtual DerivedArgList *TranslateArgs(InputArgList &Args,
+ const char *BoundArch) const;
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
@@ -96,17 +140,69 @@ public:
virtual bool IsUnwindTablesDefault() const;
virtual const char *GetDefaultRelocationModel() const;
virtual const char *GetForcedPicModel() const;
+
+ /// }
+};
+
+/// DarwinClang - The Darwin toolchain used by Clang.
+class VISIBILITY_HIDDEN DarwinClang : public Darwin {
+public:
+ DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&DarwinVersion)[3], bool IsIPhoneOS);
+
+ /// @name Darwin ToolChain Implementation
+ /// {
+
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// }
};
- /// Darwin_GCC - Generic Darwin tool chain using gcc.
-class VISIBILITY_HIDDEN Darwin_GCC : public Generic_GCC {
+/// DarwinGCC - The Darwin toolchain used by GCC.
+class VISIBILITY_HIDDEN DarwinGCC : public Darwin {
+ /// GCC version to use.
+ unsigned GCCVersion[3];
+
+ /// The directory suffix for this tool chain.
+ std::string ToolChainDir;
+
public:
- Darwin_GCC(const HostInfo &Host, const llvm::Triple& Triple)
+ DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
+ const unsigned (&DarwinVersion)[3], const unsigned (&GCCVersion)[3],
+ bool IsIPhoneOS);
+
+ /// @name Darwin ToolChain Implementation
+ /// {
+
+ virtual void AddLinkSearchPathArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const;
+
+ /// }
+};
+
+/// Darwin_Generic_GCC - Generic Darwin tool chain using gcc.
+class VISIBILITY_HIDDEN Darwin_Generic_GCC : public Generic_GCC {
+public:
+ Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {}
virtual const char *GetDefaultRelocationModel() const { return "pic"; }
};
+class VISIBILITY_HIDDEN AuroraUX : public Generic_GCC {
+public:
+ AuroraUX(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+};
+
class VISIBILITY_HIDDEN OpenBSD : public Generic_GCC {
public:
OpenBSD(const HostInfo &Host, const llvm::Triple& Triple);
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index d198a54cf7dd..fc91e4c43799 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -21,7 +21,8 @@
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -33,25 +34,42 @@ using namespace clang::driver::tools;
static const char *MakeFormattedString(const ArgList &Args,
const llvm::format_object_base &Fmt) {
- std::string Str;
- llvm::raw_string_ostream(Str) << Fmt;
- return Args.MakeArgString(Str.c_str());
+ llvm::SmallString<256> Str;
+ llvm::raw_svector_ostream(Str) << Fmt;
+ return Args.MakeArgString(Str.str());
}
-void Clang::AddPreprocessingOptions(const Driver &D,
+/// CheckPreprocessingOptions - Perform some validation of preprocessing
+/// arguments that is shared with gcc.
+static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC))
+ if (!Args.hasArg(options::OPT_E))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-E";
+}
+
+/// CheckCodeGenerationOptions - Perform some validation of code generation
+/// arguments that is shared with gcc.
+static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
+ // In gcc, only ARM checks this, but it seems reasonable to check universally.
+ if (Args.hasArg(options::OPT_static))
+ if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
+ options::OPT_mdynamic_no_pic))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-static";
+}
+
+void Clang::AddPreprocessingOptions(const Driver &D,
const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfo &Output,
const InputInfoList &Inputs) const {
Arg *A;
- if ((A = Args.getLastArg(options::OPT_C)) ||
- (A = Args.getLastArg(options::OPT_CC))) {
- if (!Args.hasArg(options::OPT_E))
- D.Diag(clang::diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "-E";
- A->render(Args, CmdArgs);
- }
+ CheckPreprocessingOptions(D, Args);
+
+ Args.AddLastArg(CmdArgs, options::OPT_C);
+ Args.AddLastArg(CmdArgs, options::OPT_CC);
// Handle dependency file generation.
if ((A = Args.getLastArg(options::OPT_M)) ||
@@ -77,6 +95,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
CmdArgs.push_back(DepFile);
// Add an -MT option if the user didn't specify their own.
+ //
// FIXME: This should use -MQ, when we support it.
if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
const char *DepTarget;
@@ -94,7 +113,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
P.eraseSuffix();
P.appendSuffix("o");
- DepTarget = Args.MakeArgString(P.getLast().c_str());
+ DepTarget = Args.MakeArgString(P.getLast());
}
CmdArgs.push_back("-MT");
@@ -109,13 +128,13 @@ void Clang::AddPreprocessingOptions(const Driver &D,
Args.AddLastArg(CmdArgs, options::OPT_MP);
Args.AddAllArgs(CmdArgs, options::OPT_MT);
- // FIXME: Use iterator.
-
// Add -i* options, and automatically translate to
// -include-pch/-include-pth for transparent PCH support. It's
// wonky, but we include looking for .gch so we can support seamless
// replacement into a build system already set up to be generating
// .gch files.
+ //
+ // FIXME: Use iterator.
for (ArgList::const_iterator
it = Args.begin(), ie = Args.end(); it != ie; ++it) {
const Arg *A = *it;
@@ -130,25 +149,25 @@ void Clang::AddPreprocessingOptions(const Driver &D,
P.appendSuffix("pch");
if (P.exists())
FoundPCH = true;
- else
+ else
P.eraseSuffix();
}
if (!FoundPCH) {
P.appendSuffix("pth");
- if (P.exists())
+ if (P.exists())
FoundPTH = true;
else
P.eraseSuffix();
- }
-
+ }
+
if (!FoundPCH && !FoundPTH) {
P.appendSuffix("gch");
if (P.exists()) {
FoundPCH = D.CCCUsePCH;
FoundPTH = !D.CCCUsePCH;
}
- else
+ else
P.eraseSuffix();
}
@@ -158,7 +177,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
CmdArgs.push_back("-include-pch");
else
CmdArgs.push_back("-include-pth");
- CmdArgs.push_back(Args.MakeArgString(P.c_str()));
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
continue;
}
}
@@ -181,6 +200,308 @@ void Clang::AddPreprocessingOptions(const Driver &D,
options::OPT_Xpreprocessor);
}
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static llvm::StringRef getARMTargetCPU(const ArgList &Args) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue(Args);
+
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ llvm::StringRef MArch = A->getValue(Args);
+
+ if (MArch == "armv2" || MArch == "armv2a")
+ return "arm2";
+ if (MArch == "armv3")
+ return "arm6";
+ if (MArch == "armv3m")
+ return "arm7m";
+ if (MArch == "armv4" || MArch == "armv4t")
+ return "arm7tdmi";
+ if (MArch == "armv5" || MArch == "armv5t")
+ return "arm10tdmi";
+ if (MArch == "armv5e" || MArch == "armv5te")
+ return "arm1026ejs";
+ if (MArch == "armv5tej")
+ return "arm926ejs";
+ if (MArch == "armv6" || MArch == "armv6k")
+ return "arm1136jf-s";
+ if (MArch == "armv6j")
+ return "arm1136j-s";
+ if (MArch == "armv6z" || MArch == "armv6zk")
+ return "arm1176jzf-s";
+ if (MArch == "armv6t2")
+ return "arm1156t2-s";
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ return "cortex-a8";
+ if (MArch == "armv7r" || MArch == "armv7-r")
+ return "cortex-r4";
+ if (MArch == "armv7m" || MArch == "armv7-m")
+ return "cortex-m3";
+ if (MArch == "ep9312")
+ return "ep9312";
+ if (MArch == "iwmmxt")
+ return "iwmmxt";
+ if (MArch == "xscale")
+ return "xscale";
+ }
+
+ // Otherwise return the most base CPU LLVM supports.
+ return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+ if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+ CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+ CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+ CPU == "arm940t" || CPU == "ep9312")
+ return "v4t";
+
+ if (CPU == "arm10tdmi" || CPU == "arm1020t")
+ return "v5";
+
+ if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+ CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+ CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+ CPU == "iwmmxt")
+ return "v5e";
+
+ if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+ CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+ return "v6";
+
+ if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+ return "v6t2";
+
+ if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ return "v7";
+
+ return "";
+}
+
+/// getLLVMTriple - Get the LLVM triple to use for a particular toolchain, which
+/// may depend on command line arguments.
+static std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
+ switch (TC.getTriple().getArch()) {
+ default:
+ return TC.getTripleString();
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ // FIXME: Factor into subclasses.
+ llvm::Triple Triple = TC.getTriple();
+
+ // Thumb2 is the default for V7 on Darwin.
+ //
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ llvm::StringRef Suffix = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
+ bool ThumbDefault =
+ (Suffix == "v7" && TC.getTriple().getOS() == llvm::Triple::Darwin);
+ std::string ArchName = "arm";
+ if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+ ArchName = "thumb";
+ Triple.setArchName(ArchName + Suffix.str());
+
+ return Triple.getTriple();
+ }
+ }
+}
+
+void Clang::AddARMTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getHost().getDriver();
+
+ // Select the ABI to use.
+ //
+ // FIXME: Support -meabi.
+ const char *ABIName = 0;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ ABIName = A->getValue(Args);
+ } else {
+ // Select the default based on the platform.
+ switch (getToolChain().getTriple().getOS()) {
+ // FIXME: Is this right for non-Darwin and non-Linux?
+ default:
+ ABIName = "aapcs";
+ break;
+
+ case llvm::Triple::Darwin:
+ ABIName = "apcs-gnu";
+ break;
+
+ case llvm::Triple::Linux:
+ ABIName = "aapcs-linux";
+ break;
+ }
+ }
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ // Set the CPU based on -march= and -mcpu=.
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=" + getARMTargetCPU(Args)));
+
+ // Select the float ABI as determined by -msoft-float, -mhard-float, and
+ // -mfloat-abi=.
+ llvm::StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ else {
+ FloatABI = A->getValue(Args);
+ if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
+ D.Diag(clang::diag::err_drv_invalid_mfloat_abi)
+ << A->getAsString(Args);
+ FloatABI = "soft";
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ // FIXME: This is wrong for non-Darwin, we don't have a mechanism yet for
+ // distinguishing things like linux-eabi vs linux-elf.
+ switch (getToolChain().getTriple().getOS()) {
+ case llvm::Triple::Darwin: {
+ // Darwin defaults to "softfp" for v6 and v7.
+ //
+ // FIXME: Factor out an ARM class so we can cache the arch somewhere.
+ llvm::StringRef ArchName = getLLVMArchSuffixForARM(getARMTargetCPU(Args));
+ if (ArchName.startswith("v6") || ArchName.startswith("v7"))
+ FloatABI = "softfp";
+ else
+ FloatABI = "soft";
+ break;
+ }
+
+ default:
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(clang::diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ break;
+ }
+ }
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-soft-float");
+ CmdArgs.push_back("-float-abi=soft");
+ } else if (FloatABI == "softfp") {
+ // Floating point operations are hard, but argument passing is soft.
+ CmdArgs.push_back("-float-abi=soft");
+ } else {
+ // Floating point operations and argument passing are hard.
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-float-abi=hard");
+ }
+}
+
+void Clang::AddX86TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // FIXME: This needs to change to use a clang-cc option, and set the attribute
+ // on functions.
+ if (!Args.hasFlag(options::OPT_mred_zone,
+ options::OPT_mno_red_zone,
+ true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("--disable-red-zone");
+
+ // FIXME: This needs to change to use a clang-cc option, and set the attribute
+ // on functions.
+ if (Args.hasFlag(options::OPT_msoft_float,
+ options::OPT_mno_soft_float,
+ false))
+ CmdArgs.push_back("--no-implicit-float");
+
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // FIXME: We may need some translation here from the options gcc takes to
+ // names the LLVM backend understand?
+ CmdArgs.push_back("-mcpu");
+ CmdArgs.push_back(A->getValue(Args));
+ } else {
+ // Select default CPU.
+
+ // FIXME: Need target hooks.
+ if (memcmp(getToolChain().getOS().c_str(), "darwin", 6) == 0) {
+ if (getToolChain().getArchName() == "x86_64")
+ CmdArgs.push_back("--mcpu=core2");
+ else if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--mcpu=yonah");
+ } else {
+ if (getToolChain().getArchName() == "x86_64")
+ CmdArgs.push_back("--mcpu=x86-64");
+ else if (getToolChain().getArchName() == "i386")
+ CmdArgs.push_back("--mcpu=pentium4");
+ }
+ }
+
+ // FIXME: Use iterator.
+ for (ArgList::const_iterator
+ it = Args.begin(), ie = Args.end(); it != ie; ++it) {
+ const Arg *A = *it;
+ if (A->getOption().matches(options::OPT_m_x86_Features_Group)) {
+ llvm::StringRef Name = A->getOption().getName();
+
+ // Skip over "-m".
+ assert(Name.startswith("-m") && "Invalid feature name.");
+ Name = Name.substr(2);
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+
+ A->claim();
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
+ }
+}
+
+static bool needsExceptions(const ArgList &Args, types::ID InputType,
+ const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
+ options::OPT_fno_exceptions)) {
+ if (A->getOption().matches(options::OPT_fexceptions))
+ return true;
+ else
+ return false;
+ }
+ switch (InputType) {
+ case types::TY_CXX: case types::TY_CXXHeader:
+ case types::TY_PP_CXX: case types::TY_PP_CXXHeader:
+ case types::TY_ObjCXX: case types::TY_ObjCXXHeader:
+ case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXXHeader:
+ return true;
+
+ case types::TY_ObjC: case types::TY_ObjCHeader:
+ case types::TY_PP_ObjC: case types::TY_PP_ObjCHeader:
+ if (Args.hasArg(options::OPT_fobjc_nonfragile_abi))
+ return true;
+ if (Triple.getOS() != llvm::Triple::Darwin)
+ return false;
+ return (Triple.getDarwinMajorNumber() >= 9 &&
+ Triple.getArch() == llvm::Triple::x86_64);
+
+ default:
+ return false;
+ }
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
const InputInfo &Output,
@@ -193,8 +514,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
CmdArgs.push_back("-triple");
+
const char *TripleStr =
- Args.MakeArgString(getToolChain().getTripleString().c_str());
+ Args.MakeArgString(getLLVMTriple(getToolChain(), Args));
CmdArgs.push_back(TripleStr);
if (isa<AnalyzeJobAction>(JA)) {
@@ -221,6 +543,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-llvm-bc");
} else if (JA.getType() == types::TY_PP_Asm) {
CmdArgs.push_back("-S");
+ } else if (JA.getType() == types::TY_AST) {
+ CmdArgs.push_back("-emit-pch");
}
}
@@ -238,9 +562,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-static-define");
if (isa<AnalyzeJobAction>(JA)) {
+ // Enable region store model by default.
+ CmdArgs.push_back("-analyzer-store=region");
+
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-warn-dead-stores");
+ CmdArgs.push_back("-warn-security-syntactic");
CmdArgs.push_back("-checker-cfref");
CmdArgs.push_back("-analyzer-eagerly-assume");
CmdArgs.push_back("-warn-objc-methodsigs");
@@ -259,8 +587,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add -Xanalyzer arguments when running as analyzer.
Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
- }
-
+ }
+
+ CheckCodeGenerationOptions(D, Args);
+
// Perform argument translation for LLVM backend. This
// takes some care in reconciling with llvm-gcc. The
// issue is that llvm-gcc translates these options based on
@@ -308,7 +638,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_ftime_report))
CmdArgs.push_back("--time-passes");
// FIXME: Set --enable-unsafe-fp-math.
- if (!Args.hasArg(options::OPT_fomit_frame_pointer))
+ if (Args.hasFlag(options::OPT_fno_omit_frame_pointer,
+ options::OPT_fomit_frame_pointer))
CmdArgs.push_back("--disable-fp-elim");
if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
options::OPT_fno_zero_initialized_in_bss,
@@ -322,71 +653,43 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--debug-pass=Arguments");
// FIXME: set --inline-threshhold=50 if (optimize_size || optimize
// < 3)
- if (Args.hasFlag(options::OPT_funwind_tables,
- options::OPT_fno_unwind_tables,
- (getToolChain().IsUnwindTablesDefault() &&
- !Args.hasArg(options::OPT_mkernel))))
+
+ // This is a coarse approximation of what llvm-gcc actually does, both
+ // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
+ // complicated ways.
+ bool AsynchronousUnwindTables =
+ Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ getToolChain().IsUnwindTablesDefault() &&
+ !Args.hasArg(options::OPT_mkernel));
+ if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
+ AsynchronousUnwindTables))
CmdArgs.push_back("--unwind-tables=1");
else
CmdArgs.push_back("--unwind-tables=0");
- if (!Args.hasFlag(options::OPT_mred_zone,
- options::OPT_mno_red_zone,
- true) ||
- Args.hasArg(options::OPT_mkernel) ||
- Args.hasArg(options::OPT_fapple_kext))
- CmdArgs.push_back("--disable-red-zone");
- if (Args.hasFlag(options::OPT_msoft_float,
- options::OPT_mno_soft_float,
- false))
- CmdArgs.push_back("--no-implicit-float");
// FIXME: Handle -mtune=.
(void) Args.hasArg(options::OPT_mtune_EQ);
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- // FIXME: We may need some translation here from the options gcc takes to
- // names the LLVM backend understand?
- CmdArgs.push_back("-mcpu");
+ if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ CmdArgs.push_back("-code-model");
CmdArgs.push_back(A->getValue(Args));
- } else {
- // Select default CPU.
-
- // FIXME: Need target hooks.
- if (memcmp(getToolChain().getOS().c_str(), "darwin", 6) == 0) {
- if (getToolChain().getArchName() == "x86_64")
- CmdArgs.push_back("--mcpu=core2");
- else if (getToolChain().getArchName() == "i386")
- CmdArgs.push_back("--mcpu=yonah");
- } else {
- if (getToolChain().getArchName() == "x86_64")
- CmdArgs.push_back("--mcpu=x86-64");
- else if (getToolChain().getArchName() == "i386")
- CmdArgs.push_back("--mcpu=pentium4");
- }
}
- // FIXME: Use iterator.
- for (ArgList::const_iterator
- it = Args.begin(), ie = Args.end(); it != ie; ++it) {
- const Arg *A = *it;
- if (A->getOption().matches(options::OPT_m_x86_Features_Group)) {
- const char *Name = A->getOption().getName();
+ // Add target specific cpu and features flags.
+ switch(getToolChain().getTriple().getArch()) {
+ default:
+ break;
- // Skip over "-m".
- assert(Name[0] == '-' && Name[1] == 'm' && "Invalid feature name.");
- Name += 2;
-
- bool IsNegative = memcmp(Name, "no-", 3) == 0;
- if (IsNegative)
- Name += 3;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ AddARMTargetArgs(Args, CmdArgs);
+ break;
- A->claim();
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("%c%s",
- IsNegative ? '-' : '+',
- Name)));
- }
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
}
if (Args.hasFlag(options::OPT_fmath_errno,
@@ -415,7 +718,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_mmacosx_version_min_EQ);
Args.AddLastArg(CmdArgs, options::OPT_miphoneos_version_min_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
+ Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
// Special case debug options to only pass -g to clang. This is
// wrong.
@@ -423,6 +726,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-g");
Args.AddLastArg(CmdArgs, options::OPT_nostdinc);
+ Args.AddLastArg(CmdArgs, options::OPT_nostdclanginc);
Args.AddLastArg(CmdArgs, options::OPT_isysroot);
@@ -434,13 +738,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs);
- // Manually translate -O to -O1 and -O4 to -O3; let clang reject
+ // Manually translate -O to -O2 and -O4 to -O3; let clang reject
// others.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().getId() == options::OPT_O4)
CmdArgs.push_back("-O3");
else if (A->getValue(Args)[0] == '\0')
- CmdArgs.push_back("-O1");
+ CmdArgs.push_back("-O2");
else
A->render(Args, CmdArgs);
}
@@ -474,9 +778,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue(Args));
}
+ if (Args.hasArg(options::OPT__relocatable_pch, true))
+ CmdArgs.push_back("--relocatable-pch");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+ CmdArgs.push_back("-fconstant-string-class");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
// Forward -f options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
- Args.AddLastArg(CmdArgs, options::OPT_fexceptions);
Args.AddLastArg(CmdArgs, options::OPT_ffreestanding);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fgnu_runtime);
@@ -498,6 +809,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_EQ);
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
+ Args.AddLastArg(CmdArgs, options::OPT_pthread);
+
// Forward stack protector flags.
if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
options::OPT_fstack_protector_all,
@@ -526,6 +839,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fblocks=0");
}
+ if (needsExceptions(Args, InputType, getToolChain().getTriple()))
+ CmdArgs.push_back("-fexceptions");
+ else
+ CmdArgs.push_back("-fexceptions=0");
+
+ // -frtti is default, only pass non-default.
+ if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
+ CmdArgs.push_back("-frtti=0");
+
// -fsigned-char/-funsigned-char default varies depending on platform; only
// pass if specified.
if (Arg *A = Args.getLastArg(options::OPT_fsigned_char,
@@ -556,18 +878,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fsigned-bitfields is default, and clang doesn't yet support
// --funsigned-bitfields.
- if (!Args.hasFlag(options::OPT_fsigned_bitfields,
+ if (!Args.hasFlag(options::OPT_fsigned_bitfields,
options::OPT_funsigned_bitfields))
D.Diag(clang::diag::warn_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
// -fdiagnostics-fixit-info is default, only pass non-default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
+ if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
options::OPT_fno_diagnostics_fixit_info))
CmdArgs.push_back("-fno-diagnostics-fixit-info");
// Enable -fdiagnostics-show-option by default.
- if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
options::OPT_fno_diagnostics_show_option))
CmdArgs.push_back("-fdiagnostics-show-option");
if (!Args.hasFlag(options::OPT_fcolor_diagnostics,
@@ -579,7 +901,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fdollars-in-identifiers default varies depending on platform and
// language; only pass if specified.
- if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
+ if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
options::OPT_fno_dollars_in_identifiers)) {
if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
CmdArgs.push_back("-fdollars-in-identifiers=1");
@@ -589,12 +911,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
// practical purposes.
- if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
+ if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
options::OPT_fno_unit_at_a_time)) {
if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ D.Diag(clang::diag::warn_drv_clang_unsupported) << A->getAsString(Args);
}
-
+
+ // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
+ //
+ // FIXME: This is disabled until clang-cc supports -fno-builtin-foo. PR4941.
+#if 0
+ if (getToolChain().getTriple().getOS() == llvm::Triple::Darwin &&
+ (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
+ if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+ CmdArgs.push_back("-fno-builtin-strcat");
+ if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+ CmdArgs.push_back("-fno-builtin-strcpy");
+ }
+#endif
+
+ if (Arg *A = Args.getLastArg(options::OPT_traditional,
+ options::OPT_traditional_cpp))
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
Args.AddLastArg(CmdArgs, options::OPT_dM);
Args.AddLastArg(CmdArgs, options::OPT_dD);
@@ -627,7 +967,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
// Explicitly warn that these options are unsupported, even though
@@ -699,7 +1039,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
else if (Arch == "powerpc64")
CmdArgs.push_back("ppc64");
else
- CmdArgs.push_back(Args.MakeArgString(Arch.c_str()));
+ CmdArgs.push_back(Args.MakeArgString(Arch));
}
// Try to force gcc to match the tool chain we want, if we recognize
@@ -736,10 +1076,13 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- // Don't try to pass LLVM inputs to a generic gcc.
+ // Don't try to pass LLVM or AST inputs to a generic gcc.
if (II.getType() == types::TY_LLVMBC)
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString().c_str();
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_AST)
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
if (types::canTypeBeUserSpecified(II.getType())) {
CmdArgs.push_back("-x");
@@ -758,7 +1101,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const char *GCCName =
getToolChain().getHost().getDriver().CCCGenericGCCName.c_str();
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName).c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -805,7 +1148,7 @@ const char *darwin::CC1::getCC1Name(types::ID Type) const {
const char *darwin::CC1::getBaseInputName(const ArgList &Args,
const InputInfoList &Inputs) {
llvm::sys::Path P(Inputs[0].getBaseInput());
- return Args.MakeArgString(P.getLast().c_str());
+ return Args.MakeArgString(P.getLast());
}
const char *darwin::CC1::getBaseInputStem(const ArgList &Args,
@@ -813,7 +1156,7 @@ const char *darwin::CC1::getBaseInputStem(const ArgList &Args,
const char *Str = getBaseInputName(Args, Inputs);
if (const char *End = strchr(Str, '.'))
- return Args.MakeArgString(std::string(Str, End).c_str());
+ return Args.MakeArgString(std::string(Str, End));
return Str;
}
@@ -831,31 +1174,32 @@ darwin::CC1::getDependencyFileName(const ArgList &Args,
} else
Res = darwin::CC1::getBaseInputStem(Args, Inputs);
- return Args.MakeArgString((Res + ".d").c_str());
+ return Args.MakeArgString(Res + ".d");
}
void darwin::CC1::AddCC1Args(const ArgList &Args,
ArgStringList &CmdArgs) const {
- // Derived from cc1 spec.
+ const Driver &D = getToolChain().getHost().getDriver();
+
+ CheckCodeGenerationOptions(D, Args);
- // FIXME: -fapple-kext seems to disable this too. Investigate.
+ // Derived from cc1 spec.
if (!Args.hasArg(options::OPT_mkernel) && !Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_mdynamic_no_pic))
CmdArgs.push_back("-fPIC");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+ if (!Args.hasArg(options::OPT_fbuiltin_strcat))
+ CmdArgs.push_back("-fno-builtin-strcat");
+ if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
+ CmdArgs.push_back("-fno-builtin-strcpy");
+ }
+
// gcc has some code here to deal with when no -mmacosx-version-min
// and no -miphoneos-version-min is present, but this never happens
// due to tool chain specific argument translation.
- // FIXME: Remove mthumb
- // FIXME: Remove mno-thumb
- // FIXME: Remove faltivec
- // FIXME: Remove mno-fused-madd
- // FIXME: Remove mlong-branch
- // FIXME: Remove mlongcall
- // FIXME: Remove mcpu=G4
- // FIXME: Remove mcpu=G5
-
if (Args.hasArg(options::OPT_g_Flag) &&
!Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols))
CmdArgs.push_back("-feliminate-unused-debug-symbols");
@@ -924,7 +1268,28 @@ void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
Args.AddLastArg(CmdArgs, options::OPT_p);
// The driver treats -fsyntax-only specially.
- Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
+ if (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
+ getToolChain().getTriple().getArch() == llvm::Triple::thumb) {
+ // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are
+ // used to inhibit the default -fno-builtin-str{cat,cpy}.
+ //
+ // FIXME: Should we grow a better way to deal with "removing" args?
+ //
+ // FIXME: Use iterator.
+ for (ArgList::const_iterator it = Args.begin(),
+ ie = Args.end(); it != ie; ++it) {
+ const Arg *A = *it;
+ if (A->getOption().matches(options::OPT_f_Group) ||
+ A->getOption().matches(options::OPT_fsyntax_only)) {
+ if (!A->getOption().matches(options::OPT_fbuiltin_strcat) &&
+ !A->getOption().matches(options::OPT_fbuiltin_strcpy)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+ }
+ }
+ } else
+ Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only);
Args.AddAllArgs(CmdArgs, options::OPT_undef);
if (Args.hasArg(options::OPT_Qn))
@@ -995,18 +1360,15 @@ void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
ArgStringList &CmdArgs,
- const InputInfoList &Inputs) const
-{
+ const InputInfoList &Inputs) const {
const Driver &D = getToolChain().getHost().getDriver();
+ CheckPreprocessingOptions(D, Args);
+
// Derived from cpp_unique_options.
- Arg *A;
- if ((A = Args.getLastArg(options::OPT_C)) ||
- (A = Args.getLastArg(options::OPT_CC))) {
- if (!Args.hasArg(options::OPT_E))
- D.Diag(clang::diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "-E";
- }
+ // -{C,CC} only with -E is checked in CheckPreprocessingOptions().
+ Args.AddLastArg(CmdArgs, options::OPT_C);
+ Args.AddLastArg(CmdArgs, options::OPT_CC);
if (!Args.hasArg(options::OPT_Q))
CmdArgs.push_back("-quiet");
Args.AddAllArgs(CmdArgs, options::OPT_nostdinc);
@@ -1111,7 +1473,6 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-E");
if (Args.hasArg(options::OPT_traditional) ||
- Args.hasArg(options::OPT_ftraditional) ||
Args.hasArg(options::OPT_traditional_cpp))
CmdArgs.push_back("-traditional-cpp");
@@ -1134,7 +1495,7 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
const char *CC1Name = getCC1Name(Inputs[0].getType());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1150,8 +1511,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
types::ID InputType = Inputs[0].getType();
const Arg *A;
- if ((A = Args.getLastArg(options::OPT_traditional)) ||
- (A = Args.getLastArg(options::OPT_ftraditional)))
+ if ((A = Args.getLastArg(options::OPT_traditional)))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-E";
@@ -1159,6 +1519,9 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-llvm");
else if (Output.getType() == types::TY_LLVMBC)
CmdArgs.push_back("-emit-llvm-bc");
+ else if (Output.getType() == types::TY_AST)
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
ArgStringList OutputArgs;
if (Output.getType() != types::TY_PCH) {
@@ -1187,13 +1550,17 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("-fpreprocessed");
- // FIXME: There is a spec command to remove
- // -fpredictive-compilation args here. Investigate.
-
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
+ // Reject AST inputs.
+ if (II.getType() == types::TY_AST) {
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+ return;
+ }
+
if (II.isPipe())
CmdArgs.push_back("-");
else
@@ -1222,7 +1589,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
const char *CC1Name = getCC1Name(Inputs[0].getType());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1248,14 +1615,16 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
// Derived from asm spec.
- CmdArgs.push_back("-arch");
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName().c_str()));
+ AddDarwinArch(Args, CmdArgs);
+
+ if (!getDarwinToolChain().isIPhoneOS() ||
+ Args.hasArg(options::OPT_force__cpusubtype__ALL))
+ CmdArgs.push_back("-force_cpusubtype_ALL");
- CmdArgs.push_back("-force_cpusubtype_ALL");
- if ((Args.hasArg(options::OPT_mkernel) ||
+ if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
+ (Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_fapple_kext)) &&
- !Args.hasArg(options::OPT_dynamic))
+ Args.hasArg(options::OPT_fapple_kext)))
CmdArgs.push_back("-static");
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -1275,7 +1644,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
// asm_final spec is empty.
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1304,33 +1673,84 @@ static bool isSourceSuffix(const char *Str) {
}
}
-static bool isMacosxVersionLT(unsigned (&A)[3], unsigned (&B)[3]) {
- for (unsigned i=0; i < 3; ++i) {
- if (A[i] > B[i]) return false;
- if (A[i] < B[i]) return true;
- }
- return false;
-}
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMArch(llvm::StringRef Value) {
+ if (Value == "armv6k")
+ return "armv6";
+
+ if (Value == "armv5tej")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
-static bool isMacosxVersionLT(unsigned (&A)[3],
- unsigned V0, unsigned V1=0, unsigned V2=0) {
- unsigned B[3] = { V0, V1, V2 };
- return isMacosxVersionLT(A, B);
+ if (Value == "armv4t")
+ return "armv4t";
+
+ if (Value == "armv7" || Value == "armv7-a" || Value == "armv7-r" ||
+ Value == "armv7-m" || Value == "armv7a" || Value == "armv7r" ||
+ Value == "armv7m")
+ return "armv7";
+
+ return 0;
}
-const toolchains::Darwin_X86 &darwin::Link::getDarwinToolChain() const {
- return reinterpret_cast<const toolchains::Darwin_X86&>(getToolChain());
+// FIXME: Can we tablegen this?
+static const char *GetArmArchForMCpu(llvm::StringRef Value) {
+ if (Value == "arm10tdmi" || Value == "arm1020t" || Value == "arm9e" ||
+ Value == "arm946e-s" || Value == "arm966e-s" ||
+ Value == "arm968e-s" || Value == "arm10e" ||
+ Value == "arm1020e" || Value == "arm1022e" || Value == "arm926ej-s" ||
+ Value == "arm1026ej-s")
+ return "armv5";
+
+ if (Value == "xscale")
+ return "xscale";
+
+ if (Value == "arm1136j-s" || Value == "arm1136jf-s" ||
+ Value == "arm1176jz-s" || Value == "arm1176jzf-s")
+ return "armv6";
+
+ if (Value == "cortex-a8" || Value == "cortex-r4" || Value == "cortex-m3")
+ return "armv7";
+
+ return 0;
}
-void darwin::Link::AddDarwinArch(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// Derived from darwin_arch spec.
CmdArgs.push_back("-arch");
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName().c_str()));
+
+ switch (getToolChain().getTriple().getArch()) {
+ default:
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
+ break;
+
+ case llvm::Triple::arm: {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ if (const char *Arch = GetArmArchForMArch(A->getValue(Args))) {
+ CmdArgs.push_back(Arch);
+ return;
+ }
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ if (const char *Arch = GetArmArchForMCpu(A->getValue(Args))) {
+ CmdArgs.push_back(Arch);
+ return;
+ }
+ }
+
+ CmdArgs.push_back("arm");
+ CmdArgs.push_back("-force_cpusubtype_ALL");
+ return;
+ }
+ }
}
-void darwin::Link::AddDarwinSubArch(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+void darwin::DarwinTool::AddDarwinSubArch(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
// Derived from darwin_subarch spec, not sure what the distinction
// exists for but at least for this chain it is the same.
AddDarwinArch(Args, CmdArgs);
@@ -1401,6 +1821,8 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
Args.AddLastArg(CmdArgs, options::OPT_all__load);
Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
+ if (getDarwinToolChain().isIPhoneOS())
+ Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
@@ -1411,22 +1833,22 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_image__base);
Args.AddAllArgs(CmdArgs, options::OPT_init);
- if (!Args.hasArg(options::OPT_mmacosx_version_min_EQ)) {
- if (!Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
- // FIXME: I don't understand what is going on here. This is
- // supposed to come from darwin_ld_minversion, but gcc doesn't
- // seem to be following that; it must be getting overridden
- // somewhere.
+ if (!Args.hasArg(options::OPT_mmacosx_version_min_EQ) &&
+ !Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
+ // Add default version min.
+ if (!getDarwinToolChain().isIPhoneOS()) {
CmdArgs.push_back("-macosx_version_min");
CmdArgs.push_back(getDarwinToolChain().getMacosxVersionStr());
+ } else {
+ CmdArgs.push_back("-iphoneos_version_min");
+ CmdArgs.push_back(getDarwinToolChain().getIPhoneOSVersionStr());
}
- } else {
- // Adding all arguments doesn't make sense here but this is what
- // gcc does.
- Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
- "-macosx_version_min");
}
+ // Adding all arguments doesn't make sense here but this is what
+ // gcc does.
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_mmacosx_version_min_EQ,
+ "-macosx_version_min");
Args.AddAllArgsTranslated(CmdArgs, options::OPT_miphoneos_version_min_EQ,
"-iphoneos_version_min");
Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
@@ -1454,14 +1876,22 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
+
Args.AddAllArgsTranslated(CmdArgs, options::OPT_isysroot, "-syslibroot");
+ if (getDarwinToolChain().isIPhoneOS()) {
+ if (!Args.hasArg(options::OPT_isysroot)) {
+ CmdArgs.push_back("-syslibroot");
+ CmdArgs.push_back("/Developer/SDKs/Extra");
+ }
+ }
+
Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
Args.AddAllArgs(CmdArgs, options::OPT_undefined);
Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
- Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
+ Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
if (!Args.hasArg(options::OPT_weak__reference__mismatches)) {
CmdArgs.push_back("-weak_reference_mismatches");
CmdArgs.push_back("non-weak");
@@ -1490,20 +1920,16 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
+
// The logic here is derived from gcc's behavior; most of which
// comes from specs (starting with link_command). Consult gcc for
// more information.
-
- // FIXME: The spec references -fdump= which seems to have
- // disappeared?
-
ArgStringList CmdArgs;
// I'm not sure why this particular decomposition exists in gcc, but
// we follow suite for ease of comparison.
AddLinkArgs(Args, CmdArgs);
- // FIXME: gcc has %{x} in here. How could this ever happen? Cruft?
Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_s);
Args.AddAllArgs(CmdArgs, options::OPT_t);
@@ -1514,28 +1940,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- // FIXME: This is just being pedantically bug compatible, gcc
- // doesn't *mean* to forward this, it just does (yay for pattern
- // matching). It doesn't work, of course.
- Args.AddAllArgs(CmdArgs, options::OPT_object);
-
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- unsigned MacosxVersion[3];
- if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ)) {
- bool HadExtra;
- if (!Driver::GetReleaseVersion(A->getValue(Args), MacosxVersion[0],
- MacosxVersion[1], MacosxVersion[2],
- HadExtra) ||
- HadExtra) {
- const Driver &D = getToolChain().getHost().getDriver();
- D.Diag(clang::diag::err_drv_invalid_version_number)
- << A->getAsString(Args);
- }
- } else {
- getDarwinToolChain().getMacosxVersion(MacosxVersion);
- }
+
+ unsigned MacosxVersionMin[3];
+ getDarwinToolChain().getMacosxVersionMin(Args, MacosxVersionMin);
if (!Args.hasArg(options::OPT_A) &&
!Args.hasArg(options::OPT_nostdlib) &&
@@ -1543,15 +1953,15 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib)) {
// Derived from darwin_dylib1 spec.
- if (isMacosxVersionLT(MacosxVersion, 10, 5))
+ if (getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin, 10, 5))
CmdArgs.push_back("-ldylib1.o");
- else if (isMacosxVersionLT(MacosxVersion, 10, 6))
+ else if (getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin, 10, 6))
CmdArgs.push_back("-ldylib1.10.5.o");
} else {
if (Args.hasArg(options::OPT_bundle)) {
if (!Args.hasArg(options::OPT_static)) {
// Derived from darwin_bundle1 spec.
- if (isMacosxVersionLT(MacosxVersion, 10, 6))
+ if (getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin, 10, 6))
CmdArgs.push_back("-lbundle1.o");
}
} else {
@@ -1572,9 +1982,13 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lcrt0.o");
} else {
// Derived from darwin_crt1 spec.
- if (isMacosxVersionLT(MacosxVersion, 10, 5))
+ if (getDarwinToolChain().isIPhoneOS()) {
+ CmdArgs.push_back("-lcrt1.o");
+ } else if (getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin,
+ 10, 5))
CmdArgs.push_back("-lcrt1.o");
- else if (isMacosxVersionLT(MacosxVersion, 10, 6))
+ else if (getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin,
+ 10, 6))
CmdArgs.push_back("-lcrt1.10.5.o");
else
CmdArgs.push_back("-lcrt1.10.6.o");
@@ -1587,9 +2001,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_shared_libgcc) &&
!Args.hasArg(options::OPT_miphoneos_version_min_EQ) &&
- isMacosxVersionLT(MacosxVersion, 10, 5)) {
- const char *Str = getToolChain().GetFilePath(C, "crt3.o").c_str();
- CmdArgs.push_back(Args.MakeArgString(Str));
+ getDarwinToolChain().isMacosxVersionLT(MacosxVersionMin, 10, 5)) {
+ const char *Str =
+ Args.MakeArgString(getToolChain().GetFilePath(C, "crt3.o"));
+ CmdArgs.push_back(Str);
}
}
@@ -1599,26 +2014,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// This is more complicated in gcc...
CmdArgs.push_back("-lgomp");
- // FIXME: Derive these correctly.
- const char *TCDir = getDarwinToolChain().getToolChainDir().c_str();
- if (getToolChain().getArchName() == "x86_64") {
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s/x86_64", TCDir)));
- // Intentionally duplicated for (temporary) gcc bug compatibility.
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s/x86_64", TCDir)));
- }
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/%s", TCDir)));
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s", TCDir)));
- // Intentionally duplicated for (temporary) gcc bug compatibility.
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s", TCDir)));
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s/../../../%s", TCDir, TCDir)));
- CmdArgs.push_back(MakeFormattedString(Args,
- llvm::format("-L/usr/lib/gcc/%s/../../..", TCDir)));
+ getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
@@ -1653,40 +2049,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
// link_ssp spec is empty.
- // Derived from libgcc and lib specs but refactored.
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lgcc_static");
- } else {
- if (Args.hasArg(options::OPT_static_libgcc)) {
- CmdArgs.push_back("-lgcc_eh");
- } else if (Args.hasArg(options::OPT_miphoneos_version_min_EQ)) {
- // Derived from darwin_iphoneos_libgcc spec.
- CmdArgs.push_back("-lgcc_s.10.5");
- } else if (Args.hasArg(options::OPT_shared_libgcc) ||
- Args.hasArg(options::OPT_fexceptions) ||
- Args.hasArg(options::OPT_fgnu_runtime)) {
- // FIXME: This is probably broken on 10.3?
- if (isMacosxVersionLT(MacosxVersion, 10, 5))
- CmdArgs.push_back("-lgcc_s.10.4");
- else if (isMacosxVersionLT(MacosxVersion, 10, 6))
- CmdArgs.push_back("-lgcc_s.10.5");
- } else {
- if (isMacosxVersionLT(MacosxVersion, 10, 3, 9))
- ; // Do nothing.
- else if (isMacosxVersionLT(MacosxVersion, 10, 5))
- CmdArgs.push_back("-lgcc_s.10.4");
- else if (isMacosxVersionLT(MacosxVersion, 10, 6))
- CmdArgs.push_back("-lgcc_s.10.5");
- }
-
- if (isMacosxVersionLT(MacosxVersion, 10, 6)) {
- CmdArgs.push_back("-lgcc");
- CmdArgs.push_back("-lSystem");
- } else {
- CmdArgs.push_back("-lSystem");
- CmdArgs.push_back("-lgcc");
- }
- }
+ // Let the tool chain choose which runtime library to link.
+ getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
}
if (!Args.hasArg(options::OPT_A) &&
@@ -1699,7 +2063,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_F);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
// Find the first non-empty base input (we want to ignore linker
@@ -1727,7 +2091,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Suffix = strrchr(BaseInput, '.');
if (Suffix && isSourceSuffix(Suffix + 1)) {
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil"));
ArgStringList CmdArgs;
CmdArgs.push_back(Output.getFilename());
C.getJobs().addCommand(new Command(JA, Exec, CmdArgs));
@@ -1755,7 +2119,135 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo"));
+ Dest.addCommand(new Command(JA, Exec, CmdArgs));
+}
+
+void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ if (Output.isPipe())
+ CmdArgs.push_back("-");
+ else
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ if (II.isPipe())
+ CmdArgs.push_back("-");
+ else
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
+ Dest.addCommand(new Command(JA, Exec, CmdArgs));
+}
+
+void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getHost().getDriver();
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("__start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
+ }
+ }
+
+ if (Output.isPipe()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back("-");
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
+ }
+ }
+
+ CmdArgs.push_back(MakeFormattedString(Args,
+ llvm::format("-L/opt/gcc4/lib/gcc/%s/4.2.4",
+ getToolChain().getTripleString().c_str())));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ // Don't try to pass LLVM inputs to a generic gcc.
+ if (II.getType() == types::TY_LLVMBC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+
+ if (II.isPipe())
+ CmdArgs.push_back("-");
+ else if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-pthread");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1763,8 +2255,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest, const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
- const char *LinkingOutput) const
-{
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -1786,7 +2277,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1798,12 +2289,19 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = getToolChain().getHost().getDriver();
ArgStringList CmdArgs;
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("__start");
+ }
+
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
} else {
CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-Bshareable");
+ CmdArgs.push_back("-shared");
} else {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld.so");
@@ -1823,13 +2321,17 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
}
+ CmdArgs.push_back(MakeFormattedString(Args,
+ llvm::format("-L/usr/lib/gcc-lib/%s/3.3.5",
+ getToolChain().getTripleString().c_str())));
+
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
@@ -1841,7 +2343,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Don't try to pass LLVM inputs to a generic gcc.
if (II.getType() == types::TY_LLVMBC)
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString().c_str();
+ << getToolChain().getTripleString();
if (II.isPipe())
CmdArgs.push_back("-");
@@ -1853,22 +2355,27 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-pthread");
- CmdArgs.push_back("-lc");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
}
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1876,8 +2383,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest, const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
- const char *LinkingOutput) const
-{
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
@@ -1904,7 +2410,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -1948,12 +2454,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
}
@@ -1968,7 +2474,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Don't try to pass LLVM inputs to a generic gcc.
if (II.getType() == types::TY_LLVMBC)
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString().c_str();
+ << getToolChain().getTripleString();
if (II.isPipe())
CmdArgs.push_back("-");
@@ -2008,14 +2514,14 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -2054,7 +2560,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "as"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
@@ -2097,12 +2603,12 @@ 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(C, "crt1.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));
} else {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));
}
}
@@ -2117,7 +2623,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Don't try to pass LLVM inputs to a generic gcc.
if (II.getType() == types::TY_LLVMBC)
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << getToolChain().getTripleString().c_str();
+ << getToolChain().getTripleString();
if (II.isPipe())
CmdArgs.push_back("-");
@@ -2171,13 +2677,13 @@ 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(C, "crtend.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o")));
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str()));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o").c_str()));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str());
+ Args.MakeArgString(getToolChain().GetProgramPath(C, "ld"));
Dest.addCommand(new Command(JA, Exec, CmdArgs));
}
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index ab7349600907..6729da8370a5 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -21,7 +21,7 @@ namespace driver {
class Driver;
namespace toolchains {
- class Darwin_X86;
+ class Darwin;
}
namespace tools {
@@ -33,6 +33,9 @@ namespace tools {
const InputInfo &Output,
const InputInfoList &Inputs) const;
+ void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
+
public:
Clang(const ToolChain &TC) : Tool("clang", TC) {}
@@ -42,9 +45,9 @@ namespace tools {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -56,9 +59,9 @@ namespace gcc {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
/// RenderExtraToolArgs - Render any arguments necessary to force
@@ -66,7 +69,7 @@ namespace gcc {
virtual void RenderExtraToolArgs(ArgStringList &CmdArgs) const = 0;
};
-
+
class VISIBILITY_HIDDEN Preprocess : public Common {
public:
Preprocess(const ToolChain &TC) : Common("gcc::Preprocess", TC) {}
@@ -124,13 +127,26 @@ namespace gcc {
} // end namespace gcc
namespace darwin {
- class VISIBILITY_HIDDEN CC1 : public Tool {
+ class VISIBILITY_HIDDEN DarwinTool : public Tool {
+ protected:
+ void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddDarwinSubArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+
+ const toolchains::Darwin &getDarwinToolChain() const {
+ return reinterpret_cast<const toolchains::Darwin&>(getToolChain());
+ }
+
+ public:
+ DarwinTool(const char *Name, const ToolChain &TC) : Tool(Name, TC) {};
+ };
+
+ class VISIBILITY_HIDDEN CC1 : public DarwinTool {
public:
- static const char *getBaseInputName(const ArgList &Args,
+ static const char *getBaseInputName(const ArgList &Args,
const InputInfoList &Input);
- static const char *getBaseInputStem(const ArgList &Args,
+ static const char *getBaseInputStem(const ArgList &Args,
const InputInfoList &Input);
- static const char *getDependencyFileName(const ArgList &Args,
+ static const char *getDependencyFileName(const ArgList &Args,
const InputInfoList &Inputs);
protected:
@@ -143,13 +159,13 @@ namespace darwin {
void AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs,
const InputInfoList &Inputs,
const ArgStringList &OutputArgs) const;
- void AddCPPUniqueOptionsArgs(const ArgList &Args,
+ void AddCPPUniqueOptionsArgs(const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfoList &Inputs) const;
void AddCPPArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
public:
- CC1(const char *Name, const ToolChain &TC) : Tool(Name, TC) {}
+ CC1(const char *Name, const ToolChain &TC) : DarwinTool(Name, TC) {}
virtual bool acceptsPipedInput() const { return true; }
virtual bool canPipeOutput() const { return true; }
@@ -162,9 +178,9 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -174,15 +190,15 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
- class VISIBILITY_HIDDEN Assemble : public Tool {
+ class VISIBILITY_HIDDEN Assemble : public DarwinTool {
public:
- Assemble(const ToolChain &TC) : Tool("darwin::Assemble", TC) {}
+ Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble", TC) {}
virtual bool acceptsPipedInput() const { return true; }
virtual bool canPipeOutput() const { return false; }
@@ -190,27 +206,17 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
- class VISIBILITY_HIDDEN Link : public Tool {
- void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddDarwinSubArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+ class VISIBILITY_HIDDEN Link : public DarwinTool {
void AddLinkArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- /// The default macosx-version-min.
- const char *MacosxVersionMin;
-
- const toolchains::Darwin_X86 &getDarwinToolChain() const;
-
public:
- Link(const ToolChain &TC,
- const char *_MacosxVersionMin)
- : Tool("darwin::Link", TC), MacosxVersionMin(_MacosxVersionMin) {
- }
+ Link(const ToolChain &TC) : DarwinTool("darwin::Link", TC) {}
virtual bool acceptsPipedInput() const { return false; }
virtual bool canPipeOutput() const { return false; }
@@ -218,15 +224,15 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
- class VISIBILITY_HIDDEN Lipo : public Tool {
+ class VISIBILITY_HIDDEN Lipo : public DarwinTool {
public:
- Lipo(const ToolChain &TC) : Tool("darwin::Lipo", TC) {}
+ Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", TC) {}
virtual bool acceptsPipedInput() const { return false; }
virtual bool canPipeOutput() const { return false; }
@@ -234,9 +240,9 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
}
@@ -253,9 +259,9 @@ namespace openbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
class VISIBILITY_HIDDEN Link : public Tool {
@@ -268,12 +274,12 @@ namespace openbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
-}
+} // end namespace openbsd
/// freebsd -- Directly call GNU Binutils assembler and linker
namespace freebsd {
@@ -287,9 +293,9 @@ namespace freebsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
class VISIBILITY_HIDDEN Link : public Tool {
@@ -302,12 +308,46 @@ namespace freebsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
-}
+} // end namespace freebsd
+
+ /// auroraux -- Directly call GNU Binutils assembler and linker
+namespace auroraux {
+ class VISIBILITY_HIDDEN Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", TC) {}
+
+ virtual bool acceptsPipedInput() const { return true; }
+ virtual bool canPipeOutput() const { return true; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class VISIBILITY_HIDDEN Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("auroraux::Link", TC) {}
+
+ virtual bool acceptsPipedInput() const { return true; }
+ virtual bool canPipeOutput() const { return true; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace auroraux
/// dragonfly -- Directly call GNU Binutils assembler and linker
namespace dragonfly {
@@ -321,9 +361,9 @@ namespace dragonfly {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
class VISIBILITY_HIDDEN Link : public Tool {
@@ -336,15 +376,15 @@ namespace dragonfly {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
const char *LinkingOutput) const;
};
-}
+} // end namespace dragonfly
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
-#endif
+#endif // CLANG_LIB_DRIVER_TOOLS_H_
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index e89e973f3f53..eee8c19c2776 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -35,38 +35,38 @@ static Info &getInfo(unsigned id) {
return TypeInfos[id - 1];
}
-const char *types::getTypeName(ID Id) {
- return getInfo(Id).Name;
+const char *types::getTypeName(ID Id) {
+ return getInfo(Id).Name;
}
-types::ID types::getPreprocessedType(ID Id) {
- return getInfo(Id).PreprocessedType;
+types::ID types::getPreprocessedType(ID Id) {
+ return getInfo(Id).PreprocessedType;
}
-const char *types::getTypeTempSuffix(ID Id) {
- return getInfo(Id).TempSuffix;
+const char *types::getTypeTempSuffix(ID Id) {
+ return getInfo(Id).TempSuffix;
}
-bool types::onlyAssembleType(ID Id) {
- return strchr(getInfo(Id).Flags, 'a');
+bool types::onlyAssembleType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'a');
}
-bool types::onlyPrecompileType(ID Id) {
- return strchr(getInfo(Id).Flags, 'p');
+bool types::onlyPrecompileType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'p');
}
-bool types::canTypeBeUserSpecified(ID Id) {
- return strchr(getInfo(Id).Flags, 'u');
+bool types::canTypeBeUserSpecified(ID Id) {
+ return strchr(getInfo(Id).Flags, 'u');
}
-bool types::appendSuffixForType(ID Id) {
- return strchr(getInfo(Id).Flags, 'A');
+bool types::appendSuffixForType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'A');
}
-bool types::canLipoType(ID Id) {
+bool types::canLipoType(ID Id) {
return (Id == TY_Nothing ||
Id == TY_Image ||
- Id == TY_Object);
+ Id == TY_Object);
}
bool types::isAcceptedByClang(ID Id) {
@@ -83,6 +83,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:
return true;
}
}
@@ -128,6 +129,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
case 3:
if (memcmp(Ext, "ads", 3) == 0) return TY_Ada;
if (memcmp(Ext, "adb", 3) == 0) return TY_Ada;
+ if (memcmp(Ext, "ast", 3) == 0) return TY_AST;
if (memcmp(Ext, "cxx", 3) == 0) return TY_CXX;
if (memcmp(Ext, "cpp", 3) == 0) return TY_CXX;
if (memcmp(Ext, "CPP", 3) == 0) return TY_CXX;
@@ -152,7 +154,7 @@ types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
for (unsigned i=0; i<numTypes; ++i) {
types::ID Id = (types::ID) (i + 1);
- if (canTypeBeUserSpecified(Id) &&
+ if (canTypeBeUserSpecified(Id) &&
memcmp(Name, getInfo(Id).Name, N + 1) == 0)
return Id;
}
@@ -162,25 +164,25 @@ types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
// FIXME: Why don't we just put this list in the defs file, eh.
-unsigned types::getNumCompilationPhases(ID Id) {
+unsigned types::getNumCompilationPhases(ID Id) {
if (Id == TY_Object)
return 1;
-
+
unsigned N = 0;
if (getPreprocessedType(Id) != TY_INVALID)
N += 1;
-
+
if (onlyAssembleType(Id))
return N + 2; // assemble, link
if (onlyPrecompileType(Id))
return N + 1; // precompile
-
+
return N + 3; // compile, assemble, link
}
phases::ID types::getCompilationPhase(ID Id, unsigned N) {
assert(N < getNumCompilationPhases(Id) && "Invalid index.");
-
+
if (Id == TY_Object)
return phases::Link;
@@ -200,6 +202,6 @@ phases::ID types::getCompilationPhase(ID Id, unsigned N) {
return phases::Compile;
if (N == 1)
return phases::Assemble;
-
+
return phases::Link;
}