summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Action.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Arg.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ArgList.cpp423
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp199
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp512
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp19
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/InputInfo.h11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp163
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/OptTable.cpp388
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Option.cpp200
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp389
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h220
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp64
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp1227
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.h303
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp2230
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.h188
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp55
20 files changed, 3572 insertions, 3181 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
index 2b5bbee..ddd2d59 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
@@ -11,6 +11,7 @@
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
using namespace clang::driver;
+using namespace llvm::opt;
Action::~Action() {
if (OwnsInputs) {
diff --git a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp
deleted file mode 100644
index 93d70a9..0000000
--- a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-//===--- Arg.cpp - Argument Implementations -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/Arg.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/Driver/ArgList.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;
-using clang::StringRef;
-
-Arg::Arg(const Option _Opt, StringRef S, unsigned _Index, const Arg *_BaseArg)
- : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
- Claimed(false), OwnsValues(false) {
-}
-
-Arg::Arg(const Option _Opt, StringRef S, unsigned _Index,
- const char *Value0, const Arg *_BaseArg)
- : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
- Claimed(false), OwnsValues(false) {
- Values.push_back(Value0);
-}
-
-Arg::Arg(const Option _Opt, StringRef S, unsigned _Index,
- const char *Value0, const char *Value1, const Arg *_BaseArg)
- : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
- Claimed(false), OwnsValues(false) {
- Values.push_back(Value0);
- Values.push_back(Value1);
-}
-
-Arg::~Arg() {
- if (OwnsValues) {
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- delete[] Values[i];
- }
-}
-
-void Arg::dump() const {
- llvm::errs() << "<";
-
- llvm::errs() << " Opt:";
- Opt.dump();
-
- llvm::errs() << " Index:" << Index;
-
- llvm::errs() << " Values: [";
- for (unsigned i = 0, e = Values.size(); i != e; ++i) {
- if (i) llvm::errs() << ", ";
- llvm::errs() << "'" << Values[i] << "'";
- }
-
- llvm::errs() << "]>\n";
-}
-
-std::string Arg::getAsString(const ArgList &Args) const {
- SmallString<256> Res;
- llvm::raw_svector_ostream OS(Res);
-
- ArgStringList ASL;
- render(Args, ASL);
- for (ArgStringList::iterator
- it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
- if (it != ASL.begin())
- OS << ' ';
- OS << *it;
- }
-
- return OS.str();
-}
-
-void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
- if (!getOption().hasNoOptAsInput()) {
- render(Args, Output);
- return;
- }
-
- for (unsigned i = 0, e = getNumValues(); i != e; ++i)
- Output.push_back(getValue(i));
-}
-
-void Arg::render(const ArgList &Args, ArgStringList &Output) const {
- switch (getOption().getRenderStyle()) {
- case Option::RenderValuesStyle:
- for (unsigned i = 0, e = getNumValues(); i != e; ++i)
- Output.push_back(getValue(i));
- break;
-
- case Option::RenderCommaJoinedStyle: {
- SmallString<256> Res;
- llvm::raw_svector_ostream OS(Res);
- OS << getSpelling();
- for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
- if (i) OS << ',';
- OS << getValue(i);
- }
- Output.push_back(Args.MakeArgString(OS.str()));
- break;
- }
-
- case Option::RenderJoinedStyle:
- Output.push_back(Args.GetOrMakeJoinedArgString(
- getIndex(), getSpelling(), getValue(0)));
- for (unsigned i = 1, e = getNumValues(); i != e; ++i)
- Output.push_back(getValue(i));
- break;
-
- case Option::RenderSeparateStyle:
- Output.push_back(Args.MakeArgString(getSpelling()));
- for (unsigned i = 0, e = getNumValues(); i != e; ++i)
- Output.push_back(getValue(i));
- break;
- }
-}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp
deleted file mode 100644
index 4b8d151..0000000
--- a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-//===--- ArgList.cpp - Argument List Management ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/DriverDiagnostic.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;
-using namespace clang::driver;
-
-void arg_iterator::SkipToNextArg() {
- for (; Current != Args.end(); ++Current) {
- // Done if there are no filters.
- if (!Id0.isValid())
- break;
-
- // Otherwise require a match.
- const Option &O = (*Current)->getOption();
- if (O.matches(Id0) ||
- (Id1.isValid() && O.matches(Id1)) ||
- (Id2.isValid() && O.matches(Id2)))
- break;
- }
-}
-
-//
-
-ArgList::ArgList() {
-}
-
-ArgList::~ArgList() {
-}
-
-void ArgList::append(Arg *A) {
- Args.push_back(A);
-}
-
-void ArgList::eraseArg(OptSpecifier Id) {
- for (iterator it = begin(), ie = end(); it != ie; ) {
- if ((*it)->getOption().matches(Id)) {
- it = Args.erase(it);
- ie = end();
- } else {
- ++it;
- }
- }
-}
-
-Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
- // FIXME: Make search efficient?
- for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
- if ((*it)->getOption().matches(Id))
- return *it;
- return 0;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2, OptSpecifier Id3) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2) ||
- (*it)->getOption().matches(Id3)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2, OptSpecifier Id3,
- OptSpecifier Id4) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2) ||
- (*it)->getOption().matches(Id3) ||
- (*it)->getOption().matches(Id4)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2, OptSpecifier Id3,
- OptSpecifier Id4, OptSpecifier Id5) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2) ||
- (*it)->getOption().matches(Id3) ||
- (*it)->getOption().matches(Id4) ||
- (*it)->getOption().matches(Id5)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2, OptSpecifier Id3,
- OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2) ||
- (*it)->getOption().matches(Id3) ||
- (*it)->getOption().matches(Id4) ||
- (*it)->getOption().matches(Id5) ||
- (*it)->getOption().matches(Id6)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
- OptSpecifier Id2, OptSpecifier Id3,
- OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6, OptSpecifier Id7) const {
- Arg *Res = 0;
- for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id0) ||
- (*it)->getOption().matches(Id1) ||
- (*it)->getOption().matches(Id2) ||
- (*it)->getOption().matches(Id3) ||
- (*it)->getOption().matches(Id4) ||
- (*it)->getOption().matches(Id5) ||
- (*it)->getOption().matches(Id6) ||
- (*it)->getOption().matches(Id7)) {
- Res = *it;
- Res->claim();
- }
- }
-
- return Res;
-}
-
-bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
- if (Arg *A = getLastArg(Pos, Neg))
- return A->getOption().matches(Pos);
- return Default;
-}
-
-bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
- bool Default) const {
- if (Arg *A = getLastArg(Pos, PosAlias, Neg))
- return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);
- return Default;
-}
-
-StringRef ArgList::getLastArgValue(OptSpecifier Id,
- StringRef Default) const {
- if (Arg *A = getLastArg(Id))
- return A->getValue();
- return Default;
-}
-
-int ArgList::getLastArgIntValue(OptSpecifier Id, int Default,
- clang::DiagnosticsEngine *Diags) const {
- int Res = Default;
-
- if (Arg *A = getLastArg(Id)) {
- if (StringRef(A->getValue()).getAsInteger(10, Res)) {
- if (Diags)
- Diags->Report(diag::err_drv_invalid_int_value)
- << A->getAsString(*this) << A->getValue();
- }
- }
-
- return Res;
-}
-
-std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
- SmallVector<const char *, 16> Values;
- AddAllArgValues(Values, Id);
- return std::vector<std::string>(Values.begin(), Values.end());
-}
-
-void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
- if (Arg *A = getLastArg(Id)) {
- A->claim();
- A->render(*this, Output);
- }
-}
-
-void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1) const {
- if (Arg *A = getLastArg(Id0, Id1)) {
- A->claim();
- A->render(*this, Output);
- }
-}
-
-void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1, OptSpecifier Id2) const {
- for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
- ie = filtered_end(); it != ie; ++it) {
- (*it)->claim();
- (*it)->render(*this, Output);
- }
-}
-
-void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1, OptSpecifier Id2) const {
- for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
- ie = filtered_end(); it != ie; ++it) {
- (*it)->claim();
- for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
- Output.push_back((*it)->getValue(i));
- }
-}
-
-void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
- const char *Translation,
- bool Joined) const {
- for (arg_iterator it = filtered_begin(Id0),
- ie = filtered_end(); it != ie; ++it) {
- (*it)->claim();
-
- if (Joined) {
- Output.push_back(MakeArgString(StringRef(Translation) +
- (*it)->getValue(0)));
- } else {
- Output.push_back(Translation);
- Output.push_back((*it)->getValue(0));
- }
- }
-}
-
-void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
- for (arg_iterator it = filtered_begin(Id0),
- ie = filtered_end(); it != ie; ++it)
- (*it)->claim();
-}
-
-void ArgList::ClaimAllArgs() const {
- for (const_iterator it = begin(), ie = end(); it != ie; ++it)
- if (!(*it)->isClaimed())
- (*it)->claim();
-}
-
-const char *ArgList::MakeArgString(const Twine &T) const {
- SmallString<256> Str;
- T.toVector(Str);
- return MakeArgString(Str.str());
-}
-
-const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
- StringRef LHS,
- StringRef RHS) const {
- StringRef Cur = getArgString(Index);
- if (Cur.size() == LHS.size() + RHS.size() &&
- Cur.startswith(LHS) && Cur.endswith(RHS))
- return Cur.data();
-
- return MakeArgString(LHS + RHS);
-}
-
-void ArgList::dump() {
- llvm::errs() << "ArgList:";
- for (iterator it = begin(), ie = end(); it != ie; ++it) {
- llvm::errs() << " " << (*it)->getSpelling();
- }
- llvm::errs() << "\n";
-}
-
-//
-
-InputArgList::InputArgList(const char* const *ArgBegin,
- const char* const *ArgEnd)
- : NumInputArgStrings(ArgEnd - ArgBegin) {
- ArgStrings.append(ArgBegin, ArgEnd);
-}
-
-InputArgList::~InputArgList() {
- // An InputArgList always owns its arguments.
- for (iterator it = begin(), ie = end(); it != ie; ++it)
- delete *it;
-}
-
-unsigned InputArgList::MakeIndex(StringRef String0) const {
- unsigned Index = ArgStrings.size();
-
- // Tuck away so we have a reliable const char *.
- SynthesizedStrings.push_back(String0);
- ArgStrings.push_back(SynthesizedStrings.back().c_str());
-
- return Index;
-}
-
-unsigned InputArgList::MakeIndex(StringRef String0,
- StringRef String1) const {
- unsigned Index0 = MakeIndex(String0);
- unsigned Index1 = MakeIndex(String1);
- assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
- (void) Index1;
- return Index0;
-}
-
-const char *InputArgList::MakeArgString(StringRef Str) const {
- return getArgString(MakeIndex(Str));
-}
-
-//
-
-DerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
- : BaseArgs(_BaseArgs) {
-}
-
-DerivedArgList::~DerivedArgList() {
- // We only own the arguments we explicitly synthesized.
- for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
- it != ie; ++it)
- delete *it;
-}
-
-const char *DerivedArgList::MakeArgString(StringRef Str) const {
- return BaseArgs.MakeArgString(Str);
-}
-
-Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
- Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
- Twine(Opt.getName())),
- BaseArgs.MakeIndex(Opt.getName()), BaseArg);
- SynthesizedArgs.push_back(A);
- return A;
-}
-
-Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const {
- unsigned Index = BaseArgs.MakeIndex(Value);
- Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
- Twine(Opt.getName())),
- Index, BaseArgs.getArgString(Index), BaseArg);
- SynthesizedArgs.push_back(A);
- return A;
-}
-
-Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const {
- unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
- Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
- Twine(Opt.getName())),
- Index, BaseArgs.getArgString(Index + 1), BaseArg);
- SynthesizedArgs.push_back(A);
- return A;
-}
-
-Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
- StringRef Value) const {
- unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str());
- Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
- Twine(Opt.getName())), Index,
- BaseArgs.getArgString(Index) + Opt.getName().size(),
- BaseArg);
- SynthesizedArgs.push_back(A);
- return A;
-}
diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp
index 9048043..22180c9 100644
--- a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp
@@ -8,27 +8,25 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/CC1AsOptions.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Option.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
using namespace clang;
using namespace clang::driver;
-using namespace clang::driver::options;
+using namespace llvm::opt;
using namespace clang::driver::cc1asoptions;
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR)
+#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
#include "clang/Driver/CC1AsOptions.inc"
-#undef OPTION
#undef PREFIX
static const OptTable::Info CC1AsInfoTable[] = {
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) \
{ PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
- FLAGS, OPT_##GROUP, OPT_##ALIAS },
+ FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "clang/Driver/CC1AsOptions.inc"
+#undef OPTION
};
namespace {
@@ -36,8 +34,7 @@ namespace {
class CC1AsOptTable : public OptTable {
public:
CC1AsOptTable()
- : OptTable(CC1AsInfoTable,
- sizeof(CC1AsInfoTable) / sizeof(CC1AsInfoTable[0])) {}
+ : OptTable(CC1AsInfoTable, llvm::array_lengthof(CC1AsInfoTable)) {}
};
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
index 1bff4a3..f077fd6 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -9,20 +9,20 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Action.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Program.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <errno.h>
#include <sys/stat.h>
using namespace clang::driver;
using namespace clang;
+using namespace llvm::opt;
Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
InputArgList *_Args, DerivedArgList *_TranslatedArgs)
@@ -69,160 +69,34 @@ const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
return *Entry;
}
-void Compilation::PrintJob(raw_ostream &OS, const Job &J,
- const char *Terminator, bool Quote) const {
- if (const Command *C = dyn_cast<Command>(&J)) {
- OS << " \"" << C->getExecutable() << '"';
- for (ArgStringList::const_iterator it = C->getArguments().begin(),
- ie = C->getArguments().end(); it != ie; ++it) {
- OS << ' ';
- if (!Quote && !std::strpbrk(*it, " \"\\$")) {
- OS << *it;
- continue;
- }
-
- // Quote the argument and escape shell special characters; this isn't
- // really complete but is good enough.
- OS << '"';
- for (const char *s = *it; *s; ++s) {
- if (*s == '"' || *s == '\\' || *s == '$')
- OS << '\\';
- OS << *s;
- }
- OS << '"';
- }
- OS << Terminator;
- } else {
- const JobList *Jobs = cast<JobList>(&J);
- for (JobList::const_iterator
- it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
- PrintJob(OS, **it, Terminator, Quote);
- }
-}
-
-static bool skipArg(const char *Flag, bool &SkipNextArg) {
- StringRef FlagRef(Flag);
-
- // Assume we're going to see -Flag <Arg>.
- SkipNextArg = true;
-
- // These flags are all of the form -Flag <Arg> and are treated as two
- // arguments. Therefore, we need to skip the flag and the next argument.
- bool Res = llvm::StringSwitch<bool>(Flag)
- .Cases("-I", "-MF", "-MT", "-MQ", true)
- .Cases("-o", "-coverage-file", "-dependency-file", true)
- .Cases("-fdebug-compilation-dir", "-idirafter", true)
- .Cases("-include", "-include-pch", "-internal-isystem", true)
- .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
- .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
- .Cases("-resource-dir", "-serialize-diagnostic-file", true)
- .Case("-dwarf-debug-flags", true)
- .Default(false);
-
- // Match found.
- if (Res)
- return Res;
-
- // The remaining flags are treated as a single argument.
- SkipNextArg = false;
-
- // These flags are all of the form -Flag and have no second argument.
- Res = llvm::StringSwitch<bool>(Flag)
- .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
- .Case("-MMD", true)
- .Default(false);
-
- // Match found.
- if (Res)
- return Res;
-
- // These flags are treated as a single argument (e.g., -F<Dir>).
- if (FlagRef.startswith("-F") || FlagRef.startswith("-I"))
- return true;
-
- return false;
-}
-
-static bool quoteNextArg(const char *flag) {
- return llvm::StringSwitch<bool>(flag)
- .Case("-D", true)
- .Default(false);
-}
-
-void Compilation::PrintDiagnosticJob(raw_ostream &OS, const Job &J) const {
- if (const Command *C = dyn_cast<Command>(&J)) {
- OS << C->getExecutable();
- unsigned QuoteNextArg = 0;
- for (ArgStringList::const_iterator it = C->getArguments().begin(),
- ie = C->getArguments().end(); it != ie; ++it) {
-
- bool SkipNext;
- if (skipArg(*it, SkipNext)) {
- if (SkipNext) ++it;
- continue;
- }
-
- if (!QuoteNextArg)
- QuoteNextArg = quoteNextArg(*it) ? 2 : 0;
-
- OS << ' ';
-
- if (QuoteNextArg == 1)
- OS << '"';
-
- if (!std::strpbrk(*it, " \"\\$")) {
- OS << *it;
- } else {
- // Quote the argument and escape shell special characters; this isn't
- // really complete but is good enough.
- OS << '"';
- for (const char *s = *it; *s; ++s) {
- if (*s == '"' || *s == '\\' || *s == '$')
- OS << '\\';
- OS << *s;
- }
- OS << '"';
- }
+bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
+ std::string P(File);
- if (QuoteNextArg) {
- if (QuoteNextArg == 1)
- OS << '"';
- --QuoteNextArg;
- }
- }
- OS << '\n';
- } else {
- const JobList *Jobs = cast<JobList>(&J);
- for (JobList::const_iterator
- it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it)
- PrintDiagnosticJob(OS, **it);
- }
-}
+ // FIXME: Why are we trying to remove files that we have not created? For
+ // example we should only try to remove a temporary assembly file if
+ // "clang -cc1" succeed in writing it. Was this a workaround for when
+ // clang was writing directly to a .s file and sometimes leaving it behind
+ // during a failure?
-bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
- llvm::sys::Path P(File);
- std::string Error;
+ // FIXME: If this is necessary, we can still try to split
+ // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
+ // duplicated stat from is_regular_file.
// Don't try to remove files which we don't have write access to (but may be
// able to remove), or non-regular files. Underlying tools may have
// intentionally not overwritten them.
- if (!P.canWrite() || !P.isRegularFile())
+ if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
return true;
- if (P.eraseFromDisk(false, &Error)) {
- // Failure is only failure if the file exists and is "regular". There is
- // a race condition here due to the limited interface of
- // llvm::sys::Path, we want to know if the removal gave ENOENT.
+ if (llvm::error_code EC = llvm::sys::fs::remove(File)) {
+ // Failure is only failure if the file exists and is "regular". We checked
+ // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
+ // so we don't need to check again.
- // FIXME: Grumble, P.exists() is broken. PR3837.
- struct stat buf;
- if (::stat(P.c_str(), &buf) == 0 ? (buf.st_mode & S_IFMT) == S_IFREG :
- (errno != ENOENT)) {
- if (IssueErrors)
- getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
- << Error;
- return false;
- }
+ if (IssueErrors)
+ getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+ << EC.message();
+ return false;
}
return true;
}
@@ -254,13 +128,7 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files,
int Compilation::ExecuteCommand(const Command &C,
const Command *&FailingCommand) const {
- llvm::sys::Path Prog(C.getExecutable());
- const char **Argv = new const char*[C.getArguments().size() + 2];
- Argv[0] = C.getExecutable();
- std::copy(C.getArguments().begin(), C.getArguments().end(), Argv+1);
- Argv[C.getArguments().size() + 1] = 0;
-
- if ((getDriver().CCCEcho || getDriver().CCPrintOptions ||
+ if ((getDriver().CCPrintOptions ||
getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
raw_ostream *OS = &llvm::errs();
@@ -268,9 +136,8 @@ int Compilation::ExecuteCommand(const Command &C,
// output stream.
if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
std::string Error;
- OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename,
- Error,
- llvm::raw_fd_ostream::F_Append);
+ OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, Error,
+ llvm::sys::fs::F_Append);
if (!Error.empty()) {
getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
<< Error;
@@ -283,7 +150,7 @@ int Compilation::ExecuteCommand(const Command &C,
if (getDriver().CCPrintOptions)
*OS << "[Logging clang options]";
- PrintJob(*OS, C, "\n", /*Quote=*/getDriver().CCPrintOptions);
+ C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
if (OS != &llvm::errs())
delete OS;
@@ -291,11 +158,7 @@ int Compilation::ExecuteCommand(const Command &C,
std::string Error;
bool ExecutionFailed;
- int Res =
- llvm::sys::Program::ExecuteAndWait(Prog, Argv,
- /*env*/0, Redirects,
- /*secondsToWait*/0, /*memoryLimit*/0,
- &Error, &ExecutionFailed);
+ int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
if (!Error.empty()) {
assert(Res && "Error string set with 0 result code!");
getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
@@ -304,7 +167,6 @@ int Compilation::ExecuteCommand(const Command &C,
if (Res)
FailingCommand = &C;
- delete[] Argv;
return ExecutionFailed ? 1 : Res;
}
@@ -370,9 +232,10 @@ void Compilation::initCompilationForDiagnostics() {
TranslatedArgs->ClaimAllArgs();
// Redirect stdout/stderr to /dev/null.
- Redirects = new const llvm::sys::Path*[3]();
- Redirects[1] = new const llvm::sys::Path();
- Redirects[2] = new const llvm::sys::Path();
+ Redirects = new const StringRef*[3]();
+ Redirects[0] = 0;
+ Redirects[1] = new const StringRef();
+ Redirects[2] = new const StringRef();
}
StringRef Compilation::getSysRoot() const {
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
index b541a55..49beb93 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -12,19 +12,22 @@
#include "ToolChains.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Option/OptSpecifier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -40,20 +43,21 @@
using namespace clang::driver;
using namespace clang;
+using namespace llvm::opt;
Driver::Driver(StringRef ClangExecutable,
StringRef DefaultTargetTriple,
StringRef DefaultImageName,
DiagnosticsEngine &Diags)
- : Opts(createDriverOptTable()), Diags(Diags),
+ : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
DefaultImageName(DefaultImageName),
DriverTitle("clang LLVM compiler"),
CCPrintOptionsFilename(0), CCPrintHeadersFilename(0),
- CCLogDiagnosticsFilename(0), CCCIsCXX(false),
- CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false),
- CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+ CCLogDiagnosticsFilename(0),
+ CCCPrintBindings(false),
+ CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
CCCUsePCH(true), SuppressMissingInputWarning(false) {
@@ -79,11 +83,43 @@ Driver::~Driver() {
delete I->second;
}
+void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
+ const std::string OptName =
+ getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+
+ for (size_t I = 0, E = Args.size(); I != E; ++I) {
+ const StringRef Arg = Args[I];
+ if (!Arg.startswith(OptName))
+ continue;
+
+ const StringRef Value = Arg.drop_front(OptName.size());
+ const unsigned M = llvm::StringSwitch<unsigned>(Value)
+ .Case("gcc", GCCMode)
+ .Case("g++", GXXMode)
+ .Case("cpp", CPPMode)
+ .Case("cl", CLMode)
+ .Default(~0U);
+
+ if (M != ~0U)
+ Mode = static_cast<DriverMode>(M);
+ else
+ Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
+ }
+}
+
InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
+
+ unsigned IncludedFlagsBitmask;
+ unsigned ExcludedFlagsBitmask;
+ llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ getIncludeExcludeOptionFlagMasks();
+
unsigned MissingArgIndex, MissingArgCount;
InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(),
- MissingArgIndex, MissingArgCount);
+ MissingArgIndex, MissingArgCount,
+ IncludedFlagsBitmask,
+ ExcludedFlagsBitmask);
// Check for missing argument error.
if (MissingArgCount)
@@ -107,6 +143,11 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
}
}
+ for (arg_iterator it = Args->filtered_begin(options::OPT_UNKNOWN),
+ ie = Args->filtered_end(); it != ie; ++it) {
+ Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
+ }
+
return Args;
}
@@ -119,7 +160,7 @@ const {
phases::ID FinalPhase;
// -{E,M,MM} only run the preprocessor.
- if (CCCIsCPP ||
+ if (CCCIsCPP() ||
(PhaseArg = DAL.getLastArg(options::OPT_E)) ||
(PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) {
FinalPhase = phases::Preprocess;
@@ -150,6 +191,14 @@ const {
return FinalPhase;
}
+static Arg* MakeInputArg(const DerivedArgList &Args, OptTable *Opts,
+ StringRef Value) {
+ Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value,
+ Args.getBaseArgs().MakeIndex(Value), Value.data());
+ A->claim();
+ return A;
+}
+
DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DerivedArgList *DAL = new DerivedArgList(Args);
@@ -215,6 +264,14 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
}
}
+ // Pick up inputs via the -- option.
+ if (A->getOption().matches(options::OPT__DASH_DASH)) {
+ A->claim();
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
+ DAL->append(MakeInputArg(*DAL, Opts, A->getValue(i)));
+ continue;
+ }
+
DAL->append(*it);
}
@@ -241,16 +298,20 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
StringRef CompilerPath = env;
while (!CompilerPath.empty()) {
std::pair<StringRef, StringRef> Split
- = CompilerPath.split(llvm::sys::PathSeparator);
+ = CompilerPath.split(llvm::sys::EnvPathSeparator);
PrefixDirs.push_back(Split.first);
CompilerPath = Split.second;
}
}
+ // We look for the driver mode option early, because the mode can affect
+ // how other options are parsed.
+ ParseDriverMode(ArgList.slice(1));
+
// FIXME: What are we going to do with -V and -b?
// FIXME: This stuff needs to go into the Compilation, not the driver.
- bool CCCPrintOptions, CCCPrintActions;
+ bool CCCPrintActions;
InputArgList *Args = ParseArgStrings(ArgList.slice(1));
@@ -266,17 +327,20 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// 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.
- CCCPrintOptions = Args->hasArg(options::OPT_ccc_print_options);
CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases);
CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings);
- CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX;
- CCCEcho = Args->hasArg(options::OPT_ccc_echo);
if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name))
CCCGenericGCCName = A->getValue();
CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch,
options::OPT_ccc_pch_is_pth);
// FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
+ if (IsCLMode()) {
+ // clang-cl targets Win32.
+ llvm::Triple T(DefaultTargetTriple);
+ T.setOSName(llvm::Triple::getOSTypeName(llvm::Triple::Win32));
+ DefaultTargetTriple = T.str();
+ }
if (const Arg *A = Args->getLastArg(options::OPT_target))
DefaultTargetTriple = A->getValue();
if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
@@ -289,6 +353,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
}
if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ))
SysRoot = A->getValue();
+ if (const Arg *A = Args->getLastArg(options::OPT__dyld_prefix_EQ))
+ DyldPrefix = A->getValue();
if (Args->hasArg(options::OPT_nostdlib))
UseStdLib = false;
@@ -304,18 +370,12 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// The compilation takes ownership of Args.
Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs);
- // FIXME: This behavior shouldn't be here.
- if (CCCPrintOptions) {
- PrintOptions(C->getInputArgs());
- return C;
- }
-
if (!HandleImmediateArgs(*C))
return C;
// Construct the list of inputs.
InputList Inputs;
- BuildInputs(C->getDefaultToolChain(), C->getArgs(), Inputs);
+ BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
// Construct the list of abstract actions to perform for this compilation. On
// Darwin target OSes this uses the driver-driver and universal actions.
@@ -357,7 +417,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
"crash backtrace, preprocessed source, and associated run script.";
// Suppress driver output and emit preprocessor output to temp file.
- CCCIsCPP = true;
+ Mode = CPPMode;
CCGenDiagnostics = true;
C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes));
@@ -365,11 +425,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
std::string Cmd;
llvm::raw_string_ostream OS(Cmd);
if (FailingCommand)
- C.PrintDiagnosticJob(OS, *FailingCommand);
+ FailingCommand->Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true);
else
// Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an
// associated FailingCommand, so just pass all jobs.
- C.PrintDiagnosticJob(OS, C.getJobs());
+ C.getJobs().Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true);
OS.flush();
// Keep track of whether we produce any errors while trying to produce
@@ -463,9 +523,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
std::string Err;
std::string Script = StringRef(*it).rsplit('.').first;
Script += ".sh";
- llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err,
- llvm::raw_fd_ostream::F_Excl |
- llvm::raw_fd_ostream::F_Binary);
+ llvm::raw_fd_ostream ScriptOS(
+ Script.c_str(), Err, llvm::sys::fs::F_Excl | llvm::sys::fs::F_Binary);
if (!Err.empty()) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating run script: " + Script + " " + Err;
@@ -503,7 +562,7 @@ int Driver::ExecuteCompilation(const Compilation &C,
SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const {
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
- C.PrintJob(llvm::errs(), C.getJobs(), "\n", true);
+ C.getJobs().Print(llvm::errs(), "\n", true);
return 0;
}
@@ -559,28 +618,18 @@ int Driver::ExecuteCompilation(const Compilation &C,
return 0;
}
-void Driver::PrintOptions(const ArgList &Args) const {
- unsigned i = 0;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it, ++i) {
- Arg *A = *it;
- llvm::errs() << "Option " << i << " - "
- << "Name: \"" << A->getOption().getPrefixedName() << "\", "
- << "Values: {";
- for (unsigned j = 0; j < A->getNumValues(); ++j) {
- if (j)
- llvm::errs() << ", ";
- llvm::errs() << '"' << A->getValue(j) << '"';
- }
- llvm::errs() << "}\n";
- }
-}
-
void Driver::PrintHelp(bool ShowHidden) const {
+ unsigned IncludedFlagsBitmask;
+ unsigned ExcludedFlagsBitmask;
+ llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ getIncludeExcludeOptionFlagMasks();
+
+ ExcludedFlagsBitmask |= options::NoDriverOption;
+ if (!ShowHidden)
+ ExcludedFlagsBitmask |= HelpHidden;
+
getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
- /*Include*/0,
- /*Exclude*/options::NoDriverOption |
- (ShowHidden ? 0 : options::HelpHidden));
+ IncludedFlagsBitmask, ExcludedFlagsBitmask);
}
void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
@@ -649,6 +698,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
const ToolChain &TC = C.getDefaultToolChain();
+
+ if (C.getArgs().hasArg(options::OPT_v))
+ TC.printVerboseInfo(llvm::errs());
+
if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
llvm::outs() << "programs: =";
for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(),
@@ -707,6 +760,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
case llvm::Triple::ppc64:
llvm::outs() << "ppc64;@m64" << "\n";
break;
+
+ case llvm::Triple::ppc64le:
+ llvm::outs() << "ppc64le;@m64" << "\n";
+ break;
}
return false;
}
@@ -729,6 +786,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
case llvm::Triple::ppc64:
llvm::outs() << "ppc64" << "\n";
break;
+
+ case llvm::Triple::ppc64le:
+ llvm::outs() << "ppc64le" << "\n";
+ break;
}
return false;
}
@@ -790,7 +851,7 @@ static bool ContainsCompileOrAssembleAction(const Action *A) {
}
void Driver::BuildUniversalActions(const ToolChain &TC,
- const DerivedArgList &Args,
+ DerivedArgList &Args,
const InputList &BAInputs,
ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
@@ -885,6 +946,33 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
}
}
+/// \brief Check that the file referenced by Value exists. If it doesn't,
+/// issue a diagnostic and return false.
+static bool DiagnoseInputExistance(const Driver &D, const DerivedArgList &Args,
+ StringRef Value) {
+ if (!D.getCheckInputsExist())
+ return true;
+
+ // stdin always exists.
+ if (Value == "-")
+ return true;
+
+ SmallString<64> Path(Value);
+ if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) {
+ if (!llvm::sys::path::is_absolute(Path.str())) {
+ SmallString<64> Directory(WorkDir->getValue());
+ llvm::sys::path::append(Directory, Value);
+ Path.assign(Directory);
+ }
+ }
+
+ if (llvm::sys::fs::exists(Twine(Path)))
+ return true;
+
+ D.Diag(clang::diag::err_drv_no_such_file) << Path.str();
+ return false;
+}
+
// Construct a the list of inputs and their types.
void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
InputList &Inputs) const {
@@ -894,6 +982,31 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
types::ID InputType = types::TY_Nothing;
Arg *InputTypeArg = 0;
+ // The last /TC or /TP option sets the input type to C or C++ globally.
+ if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC,
+ options::OPT__SLASH_TP)) {
+ InputTypeArg = TCTP;
+ InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
+ ? types::TY_C : types::TY_CXX;
+
+ arg_iterator it = Args.filtered_begin(options::OPT__SLASH_TC,
+ options::OPT__SLASH_TP);
+ const arg_iterator ie = Args.filtered_end();
+ Arg *Previous = *it++;
+ bool ShowNote = false;
+ while (it != ie) {
+ Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Previous->getSpelling() << (*it)->getSpelling();
+ Previous = *it++;
+ ShowNote = true;
+ }
+ if (ShowNote)
+ Diag(clang::diag::note_drv_t_option_is_global);
+
+ // No driver mode exposes -x and /TC or /TP; we don't support mixing them.
+ assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed");
+ }
+
for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
it != ie; ++it) {
Arg *A = *it;
@@ -915,7 +1028,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
//
// Otherwise emit an error but still use a valid type to avoid
// spurious errors (e.g., no inputs).
- if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP)
+ if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
Diag(clang::diag::err_drv_unknown_stdin_type);
Ty = types::TY_C;
} else {
@@ -927,7 +1040,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
Ty = TC.LookupTypeForExtension(Ext + 1);
if (Ty == types::TY_INVALID) {
- if (CCCIsCPP)
+ if (CCCIsCPP())
Ty = types::TY_C;
else
Ty = types::TY_Object;
@@ -935,7 +1048,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
// If the driver is invoked as C++ compiler (like clang++ or c++) it
// should autodetect some input files as C++ for g++ compatibility.
- if (CCCIsCXX) {
+ if (CCCIsCXX()) {
types::ID OldTy = Ty;
Ty = types::lookupCXXTypeForCType(Ty);
@@ -962,25 +1075,23 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
Ty = InputType;
}
- // Check that the file exists, if enabled.
- if (CheckInputsExist && memcmp(Value, "-", 2) != 0) {
- SmallString<64> Path(Value);
- if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) {
- if (!llvm::sys::path::is_absolute(Path.str())) {
- SmallString<64> Directory(WorkDir->getValue());
- llvm::sys::path::append(Directory, Value);
- Path.assign(Directory);
- }
- }
-
- bool exists = false;
- if (llvm::sys::fs::exists(Path.c_str(), exists) || !exists)
- Diag(clang::diag::err_drv_no_such_file) << Path.str();
- else
- Inputs.push_back(std::make_pair(Ty, A));
- } else
+ if (DiagnoseInputExistance(*this, Args, Value))
Inputs.push_back(std::make_pair(Ty, A));
+ } else if (A->getOption().matches(options::OPT__SLASH_Tc)) {
+ StringRef Value = A->getValue();
+ if (DiagnoseInputExistance(*this, Args, Value)) {
+ Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
+ Inputs.push_back(std::make_pair(types::TY_C, InputArg));
+ }
+ A->claim();
+ } else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
+ StringRef Value = A->getValue();
+ if (DiagnoseInputExistance(*this, Args, Value)) {
+ Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
+ Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
+ }
+ A->claim();
} else if (A->getOption().hasFlag(options::LinkerInput)) {
// Just treat as object type, we could make a special type for this if
// necessary.
@@ -1000,17 +1111,15 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
}
}
}
- if (CCCIsCPP && Inputs.empty()) {
+ if (CCCIsCPP() && Inputs.empty()) {
// If called as standalone preprocessor, stdin is processed
// if no other input is present.
- unsigned Index = Args.getBaseArgs().MakeIndex("-");
- Arg *A = Opts->ParseOneArg(Args, Index);
- A->claim();
+ Arg *A = MakeInputArg(Args, Opts, "-");
Inputs.push_back(std::make_pair(types::TY_C, A));
}
}
-void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args,
+void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
const InputList &Inputs, ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
@@ -1022,11 +1131,50 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args,
Arg *FinalPhaseArg;
phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
+ if (FinalPhase == phases::Link && Args.hasArg(options::OPT_emit_llvm)) {
+ Diag(clang::diag::err_drv_emit_llvm_link);
+ }
+
// 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);
+ // Diagnose misuse of /Fo.
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) {
+ StringRef V = A->getValue();
+ if (V.empty()) {
+ // It has to have a value.
+ Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
+ Args.eraseArg(options::OPT__SLASH_Fo);
+ } else if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) {
+ // Check whether /Fo tries to name an output file for multiple inputs.
+ Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
+ << A->getSpelling() << V;
+ Args.eraseArg(options::OPT__SLASH_Fo);
+ }
+ }
+
+ // Diagnose misuse of /Fa.
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) {
+ StringRef V = A->getValue();
+ if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) {
+ // Check whether /Fa tries to name an asm file for multiple inputs.
+ Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
+ << A->getSpelling() << V;
+ Args.eraseArg(options::OPT__SLASH_Fa);
+ }
+ }
+
+ // Diagnose misuse of /Fe.
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fe)) {
+ if (A->getValue()[0] == '\0') {
+ // It has to have a value.
+ Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
+ Args.eraseArg(options::OPT__SLASH_Fe);
+ }
+ }
+
// Construct the actions to perform.
ActionList LinkerInputs;
ActionList SplitInputs;
@@ -1051,7 +1199,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args,
// Special case when final phase determined by binary name, rather than
// by a command-line argument with a corresponding Arg.
- if (CCCIsCPP)
+ if (CCCIsCPP())
Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
<< InputArg->getAsString(Args)
<< getPhaseName(InitialPhase);
@@ -1075,7 +1223,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args,
// Build the pipeline for this file.
OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
- for (llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>::iterator
+ for (SmallVectorImpl<phases::ID>::iterator
i = PL.begin(), e = PL.end(); i != e; ++i) {
phases::ID Phase = *i;
@@ -1113,8 +1261,13 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args,
// If we are linking, claim any options which are obviously only used for
// compilation.
- if (FinalPhase == phases::Link && PL.size() == 1)
+ if (FinalPhase == phases::Link && PL.size() == 1) {
Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
+ Args.ClaimAllArgs(options::OPT_cl_compile_Group);
+ }
+
+ // Claim ignored clang-cl options.
+ Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
}
Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
@@ -1165,6 +1318,10 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return new CompileJobAction(Input, Output);
+ } else if (Args.hasArg(options::OPT_emit_llvm)) {
+ types::ID Output =
+ Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
+ return new CompileJobAction(Input, Output);
} else {
return new CompileJobAction(Input, types::TY_PP_Asm);
}
@@ -1177,15 +1334,9 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
}
bool Driver::IsUsingLTO(const ArgList &Args) const {
- // Check for -emit-llvm or -flto.
- if (Args.hasArg(options::OPT_emit_llvm) ||
- Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false))
+ if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false))
return true;
- // Check for -O4.
- if (const Arg *A = Args.getLastArg(options::OPT_O_Group))
- return A->getOption().matches(options::OPT_O4);
-
return false;
}
@@ -1256,6 +1407,9 @@ void Driver::BuildJobs(Compilation &C) const {
// Claim -### here.
(void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
+ // Claim --driver-mode, it was handled earlier.
+ (void) C.getArgs().hasArg(options::OPT_driver_mode);
+
for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
it != ie; ++it) {
Arg *A = *it;
@@ -1302,6 +1456,8 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
if (TC->useIntegratedAs() &&
!C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
isa<AssembleJobAction>(JA) &&
Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
const Tool *Compiler =
@@ -1424,6 +1580,38 @@ void Driver::BuildJobsForAction(Compilation &C,
}
}
+/// \brief Create output filename based on ArgValue, which could either be a
+/// full filename, filename without extension, or a directory. If ArgValue
+/// does not provide a filename, then use BaseName, and use the extension
+/// suitable for FileType.
+static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
+ StringRef BaseName, types::ID FileType) {
+ SmallString<128> Filename = ArgValue;
+
+ if (ArgValue.empty()) {
+ // If the argument is empty, output to BaseName in the current dir.
+ Filename = BaseName;
+ } else if (llvm::sys::path::is_separator(Filename.back())) {
+ // If the argument is a directory, output to BaseName in that dir.
+ llvm::sys::path::append(Filename, BaseName);
+ }
+
+ if (!llvm::sys::path::has_extension(ArgValue)) {
+ // If the argument didn't provide an extension, then set it.
+ const char *Extension = types::getTypeTempSuffix(FileType, true);
+
+ if (FileType == types::TY_Image &&
+ Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) {
+ // The output file is a dll.
+ Extension = "dll";
+ }
+
+ llvm::sys::path::replace_extension(Filename, Extension);
+ }
+
+ return Args.MakeArgString(Filename.c_str());
+}
+
const char *Driver::GetNamedOutputPath(Compilation &C,
const JobAction &JA,
const char *BaseInput,
@@ -1443,13 +1631,26 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
(isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
return "-";
+ // Is this the assembly listing for /FA?
+ if (JA.getType() == types::TY_PP_Asm &&
+ (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
+ C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
+ // Use /Fa and the input filename to determine the asm file name.
+ StringRef BaseName = llvm::sys::path::filename(BaseInput);
+ StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
+ return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName,
+ JA.getType()), &JA);
+ }
+
// Output to a temporary file?
- if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) ||
+ if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
CCGenDiagnostics) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName =
- GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType()));
+ GetTemporaryPath(Split.first,
+ types::getTypeTempSuffix(JA.getType(), IsCLMode()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
@@ -1464,8 +1665,25 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
// Determine what the derived output name should be.
const char *NamedOutput;
- if (JA.getType() == types::TY_Image) {
- if (MultipleArchs && BoundArch) {
+
+ if (JA.getType() == types::TY_Object &&
+ C.getArgs().hasArg(options::OPT__SLASH_Fo)) {
+ // The /Fo flag decides the object filename.
+ StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue();
+ NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
+ types::TY_Object);
+ } else if (JA.getType() == types::TY_Image &&
+ C.getArgs().hasArg(options::OPT__SLASH_Fe)) {
+ // The /Fe flag names the linked file.
+ StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue();
+ NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
+ types::TY_Image);
+ } else if (JA.getType() == types::TY_Image) {
+ if (IsCLMode()) {
+ // clang-cl uses BaseName for the executable name.
+ NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
+ types::TY_Image);
+ } else if (MultipleArchs && BoundArch) {
SmallString<128> Output(DefaultImageName.c_str());
Output += "-";
Output.append(BoundArch);
@@ -1473,7 +1691,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
} else
NamedOutput = DefaultImageName.c_str();
} else {
- const char *Suffix = types::getTypeTempSuffix(JA.getType());
+ const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
assert(Suffix && "All types used for output should have a suffix.");
std::string::size_type End = std::string::npos;
@@ -1504,7 +1722,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName =
- GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType()));
+ GetTemporaryPath(Split.first,
+ types::getTypeTempSuffix(JA.getType(), IsCLMode()));
return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
}
}
@@ -1532,17 +1751,15 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
continue;
if (Dir[0] == '=')
Dir = SysRoot + Dir.substr(1);
- llvm::sys::Path P(Dir);
- P.appendComponent(Name);
- bool Exists;
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ SmallString<128> P(Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
return P.str();
}
- llvm::sys::Path P(ResourceDir);
- P.appendComponent(Name);
- bool Exists;
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ SmallString<128> P(ResourceDir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
return P.str();
const ToolChain::path_list &List = TC.getFilePaths();
@@ -1553,10 +1770,9 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
continue;
if (Dir[0] == '=')
Dir = SysRoot + Dir.substr(1);
- llvm::sys::Path P(Dir);
- P.appendComponent(Name);
- bool Exists;
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ SmallString<128> P(Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
return P.str();
}
@@ -1571,69 +1787,58 @@ std::string Driver::GetProgramPath(const char *Name,
// attempting to use this prefix when looking for program paths.
for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
ie = PrefixDirs.end(); it != ie; ++it) {
- bool IsDirectory;
- if (!llvm::sys::fs::is_directory(*it, IsDirectory) && IsDirectory) {
- llvm::sys::Path P(*it);
- P.appendComponent(TargetSpecificExecutable);
- if (P.canExecute()) return P.str();
- P.eraseComponent();
- P.appendComponent(Name);
- if (P.canExecute()) return P.str();
+ if (llvm::sys::fs::is_directory(*it)) {
+ SmallString<128> P(*it);
+ llvm::sys::path::append(P, TargetSpecificExecutable);
+ if (llvm::sys::fs::can_execute(Twine(P)))
+ return P.str();
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::can_execute(Twine(P)))
+ return P.str();
} else {
- llvm::sys::Path P(*it + Name);
- if (P.canExecute()) return P.str();
+ SmallString<128> P(*it + Name);
+ if (llvm::sys::fs::can_execute(Twine(P)))
+ return P.str();
}
}
const ToolChain::path_list &List = TC.getProgramPaths();
for (ToolChain::path_list::const_iterator
it = List.begin(), ie = List.end(); it != ie; ++it) {
- llvm::sys::Path P(*it);
- P.appendComponent(TargetSpecificExecutable);
- if (P.canExecute()) return P.str();
- P.eraseComponent();
- P.appendComponent(Name);
- if (P.canExecute()) return P.str();
+ SmallString<128> P(*it);
+ llvm::sys::path::append(P, TargetSpecificExecutable);
+ if (llvm::sys::fs::can_execute(Twine(P)))
+ return P.str();
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::can_execute(Twine(P)))
+ return P.str();
}
// If all else failed, search the path.
- llvm::sys::Path
- P(llvm::sys::Program::FindProgramByName(TargetSpecificExecutable));
+ std::string P(llvm::sys::FindProgramByName(TargetSpecificExecutable));
if (!P.empty())
- return P.str();
+ return P;
- P = llvm::sys::Path(llvm::sys::Program::FindProgramByName(Name));
+ P = llvm::sys::FindProgramByName(Name);
if (!P.empty())
- return P.str();
+ return P;
return Name;
}
std::string Driver::GetTemporaryPath(StringRef Prefix, 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).
- std::string Error;
- const char *TmpDir = ::getenv("TMPDIR");
- if (!TmpDir)
- TmpDir = ::getenv("TEMP");
- if (!TmpDir)
- TmpDir = ::getenv("TMP");
- if (!TmpDir)
- TmpDir = "/tmp";
- llvm::sys::Path P(TmpDir);
- P.appendComponent(Prefix);
- if (P.makeUnique(false, &Error)) {
- Diag(clang::diag::err_unable_to_make_temp) << Error;
+ SmallString<128> Path;
+ llvm::error_code EC =
+ llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
+ if (EC) {
+ Diag(clang::diag::err_unable_to_make_temp) << EC.message();
return "";
}
- // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837.
- P.eraseFromDisk(false, 0);
-
- if (Suffix)
- P.appendSuffix(Suffix);
- return P.str();
+ return Path.str();
}
/// \brief Compute target triple from args.
@@ -1772,6 +1977,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Hexagon_TC(*this, Target, Args);
break;
}
+ if (Target.getArch() == llvm::Triple::xcore) {
+ TC = new toolchains::XCore(*this, Target, Args);
+ break;
+ }
TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
}
@@ -1831,3 +2040,18 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
HadExtra = true;
return true;
}
+
+std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const {
+ unsigned IncludedFlagsBitmask = 0;
+ unsigned ExcludedFlagsBitmask = options::NoDriverOption;
+
+ if (Mode == CLMode) {
+ // Include CL and Core options.
+ IncludedFlagsBitmask |= options::CLOption;
+ IncludedFlagsBitmask |= options::CoreOption;
+ } else {
+ ExcludedFlagsBitmask |= options::CLOption;
+ }
+
+ return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
index 3925b8a..6ff1cba 100644
--- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
@@ -8,26 +8,25 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Options.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Option.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
using namespace clang::driver;
using namespace clang::driver::options;
+using namespace llvm::opt;
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR)
+#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE;
#include "clang/Driver/Options.inc"
-#undef OPTION
#undef PREFIX
static const OptTable::Info InfoTable[] = {
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR) \
{ PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
- FLAGS, OPT_##GROUP, OPT_##ALIAS },
+ FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "clang/Driver/Options.inc"
+#undef OPTION
};
namespace {
@@ -35,7 +34,7 @@ namespace {
class DriverOptTable : public OptTable {
public:
DriverOptTable()
- : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
+ : OptTable(InfoTable, llvm::array_lengthof(InfoTable)) {}
};
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
index a243d32..4eedd22 100644
--- a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
+++ b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
@@ -10,8 +10,8 @@
#ifndef CLANG_LIB_DRIVER_INPUTINFO_H_
#define CLANG_LIB_DRIVER_INPUTINFO_H_
-#include "clang/Driver/Arg.h"
#include "clang/Driver/Types.h"
+#include "llvm/Option/Arg.h"
#include <cassert>
#include <string>
@@ -35,7 +35,7 @@ class InputInfo {
union {
const char *Filename;
- const Arg *InputArg;
+ const llvm::opt::Arg *InputArg;
} Data;
Class Kind;
types::ID Type;
@@ -50,8 +50,9 @@ public:
: Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
Data.Filename = _Filename;
}
- InputInfo(const Arg *_InputArg, types::ID _Type, const char *_BaseInput)
- : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
+ InputInfo(const llvm::opt::Arg *_InputArg, types::ID _Type,
+ const char *_BaseInput)
+ : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
Data.InputArg = _InputArg;
}
@@ -65,7 +66,7 @@ public:
assert(isFilename() && "Invalid accessor.");
return Data.Filename;
}
- const Arg &getInputArg() const {
+ const llvm::opt::Arg &getInputArg() const {
assert(isInputArg() && "Invalid accessor.");
return *Data.InputArg;
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
index 8c46705..ee68e6f 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -9,18 +9,158 @@
#include "clang/Driver/Job.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
#include <cassert>
using namespace clang::driver;
+using llvm::raw_ostream;
+using llvm::StringRef;
Job::~Job() {}
-void Command::anchor() {}
-
Command::Command(const Action &_Source, const Tool &_Creator,
- const char *_Executable, const ArgStringList &_Arguments)
- : Job(CommandClass), Source(_Source), Creator(_Creator),
- Executable(_Executable), Arguments(_Arguments)
-{
+ const char *_Executable,
+ const ArgStringList &_Arguments)
+ : Job(CommandClass), Source(_Source), Creator(_Creator),
+ Executable(_Executable), Arguments(_Arguments) {}
+
+static int skipArgs(const char *Flag) {
+ // These flags are all of the form -Flag <Arg> and are treated as two
+ // arguments. Therefore, we need to skip the flag and the next argument.
+ bool Res = llvm::StringSwitch<bool>(Flag)
+ .Cases("-I", "-MF", "-MT", "-MQ", true)
+ .Cases("-o", "-coverage-file", "-dependency-file", true)
+ .Cases("-fdebug-compilation-dir", "-idirafter", true)
+ .Cases("-include", "-include-pch", "-internal-isystem", true)
+ .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
+ .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true)
+ .Cases("-resource-dir", "-serialize-diagnostic-file", true)
+ .Case("-dwarf-debug-flags", true)
+ .Default(false);
+
+ // Match found.
+ if (Res)
+ return 2;
+
+ // The remaining flags are treated as a single argument.
+
+ // These flags are all of the form -Flag and have no second argument.
+ Res = llvm::StringSwitch<bool>(Flag)
+ .Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
+ .Case("-MMD", true)
+ .Default(false);
+
+ // Match found.
+ if (Res)
+ return 1;
+
+ // These flags are treated as a single argument (e.g., -F<Dir>).
+ StringRef FlagRef(Flag);
+ if (FlagRef.startswith("-F") || FlagRef.startswith("-I"))
+ return 1;
+
+ return 0;
+}
+
+static bool quoteNextArg(const char *flag) {
+ return llvm::StringSwitch<bool>(flag)
+ .Case("-D", true)
+ .Default(false);
+}
+
+static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) {
+ const bool Escape = std::strpbrk(Arg, "\"\\$");
+
+ if (!Quote && !Escape) {
+ OS << Arg;
+ return;
+ }
+
+ // Quote and escape. This isn't really complete, but good enough.
+ OS << '"';
+ while (const char c = *Arg++) {
+ if (c == '"' || c == '\\' || c == '$')
+ OS << '\\';
+ OS << c;
+ }
+ OS << '"';
+}
+
+void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
+ bool CrashReport) const {
+ OS << " \"" << Executable << '"';
+
+ for (size_t i = 0, e = Arguments.size(); i < e; ++i) {
+ const char *const Arg = Arguments[i];
+
+ if (CrashReport) {
+ if (int Skip = skipArgs(Arg)) {
+ i += Skip - 1;
+ continue;
+ }
+ }
+
+ OS << ' ';
+ PrintArg(OS, Arg, Quote);
+
+ if (CrashReport && quoteNextArg(Arg) && i + 1 < e) {
+ OS << ' ';
+ PrintArg(OS, Arguments[++i], true);
+ }
+ }
+ OS << Terminator;
+}
+
+int Command::Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const {
+ SmallVector<const char*, 128> Argv;
+ Argv.push_back(Executable);
+ for (size_t i = 0, e = Arguments.size(); i != e; ++i)
+ Argv.push_back(Arguments[i]);
+ Argv.push_back(0);
+
+ return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ 0,
+ Redirects, /*secondsToWait*/ 0,
+ /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
+}
+
+FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
+ const char *Executable_,
+ const ArgStringList &Arguments_,
+ Command *Fallback_)
+ : Command(Source_, Creator_, Executable_, Arguments_), Fallback(Fallback_) {
+}
+
+void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport) const {
+ Command::Print(OS, "", Quote, CrashReport);
+ OS << " ||";
+ Fallback->Print(OS, Terminator, Quote, CrashReport);
+}
+
+static bool ShouldFallback(int ExitCode) {
+ // FIXME: We really just want to fall back for internal errors, such
+ // as when some symbol cannot be mangled, when we should be able to
+ // parse something but can't, etc.
+ return ExitCode != 0;
+}
+
+int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const {
+ int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
+ if (!ShouldFallback(PrimaryStatus))
+ return PrimaryStatus;
+
+ // Clear ExecutionFailed and ErrMsg before falling back.
+ if (ErrMsg)
+ ErrMsg->clear();
+ if (ExecutionFailed)
+ *ExecutionFailed = false;
+
+ int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
+ return SecondaryStatus;
}
JobList::JobList() : Job(JobListClass) {}
@@ -30,11 +170,12 @@ JobList::~JobList() {
delete *it;
}
-void JobList::clear() {
- DeleteContainerPointers(Jobs);
+void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote,
+ bool CrashReport) const {
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it)
+ (*it)->Print(OS, Terminator, Quote, CrashReport);
}
-void Job::addCommand(Command *C) {
- cast<JobList>(this)->addJob(C);
+void JobList::clear() {
+ DeleteContainerPointers(Jobs);
}
-
diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
deleted file mode 100644
index 20214a6..0000000
--- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-//===--- OptTable.cpp - Option Table Implementation -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Option.h"
-#include "clang/Driver/Options.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <map>
-using namespace clang::driver;
-using namespace clang::driver::options;
-using namespace clang;
-
-// Ordering on Info. The ordering is *almost* lexicographic, with two
-// exceptions. First, '\0' comes at the end of the alphabet instead of
-// the beginning (thus options precede any other options which prefix
-// them). Second, for options with the same name, the less permissive
-// version should come first; a Flag option should precede a Joined
-// option, for example.
-
-static int StrCmpOptionName(const char *A, const char *B) {
- char a = *A, b = *B;
- while (a == b) {
- if (a == '\0')
- return 0;
-
- a = *++A;
- b = *++B;
- }
-
- if (a == '\0') // A is a prefix of B.
- return 1;
- if (b == '\0') // B is a prefix of A.
- return -1;
-
- // Otherwise lexicographic.
- return (a < b) ? -1 : 1;
-}
-
-namespace clang {
-namespace driver {
-static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
- if (&A == &B)
- return false;
-
- if (int N = StrCmpOptionName(A.Name, B.Name))
- return N == -1;
-
- for (const char * const *APre = A.Prefixes,
- * const *BPre = B.Prefixes;
- *APre != 0 && *BPre != 0; ++APre, ++BPre) {
- if (int N = StrCmpOptionName(*APre, *BPre))
- return N == -1;
- }
-
- // Names are the same, check that classes are in order; exactly one
- // should be joined, and it should succeed the other.
- assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
- "Unexpected classes for options with same name.");
- return B.Kind == Option::JoinedClass;
-}
-
-// Support lower_bound between info and an option name.
-static inline bool operator<(const OptTable::Info &I, const char *Name) {
- return StrCmpOptionName(I.Name, Name) == -1;
-}
-static inline bool operator<(const char *Name, const OptTable::Info &I) {
- return StrCmpOptionName(Name, I.Name) == -1;
-}
-}
-}
-
-//
-
-OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
-
-//
-
-OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
- : OptionInfos(_OptionInfos),
- NumOptionInfos(_NumOptionInfos),
- TheInputOptionID(0),
- TheUnknownOptionID(0),
- FirstSearchableIndex(0)
-{
- // Explicitly zero initialize the error to work around a bug in array
- // value-initialization on MinGW with gcc 4.3.5.
-
- // Find start of normal options.
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
- unsigned Kind = getInfo(i + 1).Kind;
- if (Kind == Option::InputClass) {
- assert(!TheInputOptionID && "Cannot have multiple input options!");
- TheInputOptionID = getInfo(i + 1).ID;
- } else if (Kind == Option::UnknownClass) {
- assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
- TheUnknownOptionID = getInfo(i + 1).ID;
- } else if (Kind != Option::GroupClass) {
- FirstSearchableIndex = i;
- break;
- }
- }
- assert(FirstSearchableIndex != 0 && "No searchable options?");
-
-#ifndef NDEBUG
- // Check that everything after the first searchable option is a
- // regular option class.
- for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
- Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
- assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
- Kind != Option::GroupClass) &&
- "Special options should be defined first!");
- }
-
- // Check that options are in order.
- for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
- if (!(getInfo(i) < getInfo(i + 1))) {
- getOption(i).dump();
- getOption(i + 1).dump();
- llvm_unreachable("Options are not in order!");
- }
- }
-#endif
-
- // Build prefixes.
- for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
- if (const char *const *P = getInfo(i).Prefixes) {
- for (; *P != 0; ++P) {
- PrefixesUnion.insert(*P);
- }
- }
- }
-
- // Build prefix chars.
- for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
- E = PrefixesUnion.end(); I != E; ++I) {
- StringRef Prefix = I->getKey();
- for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
- C != CE; ++C)
- if (std::find(PrefixChars.begin(), PrefixChars.end(), *C)
- == PrefixChars.end())
- PrefixChars.push_back(*C);
- }
-}
-
-OptTable::~OptTable() {
-}
-
-const Option OptTable::getOption(OptSpecifier Opt) const {
- unsigned id = Opt.getID();
- if (id == 0)
- return Option(0, 0);
- assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
- return Option(&getInfo(id), this);
-}
-
-static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
- if (Arg == "-")
- return true;
- for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
- E = Prefixes.end(); I != E; ++I)
- if (Arg.startswith(I->getKey()))
- return false;
- return true;
-}
-
-/// \returns Matched size. 0 means no match.
-static unsigned matchOption(const OptTable::Info *I, StringRef Str) {
- for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) {
- StringRef Prefix(*Pre);
- if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name))
- return Prefix.size() + StringRef(I->Name).size();
- }
- return 0;
-}
-
-Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
- unsigned Prev = Index;
- const char *Str = Args.getArgString(Index);
-
- // Anything that doesn't start with PrefixesUnion is an input, as is '-'
- // itself.
- if (isInput(PrefixesUnion, Str))
- return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
-
- const Info *Start = OptionInfos + FirstSearchableIndex;
- const Info *End = OptionInfos + getNumOptions();
- StringRef Name = StringRef(Str).ltrim(PrefixChars);
-
- // Search for the first next option which could be a prefix.
- Start = std::lower_bound(Start, End, Name.data());
-
- // Options are stored in sorted order, with '\0' at the end of the
- // alphabet. Since the only options which can accept a string must
- // prefix it, we iteratively search for the next option which could
- // be a prefix.
- //
- // FIXME: This is searching much more than necessary, but I am
- // blanking on the simplest way to make it fast. We can solve this
- // problem when we move to TableGen.
- for (; Start != End; ++Start) {
- unsigned ArgSize = 0;
- // Scan for first option which is a proper prefix.
- for (; Start != End; ++Start)
- if ((ArgSize = matchOption(Start, Str)))
- break;
- if (Start == End)
- break;
-
- // See if this option matches.
- if (Arg *A = Option(Start, this).accept(Args, Index, ArgSize))
- return A;
-
- // Otherwise, see if this argument was missing values.
- if (Prev != Index)
- return 0;
- }
-
- return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
-}
-
-InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
- const char* const *ArgEnd,
- unsigned &MissingArgIndex,
- unsigned &MissingArgCount) const {
- InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
-
- // FIXME: Handle '@' args (or at least error on them).
-
- MissingArgIndex = MissingArgCount = 0;
- unsigned Index = 0, End = ArgEnd - ArgBegin;
- while (Index < End) {
- // Ignore empty arguments (other things may still take them as arguments).
- if (Args->getArgString(Index)[0] == '\0') {
- ++Index;
- continue;
- }
-
- unsigned Prev = Index;
- Arg *A = ParseOneArg(*Args, Index);
- assert(Index > Prev && "Parser failed to consume argument.");
-
- // Check for missing argument error.
- if (!A) {
- assert(Index >= End && "Unexpected parser error.");
- assert(Index - Prev - 1 && "No missing arguments!");
- MissingArgIndex = Prev;
- MissingArgCount = Index - Prev - 1;
- break;
- }
-
- Args->append(A);
- }
-
- return Args;
-}
-
-static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
- const Option O = Opts.getOption(Id);
- std::string Name = O.getPrefixedName();
-
- // Add metavar, if used.
- switch (O.getKind()) {
- case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
- llvm_unreachable("Invalid option with help text.");
-
- case Option::MultiArgClass:
- llvm_unreachable("Cannot print metavar for this kind of option.");
-
- case Option::FlagClass:
- break;
-
- case Option::SeparateClass: case Option::JoinedOrSeparateClass:
- Name += ' ';
- // FALLTHROUGH
- case Option::JoinedClass: case Option::CommaJoinedClass:
- case Option::JoinedAndSeparateClass:
- if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
- Name += MetaVarName;
- else
- Name += "<value>";
- break;
- }
-
- return Name;
-}
-
-static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
- std::vector<std::pair<std::string,
- const char*> > &OptionHelp) {
- OS << Title << ":\n";
-
- // 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.
- unsigned Length = OptionHelp[i].first.size();
- if (Length <= 23)
- OptionFieldWidth = std::max(OptionFieldWidth, Length);
- }
-
- const unsigned InitialPad = 2;
- for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
- const std::string &Option = OptionHelp[i].first;
- int Pad = OptionFieldWidth - int(Option.size());
- OS.indent(InitialPad) << Option;
-
- // Break on long option names.
- if (Pad < 0) {
- OS << "\n";
- Pad = OptionFieldWidth + InitialPad;
- }
- OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
- }
-}
-
-static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
- unsigned GroupID = Opts.getOptionGroupID(Id);
-
- // If not in a group, return the default help group.
- if (!GroupID)
- return "OPTIONS";
-
- // Abuse the help text of the option groups to store the "help group"
- // name.
- //
- // FIXME: Split out option groups.
- if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
- return GroupHelp;
-
- // Otherwise keep looking.
- return getOptionHelpGroup(Opts, GroupID);
-}
-
-void OptTable::PrintHelp(raw_ostream &OS, const char *Name,
- const char *Title, unsigned short FlagsToInclude,
- unsigned short FlagsToExclude) const {
- OS << "OVERVIEW: " << Title << "\n";
- OS << '\n';
- OS << "USAGE: " << Name << " [options] <inputs>\n";
- OS << '\n';
-
- // Render help text into a map of group-name to a list of (option, help)
- // pairs.
- typedef std::map<std::string,
- std::vector<std::pair<std::string, const char*> > > helpmap_ty;
- helpmap_ty GroupedOptionHelp;
-
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
- unsigned Id = i + 1;
-
- // FIXME: Split out option groups.
- if (getOptionKind(Id) == Option::GroupClass)
- continue;
-
- if ((FlagsToInclude && !(getInfo(Id).Flags & FlagsToInclude)) ||
- getInfo(Id).Flags & FlagsToExclude)
- continue;
-
- if (const char *Text = getOptionHelpText(Id)) {
- const char *HelpGroup = getOptionHelpGroup(*this, Id);
- const std::string &OptName = getOptionHelpName(*this, Id);
- GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
- }
- }
-
- for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
- ie = GroupedOptionHelp.end(); it != ie; ++it) {
- if (it != GroupedOptionHelp .begin())
- OS << "\n";
- PrintHelpOptionList(OS, it->first, it->second);
- }
-
- OS.flush();
-}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp
deleted file mode 100644
index dbc61ea..0000000
--- a/contrib/llvm/tools/clang/lib/Driver/Option.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-//===--- Option.cpp - Abstract Driver Options -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/Option.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-using namespace clang::driver;
-
-Option::Option(const OptTable::Info *info, const OptTable *owner)
- : Info(info), Owner(owner) {
-
- // Multi-level aliases are not supported, and alias options cannot
- // have groups. This just simplifies option tracking, it is not an
- // inherent limitation.
- assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() &&
- !getGroup().isValid())) &&
- "Multi-level aliases and aliases with groups are unsupported.");
-}
-
-Option::~Option() {
-}
-
-void Option::dump() const {
- llvm::errs() << "<";
- switch (getKind()) {
-#define P(N) case N: llvm::errs() << #N; break
- P(GroupClass);
- P(InputClass);
- P(UnknownClass);
- P(FlagClass);
- P(JoinedClass);
- P(SeparateClass);
- P(CommaJoinedClass);
- P(MultiArgClass);
- P(JoinedOrSeparateClass);
- P(JoinedAndSeparateClass);
-#undef P
- }
-
- llvm::errs() << " Prefixes:[";
- for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) {
- llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", ");
- }
- llvm::errs() << ']';
-
- llvm::errs() << " Name:\"" << getName() << '"';
-
- const Option Group = getGroup();
- if (Group.isValid()) {
- llvm::errs() << " Group:";
- Group.dump();
- }
-
- const Option Alias = getAlias();
- if (Alias.isValid()) {
- llvm::errs() << " Alias:";
- Alias.dump();
- }
-
- if (getKind() == MultiArgClass)
- llvm::errs() << " NumArgs:" << getNumArgs();
-
- llvm::errs() << ">\n";
-}
-
-bool Option::matches(OptSpecifier Opt) const {
- // Aliases are never considered in matching, look through them.
- const Option Alias = getAlias();
- if (Alias.isValid())
- return Alias.matches(Opt);
-
- // Check exact match.
- if (getID() == Opt.getID())
- return true;
-
- const Option Group = getGroup();
- if (Group.isValid())
- return Group.matches(Opt);
- return false;
-}
-
-Arg *Option::accept(const ArgList &Args,
- unsigned &Index,
- unsigned ArgSize) const {
- const Option &UnaliasedOption = getUnaliasedOption();
- StringRef Spelling;
- // If the option was an alias, get the spelling from the unaliased one.
- if (getID() == UnaliasedOption.getID()) {
- Spelling = StringRef(Args.getArgString(Index), ArgSize);
- } else {
- Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
- Twine(UnaliasedOption.getName()));
- }
-
- switch (getKind()) {
- case FlagClass:
- if (ArgSize != strlen(Args.getArgString(Index)))
- return 0;
-
- return new Arg(UnaliasedOption, Spelling, Index++);
- case JoinedClass: {
- const char *Value = Args.getArgString(Index) + ArgSize;
- return new Arg(UnaliasedOption, Spelling, Index++, Value);
- }
- case CommaJoinedClass: {
- // Always matches.
- const char *Str = Args.getArgString(Index) + ArgSize;
- Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
-
- // Parse out the comma separated values.
- const char *Prev = Str;
- for (;; ++Str) {
- char c = *Str;
-
- if (!c || c == ',') {
- if (Prev != Str) {
- char *Value = new char[Str - Prev + 1];
- memcpy(Value, Prev, Str - Prev);
- Value[Str - Prev] = '\0';
- A->getValues().push_back(Value);
- }
-
- if (!c)
- break;
-
- Prev = Str + 1;
- }
- }
- A->setOwnsValues(true);
-
- return A;
- }
- case SeparateClass:
- // Matches iff this is an exact match.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index)))
- return 0;
-
- Index += 2;
- if (Index > Args.getNumInputArgStrings())
- return 0;
-
- return new Arg(UnaliasedOption, Spelling,
- Index - 2, Args.getArgString(Index - 1));
- case MultiArgClass: {
- // Matches iff this is an exact match.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index)))
- return 0;
-
- Index += 1 + getNumArgs();
- if (Index > Args.getNumInputArgStrings())
- return 0;
-
- Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
- Args.getArgString(Index - getNumArgs()));
- for (unsigned i = 1; i != getNumArgs(); ++i)
- A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
- return A;
- }
- case JoinedOrSeparateClass: {
- // If this is not an exact match, it is a joined arg.
- // FIXME: Avoid strlen.
- if (ArgSize != strlen(Args.getArgString(Index))) {
- const char *Value = Args.getArgString(Index) + ArgSize;
- return new Arg(*this, Spelling, Index++, Value);
- }
-
- // Otherwise it must be separate.
- Index += 2;
- if (Index > Args.getNumInputArgStrings())
- return 0;
-
- return new Arg(UnaliasedOption, Spelling,
- Index - 2, Args.getArgString(Index - 1));
- }
- case JoinedAndSeparateClass:
- // Always matches.
- Index += 2;
- if (Index > Args.getNumInputArgStrings())
- return 0;
-
- return new Arg(UnaliasedOption, Spelling, Index - 2,
- Args.getArgString(Index - 2) + ArgSize,
- Args.getArgString(Index - 1));
- default:
- llvm_unreachable("Invalid option kind!");
- }
-}
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
new file mode 100644
index 0000000..43209f0
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -0,0 +1,389 @@
+//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Driver/SanitizerArgs.h"
+
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Transforms/Utils/SpecialCaseList.h"
+
+using namespace clang::driver;
+using namespace llvm::opt;
+
+void SanitizerArgs::clear() {
+ Kind = 0;
+ BlacklistFile = "";
+ MsanTrackOrigins = false;
+ AsanZeroBaseShadow = false;
+ UbsanTrapOnError = false;
+}
+
+SanitizerArgs::SanitizerArgs() {
+ clear();
+}
+
+SanitizerArgs::SanitizerArgs(const ToolChain &TC,
+ const llvm::opt::ArgList &Args) {
+ clear();
+ unsigned AllAdd = 0; // All kinds of sanitizers that were turned on
+ // at least once (possibly, disabled further).
+ unsigned AllRemove = 0; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
+ unsigned DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
+ // Used to deduplicate diagnostics.
+ const Driver &D = TC.getDriver();
+ for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
+ I != E; ++I) {
+ unsigned Add, Remove;
+ if (!parse(D, Args, *I, Add, Remove, true))
+ continue;
+ (*I)->claim();
+
+ AllAdd |= expandGroups(Add);
+ AllRemove |= expandGroups(Remove);
+
+ // Avoid diagnosing any sanitizer which is disabled later.
+ Add &= ~AllRemove;
+ // At this point we have not expanded groups, so any unsupported sanitizers
+ // in Add are those which have been explicitly enabled. Diagnose them.
+ Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/true,
+ DiagnosedKinds);
+ Add = expandGroups(Add);
+ // Group expansion may have enabled a sanitizer which is disabled later.
+ Add &= ~AllRemove;
+ // Silently discard any unsupported sanitizers implicitly enabled through
+ // group expansion.
+ Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/false,
+ DiagnosedKinds);
+
+ Kind |= Add;
+ }
+
+ UbsanTrapOnError =
+ Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
+ Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, false);
+
+ if (Args.hasArg(options::OPT_fcatch_undefined_behavior) &&
+ !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, true)) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fcatch-undefined-behavior"
+ << "-fno-sanitize-undefined-trap-on-error";
+ }
+
+ // Warn about undefined sanitizer options that require runtime support.
+ if (UbsanTrapOnError && notAllowedWithTrap()) {
+ if (Args.hasArg(options::OPT_fcatch_undefined_behavior))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NotAllowedWithTrap)
+ << "-fcatch-undefined-behavior";
+ else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error,
+ false))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NotAllowedWithTrap)
+ << "-fsanitize-undefined-trap-on-error";
+ }
+
+ // Only one runtime library can be used at once.
+ bool NeedsAsan = needsAsanRt();
+ bool NeedsTsan = needsTsanRt();
+ bool NeedsMsan = needsMsanRt();
+ bool NeedsLsan = needsLeakDetection();
+ if (NeedsAsan && NeedsTsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsAsanRt)
+ << lastArgumentForKind(D, Args, NeedsTsanRt);
+ if (NeedsAsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsAsanRt)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ if (NeedsTsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsTsanRt)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ if (NeedsLsan && NeedsTsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsLeakDetection)
+ << lastArgumentForKind(D, Args, NeedsTsanRt);
+ if (NeedsLsan && NeedsMsan)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << lastArgumentForKind(D, Args, NeedsLeakDetection)
+ << lastArgumentForKind(D, Args, NeedsMsanRt);
+ // FIXME: Currenly -fsanitize=leak is silently ignored in the presence of
+ // -fsanitize=address. Perhaps it should print an error, or perhaps
+ // -f(-no)sanitize=leak should change whether leak detection is enabled by
+ // default in ASan?
+
+ // If -fsanitize contains extra features of ASan, it should also
+ // explicitly contain -fsanitize=address (probably, turned off later in the
+ // command line).
+ if ((Kind & AddressFull) != 0 && (AllAdd & Address) == 0)
+ D.Diag(diag::warn_drv_unused_sanitizer)
+ << lastArgumentForKind(D, Args, AddressFull)
+ << "-fsanitize=address";
+
+ // Parse -f(no-)sanitize-blacklist options.
+ if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
+ options::OPT_fno_sanitize_blacklist)) {
+ if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+ std::string BLPath = BLArg->getValue();
+ if (llvm::sys::fs::exists(BLPath)) {
+ // Validate the blacklist format.
+ std::string BLError;
+ llvm::OwningPtr<llvm::SpecialCaseList> SCL(
+ llvm::SpecialCaseList::create(BLPath, BLError));
+ if (!SCL.get())
+ D.Diag(diag::err_drv_malformed_sanitizer_blacklist) << BLError;
+ else
+ BlacklistFile = BLPath;
+ } else {
+ D.Diag(diag::err_drv_no_such_file) << BLPath;
+ }
+ }
+ } else {
+ // If no -fsanitize-blacklist option is specified, try to look up for
+ // blacklist in the resource directory.
+ std::string BLPath;
+ if (getDefaultBlacklistForKind(D, Kind, BLPath) &&
+ llvm::sys::fs::exists(BLPath))
+ BlacklistFile = BLPath;
+ }
+
+ // Parse -f(no-)sanitize-memory-track-origins options.
+ if (NeedsMsan)
+ MsanTrackOrigins =
+ Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
+ options::OPT_fno_sanitize_memory_track_origins,
+ /* Default */false);
+
+ // Parse -f(no-)sanitize-address-zero-base-shadow options.
+ if (NeedsAsan) {
+ bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ bool ZeroBaseShadowDefault = IsAndroid;
+ AsanZeroBaseShadow =
+ Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
+ options::OPT_fno_sanitize_address_zero_base_shadow,
+ ZeroBaseShadowDefault);
+ // Zero-base shadow is a requirement on Android.
+ if (IsAndroid && !AsanZeroBaseShadow) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-sanitize-address-zero-base-shadow"
+ << lastArgumentForKind(D, Args, Address);
+ }
+ }
+}
+
+void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ if (!Kind)
+ return;
+ SmallString<256> SanitizeOpt("-fsanitize=");
+#define SANITIZER(NAME, ID) \
+ if (Kind & ID) \
+ SanitizeOpt += NAME ",";
+#include "clang/Basic/Sanitizers.def"
+ SanitizeOpt.pop_back();
+ CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
+ if (!BlacklistFile.empty()) {
+ SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
+ BlacklistOpt += BlacklistFile;
+ CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
+ }
+
+ if (MsanTrackOrigins)
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins"));
+
+ if (AsanZeroBaseShadow)
+ CmdArgs.push_back(
+ Args.MakeArgString("-fsanitize-address-zero-base-shadow"));
+
+ // Workaround for PR16386.
+ if (needsMsanRt())
+ CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
+}
+
+unsigned SanitizerArgs::parse(const char *Value) {
+ unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
+#define SANITIZER(NAME, ID) .Case(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group)
+#include "clang/Basic/Sanitizers.def"
+ .Default(SanitizeKind());
+ // Assume -fsanitize=address implies -fsanitize=init-order,use-after-return.
+ // FIXME: This should be either specified in Sanitizers.def, or go away when
+ // we get rid of "-fsanitize=init-order,use-after-return" flags at all.
+ if (ParsedKind & Address)
+ ParsedKind |= InitOrder | UseAfterReturn;
+ return ParsedKind;
+}
+
+unsigned SanitizerArgs::expandGroups(unsigned Kinds) {
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID;
+#include "clang/Basic/Sanitizers.def"
+ return Kinds;
+}
+
+void SanitizerArgs::filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds,
+ unsigned Mask,
+ const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ bool DiagnoseErrors,
+ unsigned &DiagnosedKinds) {
+ unsigned MaskedKinds = Kinds & Mask;
+ if (!MaskedKinds)
+ return;
+ Kinds &= ~Mask;
+ // Do we have new kinds to diagnose?
+ if (DiagnoseErrors && (DiagnosedKinds & MaskedKinds) != MaskedKinds) {
+ // Only diagnose the new kinds.
+ std::string Desc =
+ describeSanitizeArg(Args, A, MaskedKinds & ~DiagnosedKinds);
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << Desc << TC.getTriple().str();
+ DiagnosedKinds |= MaskedKinds;
+ }
+}
+
+unsigned SanitizerArgs::filterUnsupportedKinds(const ToolChain &TC,
+ unsigned Kinds,
+ const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ bool DiagnoseErrors,
+ unsigned &DiagnosedKinds) {
+ bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
+ bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
+ bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
+ if (!(IsLinux && IsX86_64)) {
+ filterUnsupportedMask(TC, Kinds, Thread | Memory | DataFlow, Args, A,
+ DiagnoseErrors, DiagnosedKinds);
+ }
+ if (!(IsLinux && (IsX86 || IsX86_64))) {
+ filterUnsupportedMask(TC, Kinds, Function, Args, A, DiagnoseErrors,
+ DiagnosedKinds);
+ }
+ return Kinds;
+}
+
+unsigned SanitizerArgs::parse(const Driver &D, const llvm::opt::Arg *A,
+ bool DiagnoseErrors) {
+ unsigned Kind = 0;
+ for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
+ if (unsigned K = parse(A->getValue(I)))
+ Kind |= K;
+ else if (DiagnoseErrors)
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue(I);
+ }
+ return Kind;
+}
+
+bool SanitizerArgs::parse(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A, unsigned &Add,
+ unsigned &Remove, bool DiagnoseErrors) {
+ Add = 0;
+ Remove = 0;
+ const char *DeprecatedReplacement = 0;
+ if (A->getOption().matches(options::OPT_faddress_sanitizer)) {
+ Add = Address;
+ DeprecatedReplacement = "-fsanitize=address";
+ } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) {
+ Remove = Address;
+ DeprecatedReplacement = "-fno-sanitize=address";
+ } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) {
+ Add = Thread;
+ DeprecatedReplacement = "-fsanitize=thread";
+ } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) {
+ Remove = Thread;
+ DeprecatedReplacement = "-fno-sanitize=thread";
+ } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
+ Add = UndefinedTrap;
+ DeprecatedReplacement =
+ "-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error";
+ } else if (A->getOption().matches(options::OPT_fbounds_checking) ||
+ A->getOption().matches(options::OPT_fbounds_checking_EQ)) {
+ Add = LocalBounds;
+ DeprecatedReplacement = "-fsanitize=local-bounds";
+ } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
+ Add = parse(D, A, DiagnoseErrors);
+ } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ Remove = parse(D, A, DiagnoseErrors);
+ } else {
+ // Flag is not relevant to sanitizers.
+ return false;
+ }
+ // If this is a deprecated synonym, produce a warning directing users
+ // towards the new spelling.
+ if (DeprecatedReplacement && DiagnoseErrors)
+ D.Diag(diag::warn_drv_deprecated_arg)
+ << A->getAsString(Args) << DeprecatedReplacement;
+ return true;
+}
+
+std::string SanitizerArgs::lastArgumentForKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ unsigned Kind) {
+ for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
+ E = Args.rend();
+ I != E; ++I) {
+ unsigned Add, Remove;
+ if (parse(D, Args, *I, Add, Remove, false) &&
+ (expandGroups(Add) & Kind))
+ return describeSanitizeArg(Args, *I, Kind);
+ Kind &= ~Remove;
+ }
+ llvm_unreachable("arg list didn't provide expected value");
+}
+
+std::string SanitizerArgs::describeSanitizeArg(const llvm::opt::ArgList &Args,
+ const llvm::opt::Arg *A,
+ unsigned Mask) {
+ if (!A->getOption().matches(options::OPT_fsanitize_EQ))
+ return A->getAsString(Args);
+
+ std::string Sanitizers;
+ for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
+ if (expandGroups(parse(A->getValue(I))) & Mask) {
+ if (!Sanitizers.empty())
+ Sanitizers += ",";
+ Sanitizers += A->getValue(I);
+ }
+ }
+
+ assert(!Sanitizers.empty() && "arg didn't provide expected value");
+ return "-fsanitize=" + Sanitizers;
+}
+
+bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
+ std::string &BLPath) {
+ const char *BlacklistFile = 0;
+ if (Kind & NeedsAsanRt)
+ BlacklistFile = "asan_blacklist.txt";
+ else if (Kind & NeedsMsanRt)
+ BlacklistFile = "msan_blacklist.txt";
+ else if (Kind & NeedsTsanRt)
+ BlacklistFile = "tsan_blacklist.txt";
+ else if (Kind & NeedsDfsanRt)
+ BlacklistFile = "dfsan_abilist.txt";
+
+ if (BlacklistFile) {
+ SmallString<64> Path(D.ResourceDir);
+ llvm::sys::path::append(Path, BlacklistFile);
+ BLPath = Path.str();
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h
deleted file mode 100644
index 326d80d..0000000
--- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h
+++ /dev/null
@@ -1,220 +0,0 @@
-//===--- SanitizerArgs.h - Arguments for sanitizer tools -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_
-#define CLANG_LIB_DRIVER_SANITIZERARGS_H_
-
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Options.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Path.h"
-
-namespace clang {
-namespace driver {
-
-class SanitizerArgs {
- /// Assign ordinals to sanitizer flags. We'll use the ordinal values as
- /// bit positions within \c Kind.
- enum SanitizeOrdinal {
-#define SANITIZER(NAME, ID) SO_##ID,
-#include "clang/Basic/Sanitizers.def"
- SO_Count
- };
-
- /// Bugs to catch at runtime.
- enum SanitizeKind {
-#define SANITIZER(NAME, ID) ID = 1 << SO_##ID,
-#define SANITIZER_GROUP(NAME, ID, ALIAS) ID = ALIAS,
-#include "clang/Basic/Sanitizers.def"
- NeedsAsanRt = Address,
- NeedsTsanRt = Thread,
- NeedsMsanRt = Memory,
- NeedsUbsanRt = Undefined | Integer,
- NotAllowedWithTrap = Vptr,
- HasZeroBaseShadow = Thread | Memory
- };
- unsigned Kind;
- std::string BlacklistFile;
- bool MsanTrackOrigins;
- bool AsanZeroBaseShadow;
- bool UbsanTrapOnError;
-
- public:
- SanitizerArgs() : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false), UbsanTrapOnError(false) {}
- /// Parses the sanitizer arguments from an argument list.
- SanitizerArgs(const ToolChain &TC, const ArgList &Args);
-
- bool needsAsanRt() const { return Kind & NeedsAsanRt; }
- bool needsTsanRt() const { return Kind & NeedsTsanRt; }
- bool needsMsanRt() const { return Kind & NeedsMsanRt; }
- bool needsUbsanRt() const {
- if (UbsanTrapOnError)
- return false;
- return Kind & NeedsUbsanRt;
- }
-
- bool sanitizesVptr() const { return Kind & Vptr; }
- bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; }
- bool hasZeroBaseShadow() const {
- return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow;
- }
-
- void addArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
- if (!Kind)
- return;
- SmallString<256> SanitizeOpt("-fsanitize=");
-#define SANITIZER(NAME, ID) \
- if (Kind & ID) \
- SanitizeOpt += NAME ",";
-#include "clang/Basic/Sanitizers.def"
- SanitizeOpt.pop_back();
- CmdArgs.push_back(Args.MakeArgString(SanitizeOpt));
- if (!BlacklistFile.empty()) {
- SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
- BlacklistOpt += BlacklistFile;
- CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
- }
-
- if (MsanTrackOrigins)
- CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins"));
-
- if (AsanZeroBaseShadow)
- CmdArgs.push_back(Args.MakeArgString(
- "-fsanitize-address-zero-base-shadow"));
- }
-
- private:
- /// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
- /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0
- /// if \p Value is not known.
- static unsigned parse(const char *Value) {
- unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value)
-#define SANITIZER(NAME, ID) .Case(NAME, ID)
-#define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID)
-#include "clang/Basic/Sanitizers.def"
- .Default(SanitizeKind());
- // Assume -fsanitize=address implies -fsanitize=init-order.
- // FIXME: This should be either specified in Sanitizers.def, or go away when
- // we get rid of "-fsanitize=init-order" flag at all.
- if (ParsedKind & Address)
- ParsedKind |= InitOrder;
- return ParsedKind;
- }
-
- /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
- /// invalid components.
- static unsigned parse(const Driver &D, const Arg *A, bool DiagnoseErrors) {
- unsigned Kind = 0;
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
- if (unsigned K = parse(A->getValue(I)))
- Kind |= K;
- else if (DiagnoseErrors)
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue(I);
- }
- return Kind;
- }
-
- /// Parse a single flag of the form -f[no]sanitize=, or
- /// -f*-sanitizer. Sets the masks defining required change of Kind value.
- /// Returns true if the flag was parsed successfully.
- static bool parse(const Driver &D, const ArgList &Args, const Arg *A,
- unsigned &Add, unsigned &Remove, bool DiagnoseErrors) {
- Add = 0;
- Remove = 0;
- const char *DeprecatedReplacement = 0;
- if (A->getOption().matches(options::OPT_faddress_sanitizer)) {
- Add = Address;
- DeprecatedReplacement = "-fsanitize=address";
- } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) {
- Remove = Address;
- DeprecatedReplacement = "-fno-sanitize=address";
- } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) {
- Add = Thread;
- DeprecatedReplacement = "-fsanitize=thread";
- } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) {
- Remove = Thread;
- DeprecatedReplacement = "-fno-sanitize=thread";
- } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) {
- Add = UndefinedTrap;
- DeprecatedReplacement =
- "-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error";
- } else if (A->getOption().matches(options::OPT_fbounds_checking) ||
- A->getOption().matches(options::OPT_fbounds_checking_EQ)) {
- Add = Bounds;
- DeprecatedReplacement = "-fsanitize=bounds";
- } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
- Add = parse(D, A, DiagnoseErrors);
- } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
- Remove = parse(D, A, DiagnoseErrors);
- } else {
- // Flag is not relevant to sanitizers.
- return false;
- }
- // If this is a deprecated synonym, produce a warning directing users
- // towards the new spelling.
- if (DeprecatedReplacement && DiagnoseErrors)
- D.Diag(diag::warn_drv_deprecated_arg)
- << A->getAsString(Args) << DeprecatedReplacement;
- return true;
- }
-
- /// Produce an argument string from ArgList \p Args, which shows how it
- /// provides a sanitizer kind in \p Mask. For example, the argument list
- /// "-fsanitize=thread,vptr -faddress-sanitizer" with mask \c NeedsUbsanRt
- /// would produce "-fsanitize=vptr".
- static std::string lastArgumentForKind(const Driver &D, const ArgList &Args,
- unsigned Kind) {
- for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
- I != E; ++I) {
- unsigned Add, Remove;
- if (parse(D, Args, *I, Add, Remove, false) &&
- (Add & Kind))
- return describeSanitizeArg(Args, *I, Kind);
- Kind &= ~Remove;
- }
- llvm_unreachable("arg list didn't provide expected value");
- }
-
- /// Produce an argument string from argument \p A, which shows how it provides
- /// a value in \p Mask. For instance, the argument
- /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce
- /// "-fsanitize=alignment".
- static std::string describeSanitizeArg(const ArgList &Args, const Arg *A,
- unsigned Mask) {
- if (!A->getOption().matches(options::OPT_fsanitize_EQ))
- return A->getAsString(Args);
-
- for (unsigned I = 0, N = A->getNumValues(); I != N; ++I)
- if (parse(A->getValue(I)) & Mask)
- return std::string("-fsanitize=") + A->getValue(I);
-
- llvm_unreachable("arg didn't provide expected value");
- }
-
- static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind,
- std::string &BLPath) {
- // For now, specify the default blacklist location for ASan only.
- if (Kind & NeedsAsanRt) {
- SmallString<64> Path(D.ResourceDir);
- llvm::sys::path::append(Path, "asan_blacklist.txt");
- BLPath = Path.str();
- return true;
- }
- return false;
- }
-};
-
-} // namespace driver
-} // namespace clang
-
-#endif // CLANG_LIB_DRIVER_SANITIZERARGS_H_
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index 71f5393..efd3945 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -8,20 +8,22 @@
//===----------------------------------------------------------------------===//
#include "Tools.h"
-#include "clang/Driver/ToolChain.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Driver/Action.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
using namespace clang::driver;
using namespace clang;
+using namespace llvm::opt;
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &A)
@@ -41,6 +43,12 @@ bool ToolChain::useIntegratedAs() const {
IsIntegratedAssemblerDefault());
}
+const SanitizerArgs& ToolChain::getSanitizerArgs() const {
+ if (!SanitizerArguments.get())
+ SanitizerArguments.reset(new SanitizerArgs(*this, Args));
+ return *SanitizerArguments.get();
+}
+
std::string ToolChain::getDefaultUniversalArchName() const {
// In universal driver terms, the arch name accepted by -arch isn't exactly
// the same as the ones that appear in the triple. Roughly speaking, this is
@@ -51,6 +59,8 @@ std::string ToolChain::getDefaultUniversalArchName() const {
return "ppc";
case llvm::Triple::ppc64:
return "ppc64";
+ case llvm::Triple::ppc64le:
+ return "ppc64le";
default:
return Triple.getArchName();
}
@@ -173,11 +183,17 @@ static const char *getARMTargetCPU(const ArgList &Args,
MArch = Triple.getArchName();
}
- return llvm::StringSwitch<const char *>(MArch)
+ if (Triple.getOS() == llvm::Triple::NetBSD) {
+ if (MArch == "armv6")
+ return "arm1176jzf-s";
+ }
+
+ const char *result = llvm::StringSwitch<const char *>(MArch)
.Cases("armv2", "armv2a","arm2")
.Case("armv3", "arm6")
.Case("armv3m", "arm7m")
- .Cases("armv4", "armv4t", "arm7tdmi")
+ .Case("armv4", "strongarm")
+ .Case("armv4t", "arm7tdmi")
.Cases("armv5", "armv5t", "arm10tdmi")
.Cases("armv5e", "armv5te", "arm1026ejs")
.Case("armv5tej", "arm926ej-s")
@@ -193,11 +209,21 @@ static const char *getARMTargetCPU(const ArgList &Args,
.Cases("armv7r", "armv7-r", "cortex-r4")
.Cases("armv7m", "armv7-m", "cortex-m3")
.Cases("armv7em", "armv7e-m", "cortex-m4")
+ .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
.Case("ep9312", "ep9312")
.Case("iwmmxt", "iwmmxt")
.Case("xscale", "xscale")
- // If all else failed, return the most base CPU LLVM supports.
- .Default("arm7tdmi");
+ // If all else failed, return the most base CPU with thumb interworking
+ // supported by LLVM.
+ .Default(0);
+
+ if (result)
+ return result;
+
+ return
+ Triple.getEnvironment() == llvm::Triple::GNUEABIHF
+ ? "arm1176jzf-s"
+ : "arm7tdmi";
}
/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
@@ -207,6 +233,7 @@ static const char *getARMTargetCPU(const ArgList &Args,
// FIXME: tblgen this, or kill it!
static const char *getLLVMArchSuffixForARM(StringRef CPU) {
return llvm::StringSwitch<const char *>(CPU)
+ .Case("strongarm", "v4")
.Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
.Cases("arm720t", "arm9", "arm9tdmi", "v4t")
.Cases("arm920", "arm920t", "arm922t", "v4t")
@@ -219,22 +246,37 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) {
.Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .Cases("cortex-a9", "cortex-a15", "v7")
- .Case("cortex-r5", "v7r")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
+ .Cases("cortex-r4", "cortex-r5", "v7r")
.Case("cortex-m0", "v6m")
.Case("cortex-m3", "v7m")
.Case("cortex-m4", "v7em")
.Case("cortex-a9-mp", "v7f")
.Case("swift", "v7s")
+ .Cases("cortex-a53", "cortex-a57", "v8")
.Default("");
}
-std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
types::ID InputType) const {
switch (getTriple().getArch()) {
default:
return getTripleString();
+ case llvm::Triple::x86_64: {
+ llvm::Triple Triple = getTriple();
+ if (!Triple.isOSDarwin())
+ return getTripleString();
+
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // x86_64h goes in the triple. Other -march options just use the
+ // vanilla triple we already have.
+ StringRef MArch = A->getValue();
+ if (MArch == "x86_64h")
+ Triple.setArchName(MArch);
+ }
+ return Triple.getTriple();
+ }
case llvm::Triple::arm:
case llvm::Triple::thumb: {
// FIXME: Factor into subclasses.
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index dbb69ac..8a47e76 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -8,27 +8,28 @@
//===----------------------------------------------------------------------===//
#include "ToolChains.h"
-#include "SanitizerArgs.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include "llvm/Support/Program.h"
// FIXME: This needs to be listed last until we fix the broken include guards
// in these files and the LLVM config.h files.
@@ -39,6 +40,7 @@
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
+using namespace llvm::opt;
/// Darwin - Darwin tool chain for i386 and x86_64.
@@ -122,7 +124,9 @@ static const char *GetArmArchForMCpu(StringRef Value) {
.Case("xscale", "xscale")
.Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
.Case("cortex-m0", "armv6m")
- .Cases("cortex-a8", "cortex-r4", "cortex-a9", "cortex-a15", "armv7")
+ .Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "armv7")
+ .Cases("cortex-r4", "cortex-r5", "armv7r")
.Case("cortex-a9-mp", "armv7f")
.Case("cortex-m3", "armv7m")
.Case("cortex-m4", "armv7em")
@@ -162,10 +166,18 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
if (!isTargetInitialized())
return Triple.getTriple();
- SmallString<16> Str;
- Str += isTargetIPhoneOS() ? "ios" : "macosx";
- Str += getTargetVersion().getAsString();
- Triple.setOSName(Str);
+ if (Triple.getArchName() == "thumbv6m" ||
+ Triple.getArchName() == "thumbv7m" ||
+ Triple.getArchName() == "thumbv7em") {
+ // OS is ios or macosx unless it's the v6m or v7m.
+ Triple.setOS(llvm::Triple::Darwin);
+ Triple.setEnvironment(llvm::Triple::EABI);
+ } else {
+ SmallString<16> Str;
+ Str += isTargetIPhoneOS() ? "ios" : "macosx";
+ Str += getTargetVersion().getAsString();
+ Triple.setOSName(Str);
+ }
return Triple.getTriple();
}
@@ -217,39 +229,33 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-force_load");
- llvm::sys::Path P(getDriver().ClangExecutable);
- P.eraseComponent(); // 'clang'
- P.eraseComponent(); // 'bin'
- P.appendComponent("lib");
- P.appendComponent("arc");
- P.appendComponent("libarclite_");
- std::string s = P.str();
+ SmallString<128> P(getDriver().ClangExecutable);
+ llvm::sys::path::remove_filename(P); // 'clang'
+ llvm::sys::path::remove_filename(P); // 'bin'
+ llvm::sys::path::append(P, "lib", "arc", "libarclite_");
// Mash in the platform.
if (isTargetIOSSimulator())
- s += "iphonesimulator";
+ P += "iphonesimulator";
else if (isTargetIPhoneOS())
- s += "iphoneos";
+ P += "iphoneos";
else
- s += "macosx";
- s += ".a";
+ P += "macosx";
+ P += ".a";
- CmdArgs.push_back(Args.MakeArgString(s));
+ CmdArgs.push_back(Args.MakeArgString(P));
}
void DarwinClang::AddLinkRuntimeLib(const ArgList &Args,
ArgStringList &CmdArgs,
const char *DarwinStaticLib,
bool AlwaysLink) const {
- llvm::sys::Path P(getDriver().ResourceDir);
- P.appendComponent("lib");
- P.appendComponent("darwin");
- P.appendComponent(DarwinStaticLib);
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "lib", "darwin", DarwinStaticLib);
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build (unless
// we explicitly force linking with this library).
- bool Exists;
- if (AlwaysLink || (!llvm::sys::fs::exists(P.str(), Exists) && Exists))
+ if (AlwaysLink || llvm::sys::fs::exists(P.str()))
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
@@ -294,10 +300,11 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
- SanitizerArgs Sanitize(*this, Args);
+ const SanitizerArgs &Sanitize = getSanitizerArgs();
// Add Ubsan runtime library, if required.
if (Sanitize.needsUbsanRt()) {
+ // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
if (isTargetIPhoneOS()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
<< "-fsanitize=undefined";
@@ -312,19 +319,27 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
// Add ASAN runtime library, if required. Dynamic libraries and bundles
// should not be linked with the runtime library.
if (Sanitize.needsAsanRt()) {
+ // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
if (isTargetIPhoneOS() && !isTargetIOSSimulator()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
<< "-fsanitize=address";
} else {
- if (Args.hasArg(options::OPT_dynamiclib) ||
- Args.hasArg(options::OPT_bundle)) {
- // Assume the binary will provide the ASan runtime.
- } else {
- AddLinkRuntimeLib(Args, CmdArgs,
- "libclang_rt.asan_osx_dynamic.dylib", true);
+ if (!Args.hasArg(options::OPT_dynamiclib) &&
+ !Args.hasArg(options::OPT_bundle)) {
// The ASAN runtime library requires C++.
AddCXXStdlibLibArgs(Args, CmdArgs);
}
+ if (isTargetMacOS()) {
+ AddLinkRuntimeLib(Args, CmdArgs,
+ "libclang_rt.asan_osx_dynamic.dylib",
+ true);
+ } else {
+ if (isTargetIOSSimulator()) {
+ AddLinkRuntimeLib(Args, CmdArgs,
+ "libclang_rt.asan_iossim_dynamic.dylib",
+ true);
+ }
+ }
}
}
@@ -376,8 +391,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
// isysroot.
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
// Warn if the path does not exist.
- bool Exists;
- if (llvm::sys::fs::exists(A->getValue(), Exists) || !Exists)
+ if (!llvm::sys::fs::exists(A->getValue()))
getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
} else {
if (char *env = ::getenv("SDKROOT")) {
@@ -538,17 +552,14 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
// explicitly if we can't see an obvious -lstdc++ candidate.
// Check in the sysroot first.
- bool Exists;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- llvm::sys::Path P(A->getValue());
- P.appendComponent("usr");
- P.appendComponent("lib");
- P.appendComponent("libstdc++.dylib");
-
- if (llvm::sys::fs::exists(P.str(), Exists) || !Exists) {
- P.eraseComponent();
- P.appendComponent("libstdc++.6.dylib");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ SmallString<128> P(A->getValue());
+ llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
+
+ if (!llvm::sys::fs::exists(P.str())) {
+ llvm::sys::path::remove_filename(P);
+ llvm::sys::path::append(P, "libstdc++.6.dylib");
+ if (llvm::sys::fs::exists(P.str())) {
CmdArgs.push_back(Args.MakeArgString(P.str()));
return;
}
@@ -558,8 +569,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
// Otherwise, look in the root.
// FIXME: This should be removed someday when we don't have to care about
// 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
- if ((llvm::sys::fs::exists("/usr/lib/libstdc++.dylib", Exists) || !Exists)&&
- (!llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib", Exists) && Exists)){
+ if (!llvm::sys::fs::exists("/usr/lib/libstdc++.dylib") &&
+ llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib")) {
CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
return;
}
@@ -578,22 +589,20 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
// instead of the gcc-provided one (which is also incidentally
// only present in the gcc lib dir, which makes it hard to find).
- llvm::sys::Path P(getDriver().ResourceDir);
- P.appendComponent("lib");
- P.appendComponent("darwin");
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "lib", "darwin");
// Use the newer cc_kext for iOS ARM after 6.0.
if (!isTargetIPhoneOS() || isTargetIOSSimulator() ||
!isIPhoneOSVersionLT(6, 0)) {
- P.appendComponent("libclang_rt.cc_kext.a");
+ llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
} else {
- P.appendComponent("libclang_rt.cc_kext_ios5.a");
+ llvm::sys::path::append(P, "libclang_rt.cc_kext_ios5.a");
}
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
- bool Exists;
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ if (llvm::sys::fs::exists(P.str()))
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
@@ -762,7 +771,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
else if (Name == "ppc970")
DAL->AddJoinedArg(0, MCpu, "970");
- else if (Name == "ppc64")
+ else if (Name == "ppc64" || Name == "ppc64le")
DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
else if (Name == "i386")
@@ -784,6 +793,10 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
else if (Name == "x86_64")
DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+ else if (Name == "x86_64h") {
+ DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
+ DAL->AddJoinedArg(0, MArch, "x86_64h");
+ }
else if (Name == "arm")
DAL->AddJoinedArg(0, MArch, "armv4t");
@@ -839,6 +852,12 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
}
}
+ // Default to use libc++ on OS X 10.9+ and iOS 7+.
+ if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
+ (isTargetIPhoneOS() && !isIPhoneOSVersionLT(7, 0))) &&
+ !Args.getLastArg(options::OPT_stdlib_EQ))
+ DAL->AddJoinedArg(0, Opts.getOption(options::OPT_stdlib_EQ), "libc++");
+
// Validate the C++ standard library choice.
CXXStdlibType Type = GetCXXStdlibType(*DAL);
if (Type == ToolChain::CST_Libcxx) {
@@ -917,17 +936,19 @@ Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args,
/// This is the primary means of forming GCCVersion objects.
/*static*/
Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
- const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "" };
+ const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
- GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "" };
+ GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
if (First.first.getAsInteger(10, GoodVersion.Major) ||
GoodVersion.Major < 0)
return BadVersion;
+ GoodVersion.MajorStr = First.first.str();
if (Second.first.getAsInteger(10, GoodVersion.Minor) ||
GoodVersion.Minor < 0)
return BadVersion;
+ GoodVersion.MinorStr = Second.first.str();
// First look for a number prefix and parse that if present. Otherwise just
// stash the entire patch string in the suffix, and leave the number
@@ -945,7 +966,7 @@ Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
GoodVersion.Patch < 0)
return BadVersion;
- GoodVersion.PatchSuffix = PatchText.substr(EndNumber).str();
+ GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
}
}
@@ -953,31 +974,33 @@ Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
}
/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
-bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const {
- if (Major != RHS.Major)
- return Major < RHS.Major;
- if (Minor != RHS.Minor)
- return Minor < RHS.Minor;
- if (Patch != RHS.Patch) {
+bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
+ int RHSPatch,
+ StringRef RHSPatchSuffix) const {
+ if (Major != RHSMajor)
+ return Major < RHSMajor;
+ if (Minor != RHSMinor)
+ return Minor < RHSMinor;
+ if (Patch != RHSPatch) {
// Note that versions without a specified patch sort higher than those with
// a patch.
- if (RHS.Patch == -1)
+ if (RHSPatch == -1)
return true;
if (Patch == -1)
return false;
// Otherwise just sort on the patch itself.
- return Patch < RHS.Patch;
+ return Patch < RHSPatch;
}
- if (PatchSuffix != RHS.PatchSuffix) {
+ if (PatchSuffix != RHSPatchSuffix) {
// Sort empty suffixes higher.
- if (RHS.PatchSuffix.empty())
+ if (RHSPatchSuffix.empty())
return true;
if (PatchSuffix.empty())
return false;
// Provide a lexicographic sort to make this a total ordering.
- return PatchSuffix < RHS.PatchSuffix;
+ return PatchSuffix < RHSPatchSuffix;
}
// The versions are equal.
@@ -1002,20 +1025,19 @@ static StringRef getGCCToolchainDir(const ArgList &Args) {
/// triple.
void
Generic_GCC::GCCInstallationDetector::init(
- const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
- llvm::Triple MultiarchTriple
- = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
+ const llvm::Triple &TargetTriple, const ArgList &Args) {
+ llvm::Triple BiarchVariantTriple =
+ TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
: TargetTriple.get32BitArchVariant();
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
// The library directories which may contain GCC installations.
- SmallVector<StringRef, 4> CandidateLibDirs, CandidateMultiarchLibDirs;
+ SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
// The compatible GCC triples for this particular architecture.
SmallVector<StringRef, 10> CandidateTripleAliases;
- SmallVector<StringRef, 10> CandidateMultiarchTripleAliases;
- CollectLibDirsAndTriples(TargetTriple, MultiarchTriple, CandidateLibDirs,
- CandidateTripleAliases,
- CandidateMultiarchLibDirs,
- CandidateMultiarchTripleAliases);
+ SmallVector<StringRef, 10> CandidateBiarchTripleAliases;
+ CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
+ CandidateTripleAliases, CandidateBiarchLibDirs,
+ CandidateBiarchTripleAliases);
// Compute the set of prefixes for our search.
SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
@@ -1028,9 +1050,18 @@ Generic_GCC::GCCInstallationDetector::init(
Prefixes.push_back(GCCToolchainDir);
} else {
- Prefixes.push_back(D.SysRoot);
- Prefixes.push_back(D.SysRoot + "/usr");
+ // If we have a SysRoot, try that first.
+ if (!D.SysRoot.empty()) {
+ Prefixes.push_back(D.SysRoot);
+ Prefixes.push_back(D.SysRoot + "/usr");
+ }
+
+ // Then look for gcc installed alongside clang.
Prefixes.push_back(D.InstalledDir + "/..");
+
+ // And finally in /usr.
+ if (D.SysRoot.empty())
+ Prefixes.push_back("/usr");
}
// Loop over the various components which exist and select the best GCC
@@ -1047,217 +1078,216 @@ Generic_GCC::GCCInstallationDetector::init(
ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
CandidateTripleAliases[k]);
}
- for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) {
- const std::string LibDir
- = Prefixes[i] + CandidateMultiarchLibDirs[j].str();
+ for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) {
+ const std::string LibDir = Prefixes[i] + CandidateBiarchLibDirs[j].str();
if (!llvm::sys::fs::exists(LibDir))
continue;
- for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke;
+ for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke;
++k)
ScanLibDirForGCCTriple(TargetArch, Args, LibDir,
- CandidateMultiarchTripleAliases[k],
- /*NeedsMultiarchSuffix=*/true);
+ CandidateBiarchTripleAliases[k],
+ /*NeedsBiarchSuffix=*/ true);
}
}
}
+void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
+ for (std::set<std::string>::const_iterator
+ I = CandidateGCCInstallPaths.begin(),
+ E = CandidateGCCInstallPaths.end();
+ I != E; ++I)
+ OS << "Found candidate GCC installation: " << *I << "\n";
+
+ OS << "Selected GCC installation: " << GCCInstallPath << "\n";
+}
+
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
- const llvm::Triple &TargetTriple,
- const llvm::Triple &MultiarchTriple,
+ const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
SmallVectorImpl<StringRef> &LibDirs,
SmallVectorImpl<StringRef> &TripleAliases,
- SmallVectorImpl<StringRef> &MultiarchLibDirs,
- SmallVectorImpl<StringRef> &MultiarchTripleAliases) {
+ SmallVectorImpl<StringRef> &BiarchLibDirs,
+ SmallVectorImpl<StringRef> &BiarchTripleAliases) {
// Declare a bunch of static data sets that we'll select between below. These
// are specifically designed to always refer to string literals to avoid any
// lifetime or initialization issues.
static const char *const AArch64LibDirs[] = { "/lib" };
- static const char *const AArch64Triples[] = {
- "aarch64-none-linux-gnu",
- "aarch64-linux-gnu"
- };
+ static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu",
+ "aarch64-linux-gnu" };
static const char *const ARMLibDirs[] = { "/lib" };
- static const char *const ARMTriples[] = {
- "arm-linux-gnueabi",
- "arm-linux-androideabi"
- };
- static const char *const ARMHFTriples[] = {
- "arm-linux-gnueabihf",
- "armv7hl-redhat-linux-gnueabi"
- };
+ static const char *const ARMTriples[] = { "arm-linux-gnueabi",
+ "arm-linux-androideabi" };
+ static const char *const ARMHFTriples[] = { "arm-linux-gnueabihf",
+ "armv7hl-redhat-linux-gnueabi" };
static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
static const char *const X86_64Triples[] = {
- "x86_64-linux-gnu",
- "x86_64-unknown-linux-gnu",
- "x86_64-pc-linux-gnu",
- "x86_64-redhat-linux6E",
- "x86_64-redhat-linux",
- "x86_64-suse-linux",
- "x86_64-manbo-linux-gnu",
- "x86_64-linux-gnu",
- "x86_64-slackware-linux"
+ "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-pc-linux-gnu",
+ "x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux",
+ "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux"
};
static const char *const X86LibDirs[] = { "/lib32", "/lib" };
static const char *const X86Triples[] = {
- "i686-linux-gnu",
- "i686-pc-linux-gnu",
- "i486-linux-gnu",
- "i386-linux-gnu",
- "i386-redhat-linux6E",
- "i686-redhat-linux",
- "i586-redhat-linux",
- "i386-redhat-linux",
- "i586-suse-linux",
- "i486-slackware-linux",
+ "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", "i386-linux-gnu",
+ "i386-redhat-linux6E", "i686-redhat-linux", "i586-redhat-linux",
+ "i386-redhat-linux", "i586-suse-linux", "i486-slackware-linux",
"i686-montavista-linux"
};
static const char *const MIPSLibDirs[] = { "/lib" };
- static const char *const MIPSTriples[] = { "mips-linux-gnu" };
+ static const char *const MIPSTriples[] = { "mips-linux-gnu",
+ "mips-mti-linux-gnu" };
static const char *const MIPSELLibDirs[] = { "/lib" };
- static const char *const MIPSELTriples[] = {
- "mipsel-linux-gnu",
- "mipsel-linux-android",
- "mips-linux-gnu"
- };
+ static const char *const MIPSELTriples[] = { "mipsel-linux-gnu",
+ "mipsel-linux-android" };
static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
- static const char *const MIPS64Triples[] = { "mips64-linux-gnu" };
+ static const char *const MIPS64Triples[] = { "mips64-linux-gnu",
+ "mips-mti-linux-gnu" };
static const char *const MIPS64ELLibDirs[] = { "/lib64", "/lib" };
- static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu" };
+ static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu",
+ "mips-mti-linux-gnu" };
static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
static const char *const PPCTriples[] = {
- "powerpc-linux-gnu",
- "powerpc-unknown-linux-gnu",
- "powerpc-linux-gnuspe",
- "powerpc-suse-linux",
- "powerpc-montavista-linuxspe"
+ "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
+ "powerpc-suse-linux", "powerpc-montavista-linuxspe"
};
static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
- static const char *const PPC64Triples[] = {
- "powerpc64-linux-gnu",
- "powerpc64-unknown-linux-gnu",
- "powerpc64-suse-linux",
- "ppc64-redhat-linux"
- };
+ static const char *const PPC64Triples[] = { "powerpc64-linux-gnu",
+ "powerpc64-unknown-linux-gnu",
+ "powerpc64-suse-linux",
+ "ppc64-redhat-linux" };
+ static const char *const PPC64LELibDirs[] = { "/lib64", "/lib" };
+ static const char *const PPC64LETriples[] = { "powerpc64le-linux-gnu",
+ "powerpc64le-unknown-linux-gnu",
+ "powerpc64le-suse-linux",
+ "ppc64le-redhat-linux" };
static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
static const char *const SystemZTriples[] = {
- "s390x-linux-gnu",
- "s390x-unknown-linux-gnu",
- "s390x-ibm-linux-gnu",
- "s390x-suse-linux",
- "s390x-redhat-linux"
+ "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
+ "s390x-suse-linux", "s390x-redhat-linux"
};
switch (TargetTriple.getArch()) {
case llvm::Triple::aarch64:
- LibDirs.append(AArch64LibDirs, AArch64LibDirs
- + llvm::array_lengthof(AArch64LibDirs));
- TripleAliases.append(
- AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples));
- MultiarchLibDirs.append(
- AArch64LibDirs, AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs));
- MultiarchTripleAliases.append(
- AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples));
+ LibDirs.append(AArch64LibDirs,
+ AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs));
+ TripleAliases.append(AArch64Triples,
+ AArch64Triples + llvm::array_lengthof(AArch64Triples));
+ BiarchLibDirs.append(AArch64LibDirs,
+ AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs));
+ BiarchTripleAliases.append(
+ AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples));
break;
case llvm::Triple::arm:
case llvm::Triple::thumb:
LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
- TripleAliases.append(
- ARMHFTriples, ARMHFTriples + llvm::array_lengthof(ARMHFTriples));
+ TripleAliases.append(ARMHFTriples,
+ ARMHFTriples + llvm::array_lengthof(ARMHFTriples));
} else {
- TripleAliases.append(
- ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples));
+ TripleAliases.append(ARMTriples,
+ ARMTriples + llvm::array_lengthof(ARMTriples));
}
break;
case llvm::Triple::x86_64:
- LibDirs.append(
- X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
- TripleAliases.append(
- X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples));
- MultiarchLibDirs.append(
- X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
- MultiarchTripleAliases.append(
- X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
+ LibDirs.append(X86_64LibDirs,
+ X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
+ TripleAliases.append(X86_64Triples,
+ X86_64Triples + llvm::array_lengthof(X86_64Triples));
+ BiarchLibDirs.append(X86LibDirs,
+ X86LibDirs + llvm::array_lengthof(X86LibDirs));
+ BiarchTripleAliases.append(X86Triples,
+ X86Triples + llvm::array_lengthof(X86Triples));
break;
case llvm::Triple::x86:
LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
- TripleAliases.append(
- X86Triples, X86Triples + llvm::array_lengthof(X86Triples));
- MultiarchLibDirs.append(
- X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
- MultiarchTripleAliases.append(
- X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples));
+ TripleAliases.append(X86Triples,
+ X86Triples + llvm::array_lengthof(X86Triples));
+ BiarchLibDirs.append(X86_64LibDirs,
+ X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
+ BiarchTripleAliases.append(
+ X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples));
break;
case llvm::Triple::mips:
- LibDirs.append(
- MIPSLibDirs, MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
- TripleAliases.append(
- MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples));
- MultiarchLibDirs.append(
- MIPS64LibDirs, MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
- MultiarchTripleAliases.append(
- MIPS64Triples, MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
+ LibDirs.append(MIPSLibDirs,
+ MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
+ TripleAliases.append(MIPSTriples,
+ MIPSTriples + llvm::array_lengthof(MIPSTriples));
+ BiarchLibDirs.append(MIPS64LibDirs,
+ MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
+ BiarchTripleAliases.append(
+ MIPS64Triples, MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
break;
case llvm::Triple::mipsel:
- LibDirs.append(
- MIPSELLibDirs, MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
- TripleAliases.append(
- MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
- MultiarchLibDirs.append(
- MIPS64ELLibDirs, MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
- MultiarchTripleAliases.append(
- MIPS64ELTriples, MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
+ LibDirs.append(MIPSELLibDirs,
+ MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
+ TripleAliases.append(MIPSELTriples,
+ MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
+ TripleAliases.append(MIPSTriples,
+ MIPSTriples + llvm::array_lengthof(MIPSTriples));
+ BiarchLibDirs.append(
+ MIPS64ELLibDirs,
+ MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
+ BiarchTripleAliases.append(
+ MIPS64ELTriples,
+ MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
break;
case llvm::Triple::mips64:
- LibDirs.append(
- MIPS64LibDirs, MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
- TripleAliases.append(
- MIPS64Triples, MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
- MultiarchLibDirs.append(
- MIPSLibDirs, MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
- MultiarchTripleAliases.append(
- MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples));
+ LibDirs.append(MIPS64LibDirs,
+ MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
+ TripleAliases.append(MIPS64Triples,
+ MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
+ BiarchLibDirs.append(MIPSLibDirs,
+ MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
+ BiarchTripleAliases.append(MIPSTriples,
+ MIPSTriples + llvm::array_lengthof(MIPSTriples));
break;
case llvm::Triple::mips64el:
- LibDirs.append(
- MIPS64ELLibDirs, MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
+ LibDirs.append(MIPS64ELLibDirs,
+ MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
TripleAliases.append(
- MIPS64ELTriples, MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
- MultiarchLibDirs.append(
- MIPSELLibDirs, MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
- MultiarchTripleAliases.append(
- MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
+ MIPS64ELTriples,
+ MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
+ BiarchLibDirs.append(MIPSELLibDirs,
+ MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
+ BiarchTripleAliases.append(
+ MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
+ BiarchTripleAliases.append(
+ MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples));
break;
case llvm::Triple::ppc:
LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
- TripleAliases.append(
- PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
- MultiarchLibDirs.append(
- PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
- MultiarchTripleAliases.append(
- PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples));
+ TripleAliases.append(PPCTriples,
+ PPCTriples + llvm::array_lengthof(PPCTriples));
+ BiarchLibDirs.append(PPC64LibDirs,
+ PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
+ BiarchTripleAliases.append(
+ PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples));
break;
case llvm::Triple::ppc64:
- LibDirs.append(
- PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
- TripleAliases.append(
- PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples));
- MultiarchLibDirs.append(
- PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
- MultiarchTripleAliases.append(
- PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples));
+ LibDirs.append(PPC64LibDirs,
+ PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
+ TripleAliases.append(PPC64Triples,
+ PPC64Triples + llvm::array_lengthof(PPC64Triples));
+ BiarchLibDirs.append(PPCLibDirs,
+ PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
+ BiarchTripleAliases.append(PPCTriples,
+ PPCTriples + llvm::array_lengthof(PPCTriples));
+ break;
+ case llvm::Triple::ppc64le:
+ LibDirs.append(PPC64LELibDirs,
+ PPC64LELibDirs + llvm::array_lengthof(PPC64LELibDirs));
+ TripleAliases.append(PPC64LETriples,
+ PPC64LETriples + llvm::array_lengthof(PPC64LETriples));
break;
case llvm::Triple::systemz:
- LibDirs.append(
- SystemZLibDirs, SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
- TripleAliases.append(
- SystemZTriples, SystemZTriples + llvm::array_lengthof(SystemZTriples));
+ LibDirs.append(SystemZLibDirs,
+ SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
+ TripleAliases.append(SystemZTriples,
+ SystemZTriples + llvm::array_lengthof(SystemZTriples));
break;
default:
@@ -1271,8 +1301,8 @@ Generic_GCC::GCCInstallationDetector::init(
TripleAliases.push_back(TargetTriple.str());
// Also include the multiarch variant if it's different.
- if (TargetTriple.str() != MultiarchTriple.str())
- MultiarchTripleAliases.push_back(MultiarchTriple.str());
+ if (TargetTriple.str() != BiarchTriple.str())
+ BiarchTripleAliases.push_back(BiarchTriple.str());
}
static bool isSoftFloatABI(const ArgList &Args) {
@@ -1299,87 +1329,168 @@ static bool isMips16(const ArgList &Args) {
return A && A->getOption().matches(options::OPT_mips16);
}
+static bool isMips32r2(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_march_EQ,
+ options::OPT_mcpu_EQ);
+
+ return A && A->getValue() == StringRef("mips32r2");
+}
+
+static bool isMips64r2(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_march_EQ,
+ options::OPT_mcpu_EQ);
+
+ return A && A->getValue() == StringRef("mips64r2");
+}
+
static bool isMicroMips(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mmicromips,
options::OPT_mno_micromips);
return A && A->getOption().matches(options::OPT_mmicromips);
}
+static bool isMipsFP64(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mfp64, options::OPT_mfp32);
+ return A && A->getOption().matches(options::OPT_mfp64);
+}
+
+static bool isMipsNan2008(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mnan_EQ);
+ return A && A->getValue() == StringRef("2008");
+}
+
// FIXME: There is the same routine in the Tools.cpp.
static bool hasMipsN32ABIArg(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
return A && (A->getValue() == StringRef("n32"));
}
-static void appendMipsTargetSuffix(std::string &Path,
+static bool hasCrtBeginObj(Twine Path) {
+ return llvm::sys::fs::exists(Path + "/crtbegin.o");
+}
+
+static bool findTargetBiarchSuffix(std::string &Suffix, StringRef Path,
llvm::Triple::ArchType TargetArch,
const ArgList &Args) {
- if (isMips16(Args))
- Path += "/mips16";
- else if (isMicroMips(Args))
- Path += "/micromips";
-
- if (isSoftFloatABI(Args))
- Path += "/soft-float";
+ // FIXME: This routine was only intended to model bi-arch toolchains which
+ // use -m32 and -m64 to swap between variants of a target. It shouldn't be
+ // doing ABI-based builtin location for MIPS.
+ if (hasMipsN32ABIArg(Args))
+ Suffix = "/n32";
+ else if (TargetArch == llvm::Triple::x86_64 ||
+ TargetArch == llvm::Triple::ppc64 ||
+ TargetArch == llvm::Triple::systemz ||
+ TargetArch == llvm::Triple::mips64 ||
+ TargetArch == llvm::Triple::mips64el)
+ Suffix = "/64";
+ else
+ Suffix = "/32";
- if (TargetArch == llvm::Triple::mipsel ||
- TargetArch == llvm::Triple::mips64el)
- Path += "/el";
+ return hasCrtBeginObj(Path + Suffix);
}
-static StringRef getMipsTargetABISuffix(llvm::Triple::ArchType TargetArch,
- const ArgList &Args) {
- if (TargetArch == llvm::Triple::mips64 ||
- TargetArch == llvm::Triple::mips64el)
- return hasMipsN32ABIArg(Args) ? "/n32" : "/64";
-
- return "/32";
-}
+void Generic_GCC::GCCInstallationDetector::findMIPSABIDirSuffix(
+ std::string &Suffix, llvm::Triple::ArchType TargetArch, StringRef Path,
+ const llvm::opt::ArgList &Args) {
+ if (!isMipsArch(TargetArch))
+ return;
-static bool findTargetMultiarchSuffix(std::string &Suffix,
- StringRef Path,
- llvm::Triple::ArchType TargetArch,
- const ArgList &Args) {
- if (isMipsArch(TargetArch)) {
- StringRef ABISuffix = getMipsTargetABISuffix(TargetArch, Args);
+ // Some MIPS toolchains put libraries and object files compiled
+ // using different options in to the sub-directoris which names
+ // reflects the flags used for compilation. For example sysroot
+ // directory might looks like the following examples:
+ //
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips32'
+ // /mips16
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips16'
+ // /el
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips16 -EL'
+ //
+ // or
+ //
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips32r2'
+ // /mips16
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips32r2 -mips16'
+ // /mips32
+ // /usr
+ // /lib <= crt*.o files compiled with '-mips32'
+ //
+ // Unfortunately different toolchains use different and partially
+ // overlapped naming schemes. So we have to make a trick for detection
+ // of using toolchain. We lookup a path which unique for each toolchains.
+
+ bool IsMentorToolChain = hasCrtBeginObj(Path + "/mips16/soft-float");
+ bool IsFSFToolChain = hasCrtBeginObj(Path + "/mips32/mips16/sof");
+
+ if (IsMentorToolChain && IsFSFToolChain)
+ D.Diag(diag::err_drv_unknown_toolchain);
+
+ if (IsMentorToolChain) {
+ if (isMips16(Args))
+ Suffix += "/mips16";
+ else if (isMicroMips(Args))
+ Suffix += "/micromips";
+
+ if (isSoftFloatABI(Args))
+ Suffix += "/soft-float";
+
+ if (TargetArch == llvm::Triple::mipsel ||
+ TargetArch == llvm::Triple::mips64el)
+ Suffix += "/el";
+ } else if (IsFSFToolChain) {
+ if (TargetArch == llvm::Triple::mips ||
+ TargetArch == llvm::Triple::mipsel) {
+ if (isMicroMips(Args))
+ Suffix += "/micromips";
+ else if (isMips32r2(Args))
+ Suffix += "";
+ else
+ Suffix += "/mips32";
- // First build and check a complex path to crtbegin.o
- // depends on command line options (-mips16, -msoft-float, ...)
- // like mips-linux-gnu/4.7/mips16/soft-float/el/crtbegin.o
- appendMipsTargetSuffix(Suffix, TargetArch, Args);
+ if (isMips16(Args))
+ Suffix += "/mips16";
+ } else {
+ if (isMips64r2(Args))
+ Suffix += hasMipsN32ABIArg(Args) ? "/mips64r2" : "/mips64r2/64";
+ else
+ Suffix += hasMipsN32ABIArg(Args) ? "/mips64" : "/mips64/64";
+ }
- if (TargetArch == llvm::Triple::mips64 ||
+ if (TargetArch == llvm::Triple::mipsel ||
TargetArch == llvm::Triple::mips64el)
- Suffix += ABISuffix;
+ Suffix += "/el";
- if (llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o"))
- return true;
+ if (isSoftFloatABI(Args))
+ Suffix += "/sof";
+ else {
+ if (isMipsFP64(Args))
+ Suffix += "/fp64";
- // Then fall back and probe a simple case like
- // mips-linux-gnu/4.7/32/crtbegin.o
- Suffix = ABISuffix;
- return llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o");
+ if (isMipsNan2008(Args))
+ Suffix += "/nan2008";
+ }
}
- if (TargetArch == llvm::Triple::x86_64 ||
- TargetArch == llvm::Triple::ppc64 ||
- TargetArch == llvm::Triple::systemz)
- Suffix = "/64";
- else
- Suffix = "/32";
-
- return llvm::sys::fs::exists(Path + Suffix + "/crtbegin.o");
+ if (!hasCrtBeginObj(Path + Suffix))
+ Suffix.clear();
}
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
llvm::Triple::ArchType TargetArch, const ArgList &Args,
- const std::string &LibDir,
- StringRef CandidateTriple, bool NeedsMultiarchSuffix) {
+ const std::string &LibDir, StringRef CandidateTriple,
+ bool NeedsBiarchSuffix) {
// There are various different suffixes involving the triple we
// check for. We also record what is necessary to walk from each back
// up to the lib directory.
const std::string LibSuffixes[] = {
"/gcc/" + CandidateTriple.str(),
+ // Debian puts cross-compilers in gcc-cross
+ "/gcc-cross/" + CandidateTriple.str(),
"/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
// The Freescale PPC SDK has the gcc libraries in
@@ -1393,14 +1504,15 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
"/i386-linux-gnu/gcc/" + CandidateTriple.str()
};
const std::string InstallSuffixes[] = {
- "/../../..",
- "/../../../..",
- "/../..",
- "/../../../.."
+ "/../../..", // gcc/
+ "/../../..", // gcc-cross/
+ "/../../../..", // <triple>/gcc/
+ "/../..", // <triple>/
+ "/../../../.." // i386-linux-gnu/gcc/<triple>/
};
// Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
- const unsigned NumLibSuffixes = (llvm::array_lengthof(LibSuffixes) -
- (TargetArch != llvm::Triple::x86));
+ const unsigned NumLibSuffixes =
+ (llvm::array_lengthof(LibSuffixes) - (TargetArch != llvm::Triple::x86));
for (unsigned i = 0; i < NumLibSuffixes; ++i) {
StringRef LibSuffix = LibSuffixes[i];
llvm::error_code EC;
@@ -1408,28 +1520,34 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
- static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" };
- if (CandidateVersion < MinVersion)
+ if (CandidateVersion.Major != -1) // Filter obviously bad entries.
+ if (!CandidateGCCInstallPaths.insert(LI->path()).second)
+ continue; // Saw this path before; no need to look at it again.
+ if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= Version)
continue;
+ std::string MIPSABIDirSuffix;
+ findMIPSABIDirSuffix(MIPSABIDirSuffix, TargetArch, LI->path(), Args);
+
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
// libs in a subdirectory named 64. The simple logic we follow is that
// *if* there is a subdirectory of the right name with crtbegin.o in it,
- // we use that. If not, and if not a multiarch triple, we look for
+ // we use that. If not, and if not a biarch triple alias, we look for
// crtbegin.o without the subdirectory.
- std::string MultiarchSuffix;
- if (findTargetMultiarchSuffix(MultiarchSuffix,
- LI->path(), TargetArch, Args)) {
- GCCMultiarchSuffix = MultiarchSuffix;
+ std::string BiarchSuffix;
+ if (findTargetBiarchSuffix(BiarchSuffix,
+ LI->path() + MIPSABIDirSuffix,
+ TargetArch, Args)) {
+ GCCBiarchSuffix = BiarchSuffix;
+ } else if (NeedsBiarchSuffix ||
+ !hasCrtBeginObj(LI->path() + MIPSABIDirSuffix)) {
+ continue;
} else {
- if (NeedsMultiarchSuffix ||
- !llvm::sys::fs::exists(LI->path() + "/crtbegin.o"))
- continue;
- GCCMultiarchSuffix.clear();
+ GCCBiarchSuffix.clear();
}
Version = CandidateVersion;
@@ -1439,6 +1557,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// Linux.
GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str();
GCCParentLibPath = GCCInstallPath + InstallSuffixes[i];
+ GCCMIPSABIDirSuffix = MIPSABIDirSuffix;
IsValid = true;
}
}
@@ -1446,7 +1565,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), GCCInstallation() {
+ : ToolChain(D, Triple, Args), GCCInstallation(getDriver()) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
@@ -1482,6 +1601,11 @@ Tool *Generic_GCC::buildLinker() const {
return new tools::gcc::Link(*this);
}
+void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
+ // Print the information about how we detected the GCC installation.
+ GCCInstallation.print(OS);
+}
+
bool Generic_GCC::IsUnwindTablesDefault() const {
return getArch() == llvm::Triple::x86_64;
}
@@ -1626,7 +1750,6 @@ void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- llvm::sys::Path InstallDir(D.InstalledDir);
std::string Ver(GetGCCLibAndIncVersion());
std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir);
std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver);
@@ -1644,10 +1767,10 @@ void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
const Driver &D = getDriver();
std::string Ver(GetGCCLibAndIncVersion());
- llvm::sys::Path IncludeDir(Hexagon_TC::GetGnuDir(D.InstalledDir));
+ SmallString<128> IncludeDir(Hexagon_TC::GetGnuDir(D.InstalledDir));
- IncludeDir.appendComponent("hexagon/include/c++/");
- IncludeDir.appendComponent(Ver);
+ llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
+ llvm::sys::path::append(IncludeDir, Ver);
addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
}
@@ -1666,40 +1789,47 @@ Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libstdcxx;
}
-static Arg *GetLastHexagonArchArg(const ArgList &Args)
-{
- Arg *A = NULL;
-
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- if ((*it)->getOption().matches(options::OPT_march_EQ) ||
- (*it)->getOption().matches(options::OPT_mcpu_EQ)) {
- A = *it;
- A->claim();
- } else if ((*it)->getOption().matches(options::OPT_m_Joined)) {
- StringRef Value = (*it)->getValue(0);
- if (Value.startswith("v")) {
- A = *it;
- A->claim();
- }
- }
+static int getHexagonVersion(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ);
+ // Select the default CPU (v4) if none was given.
+ if (!A)
+ return 4;
+
+ // FIXME: produce errors if we cannot parse the version.
+ StringRef WhichHexagon = A->getValue();
+ if (WhichHexagon.startswith("hexagonv")) {
+ int Val;
+ if (!WhichHexagon.substr(sizeof("hexagonv") - 1).getAsInteger(10, Val))
+ return Val;
+ }
+ if (WhichHexagon.startswith("v")) {
+ int Val;
+ if (!WhichHexagon.substr(1).getAsInteger(10, Val))
+ return Val;
}
- return A;
+
+ // FIXME: should probably be an error.
+ return 4;
}
StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
{
- // Select the default CPU (v4) if none was given or detection failed.
- Arg *A = GetLastHexagonArchArg (Args);
- if (A) {
- StringRef WhichHexagon = A->getValue();
- if (WhichHexagon.startswith("hexagon"))
- return WhichHexagon.substr(sizeof("hexagon") - 1);
- if (WhichHexagon != "")
- return WhichHexagon;
+ int V = getHexagonVersion(Args);
+ // FIXME: We don't support versions < 4. We should error on them.
+ switch (V) {
+ default:
+ llvm_unreachable("Unexpected version");
+ case 5:
+ return "v5";
+ case 4:
+ return "v4";
+ case 3:
+ return "v3";
+ case 2:
+ return "v2";
+ case 1:
+ return "v1";
}
-
- return "v4";
}
// End Hexagon
@@ -1828,57 +1958,62 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
-Tool *FreeBSD::buildAssembler() const {
- return new tools::freebsd::Assemble(*this);
-}
-
-Tool *FreeBSD::buildLinker() const {
- return new tools::freebsd::Link(*this);
-}
-
-bool FreeBSD::UseSjLjExceptions() const {
- // FreeBSD uses SjLj exceptions on ARM oabi.
- switch (getTriple().getEnvironment()) {
- case llvm::Triple::GNUEABI:
- case llvm::Triple::EABI:
- return false;
-
- default:
- return (getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::thumb);
- }
-}
-
ToolChain::CXXStdlibType
FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
- if (Value == "libc++")
- return ToolChain::CST_Libcxx;
if (Value == "libstdc++")
return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
-
- return getTriple().getOSMajorVersion() >= 10 ? ToolChain::CST_Libcxx :
- ToolChain::CST_Libstdcxx;
+ if (getTriple().getOSMajorVersion() >= 10)
+ return ToolChain::CST_Libcxx;
+ return ToolChain::CST_Libstdcxx;
}
void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+ ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
- if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/v1");
- else
+ break;
+ case ToolChain::CST_Libstdcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/4.2");
- return;
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/4.2/backward");
+ break;
+ }
+}
+
+Tool *FreeBSD::buildAssembler() const {
+ return new tools::freebsd::Assemble(*this);
+}
+
+Tool *FreeBSD::buildLinker() const {
+ return new tools::freebsd::Link(*this);
+}
+bool FreeBSD::UseSjLjExceptions() const {
+ // FreeBSD uses SjLj exceptions on ARM oabi.
+ switch (getTriple().getEnvironment()) {
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::EABI:
+ return false;
+
+ default:
+ return (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb);
+ }
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
@@ -1920,6 +2055,12 @@ NetBSD::GetCXXStdlibType(const ArgList &Args) const {
<< A->getAsString(Args);
}
+ unsigned Major, Minor, Micro;
+ getTriple().getOSVersion(Major, Minor, Micro);
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
+ if (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64)
+ return ToolChain::CST_Libcxx;
+ }
return ToolChain::CST_Libstdcxx;
}
@@ -2019,15 +2160,8 @@ enum Distro {
RHEL4,
RHEL5,
RHEL6,
- Fedora13,
- Fedora14,
- Fedora15,
- Fedora16,
- FedoraRawhide,
- OpenSuse11_3,
- OpenSuse11_4,
- OpenSuse12_1,
- OpenSuse12_2,
+ Fedora,
+ OpenSUSE,
UbuntuHardy,
UbuntuIntrepid,
UbuntuJaunty,
@@ -2039,16 +2173,17 @@ enum Distro {
UbuntuPrecise,
UbuntuQuantal,
UbuntuRaring,
+ UbuntuSaucy,
+ UbuntuTrusty,
UnknownDistro
};
static bool IsRedhat(enum Distro Distro) {
- return (Distro >= Fedora13 && Distro <= FedoraRawhide) ||
- (Distro >= RHEL4 && Distro <= RHEL6);
+ return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6);
}
-static bool IsOpenSuse(enum Distro Distro) {
- return Distro >= OpenSuse11_3 && Distro <= OpenSuse12_2;
+static bool IsOpenSUSE(enum Distro Distro) {
+ return Distro == OpenSUSE;
}
static bool IsDebian(enum Distro Distro) {
@@ -2056,7 +2191,7 @@ static bool IsDebian(enum Distro Distro) {
}
static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuRaring;
+ return Distro >= UbuntuHardy && Distro <= UbuntuTrusty;
}
static Distro DetectDistro(llvm::Triple::ArchType Arch) {
@@ -2080,23 +2215,16 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
.Case("precise", UbuntuPrecise)
.Case("quantal", UbuntuQuantal)
.Case("raring", UbuntuRaring)
+ .Case("saucy", UbuntuSaucy)
+ .Case("trusty", UbuntuTrusty)
.Default(UnknownDistro);
return Version;
}
if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) {
StringRef Data = File.get()->getBuffer();
- if (Data.startswith("Fedora release 16"))
- return Fedora16;
- else if (Data.startswith("Fedora release 15"))
- return Fedora15;
- else if (Data.startswith("Fedora release 14"))
- return Fedora14;
- else if (Data.startswith("Fedora release 13"))
- return Fedora13;
- else if (Data.startswith("Fedora release") &&
- Data.find("Rawhide") != StringRef::npos)
- return FedoraRawhide;
+ if (Data.startswith("Fedora release"))
+ return Fedora;
else if (Data.startswith("Red Hat Enterprise Linux") &&
Data.find("release 6") != StringRef::npos)
return RHEL6;
@@ -2124,19 +2252,13 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) {
return UnknownDistro;
}
- if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File))
- return llvm::StringSwitch<Distro>(File.get()->getBuffer())
- .StartsWith("openSUSE 11.3", OpenSuse11_3)
- .StartsWith("openSUSE 11.4", OpenSuse11_4)
- .StartsWith("openSUSE 12.1", OpenSuse12_1)
- .StartsWith("openSUSE 12.2", OpenSuse12_2)
- .Default(UnknownDistro);
+ if (llvm::sys::fs::exists("/etc/SuSE-release"))
+ return OpenSUSE;
- bool Exists;
- if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists)
+ if (llvm::sys::fs::exists("/etc/exherbo-release"))
return Exherbo;
- if (!llvm::sys::fs::exists("/etc/arch-release", Exists) && Exists)
+ if (llvm::sys::fs::exists("/etc/arch-release"))
return ArchLinux;
return UnknownDistro;
@@ -2181,6 +2303,7 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple,
case llvm::Triple::aarch64:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
+ return TargetTriple.str();
case llvm::Triple::mips:
if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu"))
return "mips-linux-gnu";
@@ -2198,6 +2321,9 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple,
case llvm::Triple::ppc64:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu"))
return "powerpc64-linux-gnu";
+ case llvm::Triple::ppc64le:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
+ return "powerpc64le-linux-gnu";
return TargetTriple.str();
}
}
@@ -2206,34 +2332,28 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
}
-static bool isMipsR2Arch(llvm::Triple::ArchType Arch,
- const ArgList &Args) {
- if (Arch != llvm::Triple::mips &&
- Arch != llvm::Triple::mipsel)
- return false;
-
- Arg *A = Args.getLastArg(options::OPT_march_EQ,
- options::OPT_mcpu_EQ,
- options::OPT_mips_CPUs_Group);
-
- if (!A)
- return false;
-
- if (A->getOption().matches(options::OPT_mips_CPUs_Group))
- return A->getOption().matches(options::OPT_mips32r2);
-
- return A->getValue() == StringRef("mips32r2");
-}
-
static StringRef getMultilibDir(const llvm::Triple &Triple,
const ArgList &Args) {
- if (!isMipsArch(Triple.getArch()))
- return Triple.isArch32Bit() ? "lib32" : "lib64";
+ if (isMipsArch(Triple.getArch())) {
+ // lib32 directory has a special meaning on MIPS targets.
+ // It contains N32 ABI binaries. Use this folder if produce
+ // code for N32 ABI only.
+ if (hasMipsN32ABIArg(Args))
+ return "lib32";
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+ }
- // lib32 directory has a special meaning on MIPS targets.
- // It contains N32 ABI binaries. Use this folder if produce
- // code for N32 ABI only.
- if (hasMipsN32ABIArg(Args))
+ // It happens that only x86 and PPC use the 'lib32' variant of multilib, and
+ // using that variant while targeting other architectures causes problems
+ // because the libraries are laid out in shared system roots that can't cope
+ // with a 'lib32' multilib search path being considered. So we only enable
+ // them when we know we may need it.
+ //
+ // FIXME: This is a bit of a hack. We should really unify this code for
+ // reasoning about multilib spellings with the lib dir spellings in the
+ // GCCInstallationDetector, but that is a more significant refactoring.
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::ppc)
return "lib32";
return Triple.isArch32Bit() ? "lib" : "lib64";
@@ -2241,12 +2361,18 @@ static StringRef getMultilibDir(const llvm::Triple &Triple,
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- GCCInstallation.init(D, Triple, Args);
+ GCCInstallation.init(Triple, Args);
llvm::Triple::ArchType Arch = Triple.getArch();
- std::string SysRoot = computeSysRoot(Args);
-
- // OpenSuse stores the linker with the compiler, add that to the search
- // path.
+ std::string SysRoot = computeSysRoot();
+
+ // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
+ // least) put various tools in a triple-prefixed directory off of the parent
+ // of the GCC installation. We use the GCC triple here to ensure that we end
+ // up with tools that support the same amount of cross compiling as the
+ // detected GCC installation. For example, if we find a GCC installation
+ // targeting x86_64, but it is a bi-arch GCC installation, it can also be
+ // used to target i386.
+ // FIXME: This seems unlikely to be Linux-specific.
ToolChain::path_list &PPaths = getProgramPaths();
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
GCCInstallation.getTriple().str() + "/bin").str());
@@ -2255,7 +2381,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Distro Distro = DetectDistro(Arch);
- if (IsOpenSuse(Distro) || IsUbuntu(Distro)) {
+ if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
@@ -2275,11 +2401,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// ABI requires a mapping between the GOT and the symbol table.
// Android loader does not support .gnu.hash.
if (!IsMips && !IsAndroid) {
- if (IsRedhat(Distro) || IsOpenSuse(Distro) ||
+ if (IsRedhat(Distro) || IsOpenSUSE(Distro) ||
(IsUbuntu(Distro) && Distro >= UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
- if (IsDebian(Distro) || IsOpenSuse(Distro) || Distro == UbuntuLucid ||
+ if (IsDebian(Distro) || IsOpenSUSE(Distro) || Distro == UbuntuLucid ||
Distro == UbuntuJaunty || Distro == UbuntuKarmic)
ExtraOpts.push_back("--hash-style=both");
}
@@ -2288,12 +2414,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("--no-add-needed");
if (Distro == DebianSqueeze || Distro == DebianWheezy ||
- Distro == DebianJessie || IsOpenSuse(Distro) ||
+ Distro == DebianJessie || IsOpenSUSE(Distro) ||
(IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) ||
(IsUbuntu(Distro) && Distro >= UbuntuKarmic))
ExtraOpts.push_back("--build-id");
- if (IsOpenSuse(Distro))
+ if (IsOpenSUSE(Distro))
ExtraOpts.push_back("--enable-new-dtags");
// The selection of paths to try here is designed to match the patterns which
@@ -2311,15 +2437,43 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath = GCCInstallation.getParentLibPath();
- if (IsAndroid && isMipsR2Arch(Triple.getArch(), Args))
- addPathIfExists(GCCInstallation.getInstallPath() +
- GCCInstallation.getMultiarchSuffix() +
- "/mips-r2",
- Paths);
- else
+ // Sourcery CodeBench MIPS toolchain holds some libraries under
+ // a biarch-like suffix of the GCC installation.
+ //
+ // FIXME: It would be cleaner to model this as a variant of bi-arch. IE,
+ // instead of a '64' biarch suffix it would be 'el' or something.
+ if (IsAndroid && IsMips && isMips32r2(Args)) {
+ assert(GCCInstallation.getBiarchSuffix().empty() &&
+ "Unexpected bi-arch suffix");
+ addPathIfExists(GCCInstallation.getInstallPath() + "/mips-r2", Paths);
+ } else {
addPathIfExists((GCCInstallation.getInstallPath() +
- GCCInstallation.getMultiarchSuffix()),
+ GCCInstallation.getMIPSABIDirSuffix() +
+ GCCInstallation.getBiarchSuffix()),
Paths);
+ }
+
+ // GCC cross compiling toolchains will install target libraries which ship
+ // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
+ // any part of the GCC installation in
+ // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
+ // debatable, but is the reality today. We need to search this tree even
+ // when we have a sysroot somewhere else. It is the responsibility of
+ // whomever is doing the cross build targetting a sysroot using a GCC
+ // installation that is *not* within the system root to ensure two things:
+ //
+ // 1) Any DSOs that are linked in from this tree or from the install path
+ // above must be preasant on the system root and found via an
+ // appropriate rpath.
+ // 2) There must not be libraries installed into
+ // <prefix>/<triple>/<libdir> unless they should be preferred over
+ // those within the system root.
+ //
+ // Note that this matches the GCC behavior. See the below comment for where
+ // Clang diverges from GCC's behavior.
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib +
+ GCCInstallation.getMIPSABIDirSuffix(),
+ Paths);
// If the GCC installation we found is inside of the sysroot, we want to
// prefer libraries installed in the parent prefix of the GCC installation.
@@ -2327,55 +2481,48 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// outside of the system root as that can pick up unintended libraries.
// This usually happens when there is an external cross compiler on the
// host system, and a more minimal sysroot available that is the target of
- // the cross.
+ // the cross. Note that GCC does include some of these directories in some
+ // configurations but this seems somewhere between questionable and simply
+ // a bug.
if (StringRef(LibPath).startswith(SysRoot)) {
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib,
- Paths);
addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
addPathIfExists(LibPath + "/../" + Multilib, Paths);
}
- // On Android, libraries in the parent prefix of the GCC installation are
- // preferred to the ones under sysroot.
- if (IsAndroid) {
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths);
- }
- // Sourcery CodeBench MIPS toolchain holds some libraries under
- // the parent prefix of the GCC installation.
- if (IsMips) {
- std::string Suffix;
- appendMipsTargetSuffix(Suffix, Arch, Args);
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" +
- Multilib + Suffix,
- Paths);
- }
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths);
addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/usr/lib/../" + Multilib, Paths);
- // Try walking via the GCC triple path in case of multiarch GCC
+ // Try walking via the GCC triple path in case of biarch or multiarch GCC
// installations with strange symlinks.
- if (GCCInstallation.isValid())
+ if (GCCInstallation.isValid()) {
addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
"/../../" + Multilib, Paths);
- // Add the non-multilib suffixed paths (if potentially different).
- if (GCCInstallation.isValid()) {
+ // Add the non-multilib suffixed paths (if potentially different).
const std::string &LibPath = GCCInstallation.getParentLibPath();
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
- if (!GCCInstallation.getMultiarchSuffix().empty())
- addPathIfExists(GCCInstallation.getInstallPath(), Paths);
+ if (!GCCInstallation.getBiarchSuffix().empty())
+ addPathIfExists(GCCInstallation.getInstallPath() +
+ GCCInstallation.getMIPSABIDirSuffix(), Paths);
- if (StringRef(LibPath).startswith(SysRoot)) {
- addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths);
+ // See comments above on the multilib variant for details of why this is
+ // included even from outside the sysroot.
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() +
+ "/lib" + GCCInstallation.getMIPSABIDirSuffix(), Paths);
+
+ // See comments above on the multilib variant for details of why this is
+ // only included from within the sysroot.
+ if (StringRef(LibPath).startswith(SysRoot))
addPathIfExists(LibPath, Paths);
- }
}
addPathIfExists(SysRoot + "/lib", Paths);
addPathIfExists(SysRoot + "/usr/lib", Paths);
+}
- IsPIEDefault = SanitizerArgs(*this, Args).hasZeroBaseShadow();
+bool FreeBSD::HasNativeLLVMSupport() const {
+ return true;
}
bool Linux::HasNativeLLVMSupport() const {
@@ -2393,8 +2540,8 @@ Tool *Linux::buildAssembler() const {
void Linux::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
- bool UseInitArrayDefault
- = V >= Generic_GCC::GCCVersion::Parse("4.7.0") ||
+ bool UseInitArrayDefault =
+ !V.isOlderThan(4, 7, 0) ||
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getEnvironment() == llvm::Triple::Android;
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
@@ -2403,25 +2550,39 @@ void Linux::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-fuse-init-array");
}
-std::string Linux::computeSysRoot(const ArgList &Args) const {
+std::string Linux::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;
if (!GCCInstallation.isValid() || !isMipsArch(getTriple().getArch()))
return std::string();
- std::string Path =
- (GCCInstallation.getInstallPath() +
- "/../../../../" + GCCInstallation.getTriple().str() + "/libc").str();
- appendMipsTargetSuffix(Path, getTriple().getArch(), Args);
+ // Standalone MIPS toolchains use different names for sysroot folder
+ // and put it into different places. Here we try to check some known
+ // variants.
+
+ const StringRef InstallDir = GCCInstallation.getInstallPath();
+ const StringRef TripleStr = GCCInstallation.getTriple().str();
+ const StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix();
+
+ std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" +
+ MIPSABIDirSuffix).str();
+
+ if (llvm::sys::fs::exists(Path))
+ return Path;
+
+ Path = (InstallDir + "/../../../../sysroot" + MIPSABIDirSuffix).str();
+
+ if (llvm::sys::fs::exists(Path))
+ return Path;
- return llvm::sys::fs::exists(Path) ? Path : "";
+ return std::string();
}
void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();
- std::string SysRoot = computeSysRoot(DriverArgs);
+ std::string SysRoot = computeSysRoot();
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
@@ -2430,8 +2591,8 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
- llvm::sys::Path P(D.ResourceDir);
- P.appendComponent("include");
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P.str());
}
@@ -2457,15 +2618,17 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Sourcery CodeBench and modern FSF Mips toolchains put extern C
// system includes under three additional directories.
if (GCCInstallation.isValid() && isMipsArch(getTriple().getArch())) {
- addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
- GCCInstallation.getInstallPath() +
- "/include");
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args, GCCInstallation.getInstallPath() + "/include");
- addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
- GCCInstallation.getInstallPath() +
- "/../../../../" +
- GCCInstallation.getTriple().str() +
- "/libc/usr/include");
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() + "/../../../../" +
+ GCCInstallation.getTriple().str() + "/libc/usr/include");
+
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() + "/../../../../sysroot/usr/include");
}
// Implement generic Debian multiarch support.
@@ -2475,8 +2638,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// FIXME: These are older forms of multiarch. It's not clear that they're
// in use in any released version of Debian, so we should consider
// removing them.
- "/usr/include/i686-linux-gnu/64",
- "/usr/include/i486-linux-gnu/64"
+ "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"
};
const StringRef X86MultiarchIncludeDirs[] = {
"/usr/include/i386-linux-gnu",
@@ -2484,8 +2646,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// FIXME: These are older forms of multiarch. It's not clear that they're
// in use in any released version of Debian, so we should consider
// removing them.
- "/usr/include/x86_64-linux-gnu/32",
- "/usr/include/i686-linux-gnu",
+ "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
"/usr/include/i486-linux-gnu"
};
const StringRef AArch64MultiarchIncludeDirs[] = {
@@ -2566,15 +2727,17 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
/// libstdc++ installation.
/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
Twine TargetArchDir,
- Twine MultiLibSuffix,
+ Twine BiarchSuffix,
+ Twine MIPSABIDirSuffix,
const ArgList &DriverArgs,
ArgStringList &CC1Args) {
- if (!addLibStdCXXIncludePaths(Base+Suffix, TargetArchDir + MultiLibSuffix,
+ if (!addLibStdCXXIncludePaths(Base + Suffix,
+ TargetArchDir + MIPSABIDirSuffix + BiarchSuffix,
DriverArgs, CC1Args))
return false;
addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix
- + MultiLibSuffix);
+ + MIPSABIDirSuffix + BiarchSuffix);
return true;
}
@@ -2602,37 +2765,39 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
- StringRef Version = GCCInstallation.getVersion().Text;
StringRef TripleStr = GCCInstallation.getTriple().str();
+ StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix();
+ StringRef BiarchSuffix = GCCInstallation.getBiarchSuffix();
+ const GCCVersion &Version = GCCInstallation.getVersion();
- if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
- "/c++/" + Version.str(),
- TripleStr,
- GCCInstallation.getMultiarchSuffix(),
- DriverArgs, CC1Args))
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+ "/c++/" + Version.Text, TripleStr, BiarchSuffix,
+ MIPSABIDirSuffix, DriverArgs, CC1Args))
return;
const std::string IncludePathCandidates[] = {
// Gentoo is weird and places its headers inside the GCC install, so if the
- // first attempt to find the headers fails, try this pattern.
- InstallDir.str() + "/include/g++-v4",
+ // first attempt to find the headers fails, try these patterns.
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
+ Version.MinorStr,
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr,
// Android standalone toolchain has C++ headers in yet another place.
- LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.str(),
+ LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
// without a subdirectory corresponding to the gcc version.
LibDir.str() + "/../include/c++",
};
for (unsigned i = 0; i < llvm::array_lengthof(IncludePathCandidates); ++i) {
- if (addLibStdCXXIncludePaths(IncludePathCandidates[i], (TripleStr +
- GCCInstallation.getMultiarchSuffix()),
- DriverArgs, CC1Args))
+ if (addLibStdCXXIncludePaths(IncludePathCandidates[i],
+ TripleStr + MIPSABIDirSuffix + BiarchSuffix,
+ DriverArgs, CC1Args))
break;
}
}
bool Linux::isPIEDefault() const {
- return IsPIEDefault;
+ return getSanitizerArgs().hasZeroBaseShadow();
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
@@ -2660,3 +2825,77 @@ Tool *DragonFly::buildAssembler() const {
Tool *DragonFly::buildLinker() const {
return new tools::dragonfly::Link(*this);
}
+
+
+/// XCore tool chain
+XCore::XCore(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) : ToolChain(D, Triple, Args) {
+ // ProgramPaths are found via 'PATH' environment variable.
+}
+
+Tool *XCore::buildAssembler() const {
+ return new tools::XCore::Assemble(*this);
+}
+
+Tool *XCore::buildLinker() const {
+ return new tools::XCore::Link(*this);
+}
+
+bool XCore::isPICDefault() const {
+ return false;
+}
+
+bool XCore::isPIEDefault() const {
+ return false;
+}
+
+bool XCore::isPICDefaultForced() const {
+ return false;
+}
+
+bool XCore::SupportsProfiling() const {
+ return false;
+}
+
+bool XCore::hasBlocksRuntime() const {
+ return false;
+}
+
+
+void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+ if (const char *cl_include_dir = getenv("XCC_C_INCLUDE_PATH")) {
+ SmallVector<StringRef, 4> Dirs;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
+ StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
+ ArrayRef<StringRef> DirVec(Dirs);
+ addSystemIncludes(DriverArgs, CC1Args, DirVec);
+ }
+}
+
+void XCore::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ CC1Args.push_back("-nostdsysteminc");
+}
+
+void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+ if (const char *cl_include_dir = getenv("XCC_CPLUS_INCLUDE_PATH")) {
+ SmallVector<StringRef, 4> Dirs;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
+ StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
+ ArrayRef<StringRef> DirVec(Dirs);
+ addSystemIncludes(DriverArgs, CC1Args, DirVec);
+ }
+}
+
+void XCore::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // We don't output any lib args. This is handled by xcc.
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
index 50145e7..ba794a7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
@@ -16,6 +16,8 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Compiler.h"
+#include <vector>
+#include <set>
namespace clang {
namespace driver {
@@ -48,11 +50,18 @@ protected:
/// \brief The parsed major, minor, and patch numbers.
int Major, Minor, Patch;
+ /// \brief The text of the parsed major, and major+minor versions.
+ std::string MajorStr, MinorStr;
+
/// \brief Any textual suffix on the patch number.
std::string PatchSuffix;
static GCCVersion Parse(StringRef VersionText);
- bool operator<(const GCCVersion &RHS) const;
+ bool isOlderThan(int RHSMajor, int RHSMinor, int RHSPatch,
+ StringRef RHSPatchSuffix = StringRef()) const;
+ bool operator<(const GCCVersion &RHS) const {
+ return isOlderThan(RHS.Major, RHS.Minor, RHS.Patch, RHS.PatchSuffix);
+ }
bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
@@ -66,21 +75,25 @@ protected:
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
-
bool IsValid;
+ const Driver &D;
llvm::Triple GCCTriple;
// FIXME: These might be better as path objects.
std::string GCCInstallPath;
- std::string GCCMultiarchSuffix;
+ std::string GCCBiarchSuffix;
std::string GCCParentLibPath;
+ std::string GCCMIPSABIDirSuffix;
GCCVersion Version;
+ // We retain the list of install paths that were considered and rejected in
+ // order to print out detailed information in verbose mode.
+ std::set<std::string> CandidateGCCInstallPaths;
+
public:
- GCCInstallationDetector() : IsValid(false) {}
- void init(const Driver &D, const llvm::Triple &TargetTriple,
- const ArgList &Args);
+ GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
+ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
/// \brief Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
@@ -91,37 +104,62 @@ protected:
/// \brief Get the detected GCC installation path.
StringRef getInstallPath() const { return GCCInstallPath; }
- /// \brief Get the detected GCC installation path suffix for multiarch GCCs.
- StringRef getMultiarchSuffix() const { return GCCMultiarchSuffix; }
+ /// \brief Get the detected GCC installation path suffix for the bi-arch
+ /// target variant.
+ StringRef getBiarchSuffix() const { return GCCBiarchSuffix; }
/// \brief Get the detected GCC parent lib path.
StringRef getParentLibPath() const { return GCCParentLibPath; }
+ /// \brief Get the detected GCC MIPS ABI directory suffix.
+ ///
+ /// This is used as a suffix both to the install directory of GCC and as
+ /// a suffix to its parent lib path in order to select a MIPS ABI-specific
+ /// subdirectory.
+ ///
+ /// This will always be empty for any non-MIPS target.
+ ///
+ // FIXME: This probably shouldn't exist at all, and should be factored
+ // into the multiarch and/or biarch support. Please don't add more uses of
+ // this interface, it is meant as a legacy crutch for the MIPS driver
+ // logic.
+ StringRef getMIPSABIDirSuffix() const { return GCCMIPSABIDirSuffix; }
+
/// \brief Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }
+ /// \brief Print information about the detected GCC installation.
+ void print(raw_ostream &OS) const;
+
private:
- static void CollectLibDirsAndTriples(
- const llvm::Triple &TargetTriple,
- const llvm::Triple &MultiarchTriple,
- SmallVectorImpl<StringRef> &LibDirs,
- SmallVectorImpl<StringRef> &TripleAliases,
- SmallVectorImpl<StringRef> &MultiarchLibDirs,
- SmallVectorImpl<StringRef> &MultiarchTripleAliases);
+ static void
+ CollectLibDirsAndTriples(const llvm::Triple &TargetTriple,
+ const llvm::Triple &BiarchTriple,
+ SmallVectorImpl<StringRef> &LibDirs,
+ SmallVectorImpl<StringRef> &TripleAliases,
+ SmallVectorImpl<StringRef> &BiarchLibDirs,
+ SmallVectorImpl<StringRef> &BiarchTripleAliases);
void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch,
- const ArgList &Args,
+ const llvm::opt::ArgList &Args,
const std::string &LibDir,
StringRef CandidateTriple,
- bool NeedsMultiarchSuffix = false);
+ bool NeedsBiarchSuffix = false);
+
+ void findMIPSABIDirSuffix(std::string &Suffix,
+ llvm::Triple::ArchType TargetArch, StringRef Path,
+ const llvm::opt::ArgList &Args);
};
GCCInstallationDetector GCCInstallation;
public:
- Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Generic_GCC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
~Generic_GCC();
+ virtual void printVerboseInfo(raw_ostream &OS) const;
+
virtual bool IsUnwindTablesDefault() const;
virtual bool isPICDefault() const;
virtual bool isPIEDefault() const;
@@ -191,13 +229,14 @@ private:
std::string iOSVersionMin;
private:
- void AddDeploymentTarget(DerivedArgList &Args) const;
+ void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
public:
- Darwin(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Darwin(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
~Darwin();
- std::string ComputeEffectiveClangTriple(const ArgList &Args,
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const;
/// @name Darwin Specific Toolchain API
@@ -247,7 +286,7 @@ public:
/// getDarwinArchName - Get the "Darwin" arch name for a particular compiler
/// invocation. For example, Darwin treats different ARM variations as
/// distinct architectures.
- StringRef getDarwinArchName(const ArgList &Args) const;
+ StringRef getDarwinArchName(const llvm::opt::ArgList &Args) const;
bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
assert(isTargetIPhoneOS() && "Unexpected call for OS X target!");
@@ -260,14 +299,15 @@ public:
}
/// AddLinkARCArgs - Add the linker arguments to link the ARC runtime library.
- virtual void AddLinkARCArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const = 0;
-
+ virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::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;
-
+ virtual void
+ AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const = 0;
+
/// }
/// @name ToolChain Implementation
/// {
@@ -279,8 +319,9 @@ public:
virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const;
virtual bool hasBlocksRuntime() const;
- virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const;
+ virtual llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const;
virtual bool IsBlocksDefault() const {
// Always allow blocks on Darwin; users interested in versioning are
@@ -288,19 +329,8 @@ public:
return true;
}
virtual bool IsIntegratedAssemblerDefault() const {
-#ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER
- return false;
-#else
// Default integrated assembler to on for Darwin.
return true;
-#endif
- }
- virtual bool IsStrictAliasingDefault() const {
-#ifdef DISABLE_DEFAULT_STRICT_ALIASING
- return false;
-#else
- return ToolChain::IsStrictAliasingDefault();
-#endif
}
virtual bool IsMathErrnoDefault() const {
@@ -353,35 +383,38 @@ public:
/// DarwinClang - The Darwin toolchain used by Clang.
class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
public:
- DarwinClang(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ DarwinClang(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
/// @name Darwin ToolChain Implementation
/// {
- virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const;
- void AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
+ virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
const char *DarwinStaticLib,
bool AlwaysLink = false) const;
- virtual void AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const;
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
- virtual void AddCCKextLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const;
+ virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
- virtual void AddLinkARCArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const;
+ virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
/// }
};
/// Darwin_Generic_GCC - Generic Darwin tool chain using gcc.
class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC {
public:
- Darwin_Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_GCC(D, Triple, Args) {}
+ Darwin_Generic_GCC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {}
- std::string ComputeEffectiveClangTriple(const ArgList &Args,
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const;
virtual bool isPICDefault() const { return false; }
@@ -390,8 +423,9 @@ public:
class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
virtual void anchor();
public:
- Generic_ELF(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
- : Generic_GCC(D, Triple, Args) {}
+ Generic_ELF(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {}
virtual bool IsIntegratedAssemblerDefault() const {
// Default integrated assembler to on for x86.
@@ -403,7 +437,8 @@ public:
class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC {
public:
- AuroraUX(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ AuroraUX(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
protected:
virtual Tool *buildAssembler() const;
@@ -412,7 +447,8 @@ protected:
class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
public:
- Solaris(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Solaris(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsIntegratedAssemblerDefault() const { return true; }
protected:
@@ -424,10 +460,16 @@ protected:
class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
public:
- OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ OpenBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
+ virtual bool isPIEDefault() const { return true; }
+
+ virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
+ return 1;
+ }
protected:
virtual Tool *buildAssembler() const;
@@ -436,16 +478,18 @@ protected:
class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF {
public:
- Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Bitrig(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
virtual bool IsObjCLegacyDispatchDefault() const { return false; }
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual void AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
return 1;
}
@@ -457,15 +501,23 @@ protected:
class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
public:
- FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
-
- virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+ FreeBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ virtual bool HasNativeLLVMSupport() const;
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual bool IsIntegratedAssemblerDefault() const {
+ if (getTriple().getArch() == llvm::Triple::ppc ||
+ getTriple().getArch() == llvm::Triple::ppc64)
+ return true;
+ return Generic_ELF::IsIntegratedAssemblerDefault();
+ }
virtual bool UseSjLjExceptions() const;
protected:
@@ -475,15 +527,25 @@ protected:
class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
public:
- NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ NetBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsMathErrnoDefault() const { return false; }
virtual bool IsObjCNonFragileABIDefault() const { return true; }
- virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+ virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const;
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual bool IsUnwindTablesDefault() const {
+ return true;
+ }
+ virtual bool IsIntegratedAssemblerDefault() const {
+ if (getTriple().getArch() == llvm::Triple::ppc)
+ return true;
+ return Generic_ELF::IsIntegratedAssemblerDefault();
+ }
protected:
virtual Tool *buildAssembler() const;
@@ -492,7 +554,8 @@ protected:
class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
public:
- Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Minix(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
protected:
virtual Tool *buildAssembler() const;
@@ -501,7 +564,8 @@ protected:
class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
public:
- DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ DragonFly(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsMathErrnoDefault() const { return false; }
@@ -512,21 +576,23 @@ protected:
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
public:
- Linux(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Linux(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool HasNativeLLVMSupport() const;
- virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual void addClangTargetOptions(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
virtual bool isPIEDefault() const;
std::string Linker;
std::vector<std::string> ExtraOpts;
- bool IsPIEDefault;
protected:
virtual Tool *buildAssembler() const;
@@ -535,14 +601,15 @@ protected:
private:
static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
Twine TargetArchDir,
- Twine MultiLibSuffix,
- const ArgList &DriverArgs,
- ArgStringList &CC1Args);
+ Twine BiarchSuffix,
+ Twine MIPSABIDirSuffix,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args);
static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
- const ArgList &DriverArgs,
- ArgStringList &CC1Args);
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args);
- std::string computeSysRoot(const ArgList &Args) const;
+ std::string computeSysRoot() const;
};
class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
@@ -553,28 +620,30 @@ protected:
public:
Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args);
+ const llvm::opt::ArgList &Args);
~Hexagon_TC();
- virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual CXXStdlibType GetCXXStdlibType(const ArgList &Args) const;
+ virtual void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
static std::string GetGnuDir(const std::string &InstalledDir);
- static StringRef GetTargetCPU(const ArgList &Args);
+ static StringRef GetTargetCPU(const llvm::opt::ArgList &Args);
};
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
public:
- TCEToolChain(const Driver &D, const llvm::Triple& Triple,
- const ArgList &Args);
+ TCEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
~TCEToolChain();
bool IsMathErrnoDefault() const;
@@ -585,7 +654,8 @@ public:
class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
public:
- Windows(const Driver &D, const llvm::Triple& Triple, const ArgList &Args);
+ Windows(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
virtual bool IsIntegratedAssemblerDefault() const;
virtual bool IsUnwindTablesDefault() const;
@@ -593,15 +663,42 @@ public:
virtual bool isPIEDefault() const;
virtual bool isPICDefaultForced() const;
- virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
- virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const;
+ virtual void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
protected:
virtual Tool *buildLinker() const;
virtual Tool *buildAssembler() const;
};
+
+class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain {
+public:
+ XCore(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+protected:
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+public:
+ virtual bool isPICDefault() const;
+ virtual bool isPIEDefault() const;
+ virtual bool isPICDefaultForced() const;
+ virtual bool SupportsProfiling() const;
+ virtual bool hasBlocksRuntime() const;
+ virtual void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 26b69f3..3529fc7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -7,43 +7,48 @@
//
//===----------------------------------------------------------------------===//
-#include <sys/stat.h>
#include "Tools.h"
#include "InputInfo.h"
-#include "SanitizerArgs.h"
#include "ToolChains.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Action.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Job.h"
-#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
+#include <sys/stat.h>
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
+using namespace llvm::opt;
/// 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.CCCIsCPP)
+ if (!Args.hasArg(options::OPT_E) && !D.CCCIsCPP())
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-E";
}
@@ -107,7 +112,7 @@ static void addDirectoryList(const ArgList &Args,
return;
StringRef::size_type Delim;
- while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) {
+ while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
if (Delim == 0) { // Leading colon.
if (CombinedArg) {
CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
@@ -223,7 +228,9 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args,
}
static bool forwardToGCC(const Option &O) {
- return !O.hasFlag(options::NoForward) &&
+ // Don't forward inputs from the original command line. They are added from
+ // InputInfoList.
+ return O.getKind() != Option::InputClass &&
!O.hasFlag(options::DriverOption) &&
!O.hasFlag(options::LinkerInput);
}
@@ -339,32 +346,28 @@ void Clang::AddPreprocessingOptions(Compilation &C,
bool FoundPTH = false;
bool FoundPCH = false;
- llvm::sys::Path P(A->getValue());
- bool Exists;
+ SmallString<128> P(A->getValue());
+ // We want the files to have a name like foo.h.pch. Add a dummy extension
+ // so that replace_extension does the right thing.
+ P += ".dummy";
if (UsePCH) {
- P.appendSuffix("pch");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ llvm::sys::path::replace_extension(P, "pch");
+ if (llvm::sys::fs::exists(P.str()))
FoundPCH = true;
- else
- P.eraseSuffix();
}
if (!FoundPCH) {
- P.appendSuffix("pth");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ llvm::sys::path::replace_extension(P, "pth");
+ if (llvm::sys::fs::exists(P.str()))
FoundPTH = true;
- else
- P.eraseSuffix();
}
if (!FoundPCH && !FoundPTH) {
- P.appendSuffix("gch");
- if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ llvm::sys::path::replace_extension(P, "gch");
+ if (llvm::sys::fs::exists(P.str())) {
FoundPCH = UsePCH;
FoundPTH = !UsePCH;
}
- else
- P.eraseSuffix();
}
if (FoundPCH || FoundPTH) {
@@ -446,6 +449,7 @@ void Clang::AddPreprocessingOptions(Compilation &C,
// FIXME: tblgen this, or kill it!
static const char *getLLVMArchSuffixForARM(StringRef CPU) {
return llvm::StringSwitch<const char *>(CPU)
+ .Case("strongarm", "v4")
.Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
.Cases("arm720t", "arm9", "arm9tdmi", "v4t")
.Cases("arm920", "arm920t", "arm922t", "v4t")
@@ -458,13 +462,14 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) {
.Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .Cases("cortex-a9", "cortex-a15", "v7")
- .Case("cortex-r5", "v7r")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
+ .Cases("cortex-r4", "cortex-r5", "v7r")
.Case("cortex-m0", "v6m")
.Case("cortex-m3", "v7m")
.Case("cortex-m4", "v7em")
.Case("cortex-a9-mp", "v7f")
.Case("swift", "v7s")
+ .Cases("cortex-a53", "cortex-a57", "v8")
.Default("");
}
@@ -494,6 +499,11 @@ static std::string getARMTargetCPU(const ArgList &Args,
MArch = Triple.getArchName();
}
+ if (Triple.getOS() == llvm::Triple::NetBSD) {
+ if (MArch == "armv6")
+ return "arm1176jzf-s";
+ }
+
// Handle -march=native.
std::string NativeMArch;
if (MArch == "native") {
@@ -510,7 +520,8 @@ static std::string getARMTargetCPU(const ArgList &Args,
.Cases("armv2", "armv2a","arm2")
.Case("armv3", "arm6")
.Case("armv3m", "arm7m")
- .Cases("armv4", "armv4t", "arm7tdmi")
+ .Case("armv4", "strongarm")
+ .Case("armv4t", "arm7tdmi")
.Cases("armv5", "armv5t", "arm10tdmi")
.Cases("armv5e", "armv5te", "arm1022e")
.Case("armv5tej", "arm926ej-s")
@@ -525,13 +536,35 @@ static std::string getARMTargetCPU(const ArgList &Args,
.Cases("armv7s", "armv7-s", "swift")
.Cases("armv7r", "armv7-r", "cortex-r4")
.Cases("armv7m", "armv7-m", "cortex-m3")
+ .Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
.Case("ep9312", "ep9312")
.Case("iwmmxt", "iwmmxt")
.Case("xscale", "xscale")
- // If all else failed, return the most base CPU LLVM supports.
+ // If all else failed, return the most base CPU with thumb interworking
+ // supported by LLVM.
.Default("arm7tdmi");
}
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting.
+//
+// FIXME: tblgen this.
+static std::string getAArch64TargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef MCPU = A->getValue();
+ // Handle -mcpu=native.
+ if (MCPU == "native")
+ return llvm::sys::getHostCPUName();
+ else
+ return MCPU;
+ }
+
+ return "generic";
+}
+
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -546,73 +579,117 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return true;
return false;
+ case llvm::Triple::ppc64le:
case llvm::Triple::systemz:
+ case llvm::Triple::xcore:
return false;
}
}
+static bool isNoCommonDefault(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return false;
+
+ case llvm::Triple::xcore:
+ return true;
+ }
+}
+
+// Handle -mfpu=.
+//
+// FIXME: Centralize feature selection, defaulting shouldn't be also in the
+// frontend target.
+static void getAArch64FPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FPU = A->getValue();
+ if (FPU == "fp-armv8") {
+ Features.push_back("+fp-armv8");
+ } else if (FPU == "neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ } else if (FPU == "crypto-neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("+crypto");
+ } else if (FPU == "neon") {
+ Features.push_back("+neon");
+ } else if (FPU == "none") {
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ Features.push_back("-neon");
+ } else
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+// Handle -mhwdiv=.
+static void getARMHWDivFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef HWDiv = A->getValue();
+ if (HWDiv == "arm") {
+ Features.push_back("+hwdiv-arm");
+ Features.push_back("-hwdiv");
+ } else if (HWDiv == "thumb") {
+ Features.push_back("-hwdiv-arm");
+ Features.push_back("+hwdiv");
+ } else if (HWDiv == "arm,thumb" || HWDiv == "thumb,arm") {
+ Features.push_back("+hwdiv-arm");
+ Features.push_back("+hwdiv");
+ } else if (HWDiv == "none") {
+ Features.push_back("-hwdiv-arm");
+ Features.push_back("-hwdiv");
+ } else
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
// frontend target.
-static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args,
- ArgStringList &CmdArgs) {
+static void getARMFPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
StringRef FPU = A->getValue();
// Set the target features based on the FPU.
if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") {
// Disable any default FPU support.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-vfp2");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("-vfp2");
+ Features.push_back("-vfp3");
+ Features.push_back("-neon");
} else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+d16");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp3");
+ Features.push_back("+d16");
+ Features.push_back("-neon");
} else if (FPU == "vfp") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp2");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp2");
+ Features.push_back("-neon");
} else if (FPU == "vfp3" || FPU == "vfpv3") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vfp3");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
+ Features.push_back("+vfp3");
+ Features.push_back("-neon");
+ } else if (FPU == "fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("-neon");
+ Features.push_back("-crypto");
+ } else if (FPU == "neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("-crypto");
+ } else if (FPU == "crypto-neon-fp-armv8") {
+ Features.push_back("+fp-armv8");
+ Features.push_back("+neon");
+ Features.push_back("+crypto");
} else if (FPU == "neon") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+neon");
- } else
- D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-// Handle -mfpmath=.
-static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args,
- ArgStringList &CmdArgs, StringRef CPU) {
- StringRef FPMath = A->getValue();
-
- // Set the target features based on the FPMath.
- if (FPMath == "neon") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+neonfp");
-
- if (CPU != "cortex-a5" && CPU != "cortex-a7" &&
- CPU != "cortex-a8" && CPU != "cortex-a9" &&
- CPU != "cortex-a9-mp" && CPU != "cortex-a15")
- D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU;
-
- } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" ||
- FPMath == "vfp4") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neonfp");
-
- // FIXME: Add warnings when disabling a feature not present for a given CPU.
+ Features.push_back("+neon");
+ } else if (FPU == "none") {
+ Features.push_back("-vfp2");
+ Features.push_back("-vfp3");
+ Features.push_back("-vfp4");
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ Features.push_back("-neon");
} else
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -697,6 +774,41 @@ static StringRef getARMFloatABI(const Driver &D,
return FloatABI;
}
+static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FloatABI = getARMFloatABI(D, Args, Triple);
+ // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
+ // yet (it uses the -mfloat-abi and -msoft-float options), and it is
+ // stripped out by the ARM target.
+ // Use software floating point operations?
+ if (FloatABI == "soft")
+ Features.push_back("+soft-float");
+
+ // Use software floating point argument passing?
+ if (FloatABI != "hard")
+ Features.push_back("+soft-float-abi");
+
+ // Honor -mfpu=.
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
+ getARMFPUFeatures(D, A, Args, Features);
+ if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
+ getARMHWDivFeatures(D, A, Args, Features);
+
+ // Setting -msoft-float effectively disables NEON because of the GCC
+ // implementation, although the same isn't true of VFP or VFP3.
+ if (FloatABI == "soft")
+ Features.push_back("-neon");
+
+ // En/disable crc
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc,
+ options::OPT_mnocrc)) {
+ if (A->getOption().matches(options::OPT_mcrc))
+ Features.push_back("+crc");
+ else
+ Features.push_back("-crc");
+ }
+}
void Clang::AddARMTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs,
@@ -716,7 +828,8 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
} else if (Triple.isOSDarwin()) {
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
- if (StringRef(CPUName).startswith("cortex-m")) {
+ if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ StringRef(CPUName).startswith("cortex-m")) {
ABIName = "aapcs";
} else {
ABIName = "apcs-gnu";
@@ -739,10 +852,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
- // Set the CPU based on -march= and -mcpu=.
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(CPUName));
-
// Determine floating point ABI from the options & target defaults.
StringRef FloatABI = getARMFloatABI(D, Args, Triple);
if (FloatABI == "soft") {
@@ -763,42 +872,9 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
CmdArgs.push_back("hard");
}
- // Set appropriate target features for floating point mode.
- //
- // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
- // yet (it uses the -mfloat-abi and -msoft-float options above), and it is
- // stripped out by the ARM target.
-
- // Use software floating point operations?
- if (FloatABI == "soft") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
- }
-
- // Use software floating point argument passing?
- if (FloatABI != "hard") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float-abi");
- }
-
- // Honor -mfpu=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
- addFPUArgs(D, A, Args, CmdArgs);
-
- // Honor -mfpmath=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ))
- addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple));
-
- // Setting -msoft-float effectively disables NEON because of the GCC
- // implementation, although the same isn't true of VFP or VFP3.
- if (FloatABI == "soft") {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-neon");
- }
-
// Kernel code has more strict alignment requirements.
if (KernelOrKext) {
- if (Triple.getOS() != llvm::Triple::IOS || Triple.isOSVersionLT(6)) {
+ if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-arm-long-calls");
}
@@ -808,7 +884,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
// The kext linker doesn't know how to deal with movw/movt.
CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-darwin-use-movt=0");
+ CmdArgs.push_back("-arm-use-movt=0");
}
// Setting -mno-global-merge disables the codegen global merge pass. Setting
@@ -823,39 +899,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args,
options::OPT_mno_implicit_float,
true))
CmdArgs.push_back("-no-implicit-float");
-}
-// Translate MIPS CPU name alias option to CPU name.
-static StringRef getMipsCPUFromAlias(const Arg &A) {
- if (A.getOption().matches(options::OPT_mips32))
- return "mips32";
- if (A.getOption().matches(options::OPT_mips32r2))
- return "mips32r2";
- if (A.getOption().matches(options::OPT_mips64))
- return "mips64";
- if (A.getOption().matches(options::OPT_mips64r2))
- return "mips64r2";
- llvm_unreachable("Unexpected option");
- return "";
+ // llvm does not support reserving registers in general. There is support
+ // for reserving r9 on ARM though (defined as a platform-specific register
+ // in ARM EABI).
+ if (Args.hasArg(options::OPT_ffixed_r9)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-reserve-r9");
+ }
}
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
static void getMipsCPUAndABI(const ArgList &Args,
- const ToolChain &TC,
+ const llvm::Triple &Triple,
StringRef &CPUName,
StringRef &ABIName) {
const char *DefMips32CPU = "mips32";
const char *DefMips64CPU = "mips64";
if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
- options::OPT_mcpu_EQ,
- options::OPT_mips_CPUs_Group)) {
- if (A->getOption().matches(options::OPT_mips_CPUs_Group))
- CPUName = getMipsCPUFromAlias(*A);
- else
- CPUName = A->getValue();
- }
+ options::OPT_mcpu_EQ))
+ CPUName = A->getValue();
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
@@ -869,7 +934,7 @@ static void getMipsCPUAndABI(const ArgList &Args,
// Setup default CPU and ABI names.
if (CPUName.empty() && ABIName.empty()) {
- switch (TC.getTriple().getArch()) {
+ switch (Triple.getArch()) {
default:
llvm_unreachable("Unexpected triple arch name");
case llvm::Triple::mips:
@@ -941,28 +1006,56 @@ static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
}
static void AddTargetFeature(const ArgList &Args,
- ArgStringList &CmdArgs,
- OptSpecifier OnOpt,
- OptSpecifier OffOpt,
+ std::vector<const char *> &Features,
+ OptSpecifier OnOpt, OptSpecifier OffOpt,
StringRef FeatureName) {
if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
- CmdArgs.push_back("-target-feature");
if (A->getOption().matches(OnOpt))
- CmdArgs.push_back(Args.MakeArgString("+" + FeatureName));
+ Features.push_back(Args.MakeArgString("+" + FeatureName));
else
- CmdArgs.push_back(Args.MakeArgString("-" + FeatureName));
+ Features.push_back(Args.MakeArgString("-" + FeatureName));
}
}
+static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef FloatABI = getMipsFloatABI(D, Args);
+ bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL;
+ if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) {
+ // FIXME: Note, this is a hack. We need to pass the selected float
+ // mode to the MipsTargetInfoBase to define appropriate macros there.
+ // Now it is the only method.
+ Features.push_back("+soft-float");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+ if (StringRef(A->getValue()) == "2008")
+ Features.push_back("+nan2008");
+ }
+
+ AddTargetFeature(Args, Features, options::OPT_msingle_float,
+ options::OPT_mdouble_float, "single-float");
+ AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
+ "mips16");
+ AddTargetFeature(Args, Features, options::OPT_mmicromips,
+ options::OPT_mno_micromips, "micromips");
+ AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
+ "dsp");
+ AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
+ "dspr2");
+ AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
+ "msa");
+ AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32,
+ "fp64");
+}
+
void Clang::AddMIPSTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
-
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName.data());
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
@@ -977,12 +1070,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
- // FIXME: Note, this is a hack. We need to pass the selected float
- // mode to the MipsTargetInfoBase to define appropriate macros there.
- // Now it is the only method.
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
-
if (FloatABI == "hard" && IsMips16) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mips16-hard-float");
@@ -995,22 +1082,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("hard");
}
- AddTargetFeature(Args, CmdArgs,
- options::OPT_msingle_float, options::OPT_mdouble_float,
- "single-float");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mips16, options::OPT_mno_mips16,
- "mips16");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mmicromips, options::OPT_mno_micromips,
- "micromips");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mdsp, options::OPT_mno_dsp,
- "dsp");
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mdspr2, options::OPT_mno_dspr2,
- "dspr2");
-
if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
if (A->getOption().matches(options::OPT_mxgot)) {
CmdArgs.push_back("-mllvm");
@@ -1018,6 +1089,22 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
}
}
+ if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
+ options::OPT_mno_ldc1_sdc1)) {
+ if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mno-ldc1-sdc1");
+ }
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
+ options::OPT_mno_check_zero_division)) {
+ if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mno-check-zero-division");
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
@@ -1081,62 +1168,48 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
.Case("pwr7", "pwr7")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
+ .Case("powerpc64le", "ppc64le")
.Default("");
}
return "";
}
-void Clang::AddPPCTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- std::string TargetCPUName = getPPCTargetCPU(Args);
-
- // LLVM may default to generating code for the native CPU,
- // but, like gcc, we default to a more generic option for
- // each architecture. (except on Darwin)
- llvm::Triple Triple = getToolChain().getTriple();
- if (TargetCPUName.empty() && !Triple.isOSDarwin()) {
- if (Triple.getArch() == llvm::Triple::ppc64)
- TargetCPUName = "ppc64";
- else
- TargetCPUName = "ppc";
- }
-
- if (!TargetCPUName.empty()) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(TargetCPUName.c_str()));
- }
-
- // Allow override of the Altivec feature.
- AddTargetFeature(Args, CmdArgs,
- options::OPT_faltivec, options::OPT_fno_altivec,
- "altivec");
+static void getPPCTargetFeatures(const ArgList &Args,
+ std::vector<const char *> &Features) {
+ for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it) {
+ StringRef Name = (*it)->getOption().getName();
+ (*it)->claim();
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mfprnd, options::OPT_mno_fprnd,
- "fprnd");
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
- // Note that gcc calls this mfcrf and LLVM calls this mfocrf.
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mmfcrf, options::OPT_mno_mfcrf,
- "mfocrf");
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
- AddTargetFeature(Args, CmdArgs,
- options::OPT_mpopcntd, options::OPT_mno_popcntd,
- "popcntd");
+ // Note that gcc calls this mfcrf and LLVM calls this mfocrf so we
+ // pass the correct option to the backend while calling the frontend
+ // option the same.
+ // TODO: Change the LLVM backend option maybe?
+ if (Name == "mfcrf")
+ Name = "mfocrf";
- // It is really only possible to turn qpx off because turning qpx on is tied
- // to using the a2q CPU.
- if (Args.hasFlag(options::OPT_mno_qpx, options::OPT_mqpx, false)) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-qpx");
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+
+ // Altivec is a bit weird, allow overriding of the Altivec feature here.
+ AddTargetFeature(Args, Features, options::OPT_faltivec,
+ options::OPT_fno_altivec, "altivec");
}
/// Get the (LLVM) name of the R600 gpu we are targeting.
static std::string getR600TargetGPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- std::string GPUName = A->getValue();
+ const char *GPUName = A->getValue();
return llvm::StringSwitch<const char *>(GPUName)
.Cases("rv630", "rv635", "r600")
.Cases("rv610", "rv620", "rs780", "rs880")
@@ -1145,27 +1218,27 @@ static std::string getR600TargetGPU(const ArgList &Args) {
.Cases("sumo", "sumo2", "sumo")
.Case("hemlock", "cypress")
.Case("aruba", "cayman")
- .Default(GPUName.c_str());
+ .Default(GPUName);
}
return "";
}
-void Clang::AddR600TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- std::string TargetGPUName = getR600TargetGPU(Args);
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(TargetGPUName.c_str()));
+static void getSparcTargetFeatures(const ArgList &Args,
+ std::vector<const char *> Features) {
+ bool SoftFloatABI = true;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
+ if (A->getOption().matches(options::OPT_mhard_float))
+ SoftFloatABI = false;
+ }
+ if (SoftFloatABI)
+ Features.push_back("+soft-float");
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(A->getValue());
- }
-
// Select the float ABI as determined by -msoft-float, -mhard-float, and
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
@@ -1178,13 +1251,9 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
// If unspecified, choose the default based on the platform.
if (FloatABI.empty()) {
- switch (getToolChain().getTriple().getOS()) {
- default:
- // Assume "soft", but warn the user we are guessing.
- FloatABI = "soft";
- D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
- break;
- }
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
}
if (FloatABI == "soft") {
@@ -1192,19 +1261,27 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
//
// FIXME: This changes CPP defines, we need -target-soft-float.
CmdArgs.push_back("-msoft-float");
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+soft-float");
} else {
assert(FloatABI == "hard" && "Invalid float abi!");
CmdArgs.push_back("-mhard-float");
}
}
+static const char *getSystemZTargetCPU(const ArgList &Args) {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ return "z10";
+}
+
static const char *getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- if (StringRef(A->getValue()) != "native")
+ if (StringRef(A->getValue()) != "native") {
+ if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
+ return "core-avx2";
+
return A->getValue();
+ }
// FIXME: Reject attempts to use -march=native unless the target matches
// the host.
@@ -1225,30 +1302,128 @@ static const char *getX86TargetCPU(const ArgList &Args,
bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
// FIXME: Need target hooks.
- if (Triple.isOSDarwin())
+ if (Triple.isOSDarwin()) {
+ if (Triple.getArchName() == "x86_64h")
+ return "core-avx2";
return Is64Bit ? "core2" : "yonah";
+ }
+
+ // All x86 devices running Android have core2 as their common
+ // denominator. This makes a better choice than pentium4.
+ if (Triple.getEnvironment() == llvm::Triple::Android)
+ return "core2";
// Everything else goes to x86-64 in 64-bit mode.
if (Is64Bit)
return "x86-64";
- if (Triple.getOSName().startswith("haiku"))
- return "i586";
- if (Triple.getOSName().startswith("openbsd"))
+ switch (Triple.getOS()) {
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
return "i486";
- if (Triple.getOSName().startswith("bitrig"))
+ case llvm::Triple::Haiku:
+ return "i586";
+ case llvm::Triple::Bitrig:
return "i686";
- if (Triple.getOSName().startswith("freebsd"))
- return "i486";
- if (Triple.getOSName().startswith("netbsd"))
- return "i486";
- // All x86 devices running Android have core2 as their common
- // denominator. This makes a better choice than pentium4.
- if (Triple.getEnvironment() == llvm::Triple::Android)
- return "core2";
+ default:
+ // Fallback to p4.
+ return "pentium4";
+ }
+}
+
+static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
+ switch(T.getArch()) {
+ default:
+ return "";
- // Fallback to p4.
- return "pentium4";
+ case llvm::Triple::aarch64:
+ return getAArch64TargetCPU(Args, T);
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return getARMTargetCPU(Args, T);
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, T, CPUName, ABIName);
+ return CPUName;
+ }
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le: {
+ std::string TargetCPUName = getPPCTargetCPU(Args);
+ // LLVM may default to generating code for the native CPU,
+ // but, like gcc, we default to a more generic option for
+ // each architecture. (except on Darwin)
+ if (TargetCPUName.empty() && !T.isOSDarwin()) {
+ if (T.getArch() == llvm::Triple::ppc64)
+ TargetCPUName = "ppc64";
+ else if (T.getArch() == llvm::Triple::ppc64le)
+ TargetCPUName = "ppc64le";
+ else
+ TargetCPUName = "ppc";
+ }
+ return TargetCPUName;
+ }
+
+ case llvm::Triple::sparc:
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ return "";
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return getX86TargetCPU(Args, T);
+
+ case llvm::Triple::hexagon:
+ return "hexagon" + toolchains::Hexagon_TC::GetTargetCPU(Args).str();
+
+ case llvm::Triple::systemz:
+ return getSystemZTargetCPU(Args);
+
+ case llvm::Triple::r600:
+ return getR600TargetGPU(Args);
+ }
+}
+
+static void getX86TargetFeatures(const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ if (Triple.getArchName() == "x86_64h") {
+ // x86_64h implies quite a few of the more modern subtarget features
+ // for Haswell class CPUs, but not all of them. Opt-out of a few.
+ Features.push_back("-rdrnd");
+ Features.push_back("-aes");
+ Features.push_back("-pclmul");
+ Features.push_back("-rtm");
+ Features.push_back("-hle");
+ Features.push_back("-fsgsbase");
+ }
+
+ // Now add any that the user explicitly requested on the command line,
+ // which may override the defaults.
+ for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it) {
+ StringRef Name = (*it)->getOption().getName();
+ (*it)->claim();
+
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
}
void Clang::AddX86TargetArgs(const ArgList &Args,
@@ -1274,45 +1449,6 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
}
if (NoImplicitFloat)
CmdArgs.push_back("-no-implicit-float");
-
- if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName);
- }
-
- // The required algorithm here is slightly strange: the options are applied
- // in order (so -mno-sse -msse2 disables SSE3), but any option that gets
- // directly overridden later is ignored (so "-mno-sse -msse2 -mno-sse2 -msse"
- // is equivalent to "-mno-sse2 -msse"). The -cc1 handling deals with the
- // former correctly, but not the latter; handle directly-overridden
- // attributes here.
- llvm::StringMap<unsigned> PrevFeature;
- std::vector<const char*> Features;
- for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group),
- ie = Args.filtered_end(); it != ie; ++it) {
- StringRef Name = (*it)->getOption().getName();
- (*it)->claim();
-
- // Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
- Name = Name.substr(1);
-
- bool IsNegative = Name.startswith("no-");
- if (IsNegative)
- Name = Name.substr(3);
-
- unsigned& Prev = PrevFeature[Name];
- if (Prev)
- Features[Prev - 1] = 0;
- Prev = Features.size() + 1;
- Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
- }
- for (unsigned i = 0; i < Features.size(); i++) {
- if (Features[i]) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(Features[i]);
- }
- }
}
static inline bool HasPICArg(const ArgList &Args) {
@@ -1339,12 +1475,6 @@ static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
void Clang::AddHexagonTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- llvm::Triple Triple = getToolChain().getTriple();
-
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(
- "hexagon"
- + toolchains::Hexagon_TC::GetTargetCPU(Args)));
CmdArgs.push_back("-fno-signed-char");
CmdArgs.push_back("-mqdsp6-compat");
CmdArgs.push_back("-Wreturn-type");
@@ -1366,6 +1496,70 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
CmdArgs.push_back ("-machine-sink-split=0");
}
+static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // Honor -mfpu=.
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
+ getAArch64FPUFeatures(D, A, Args, Features);
+}
+
+static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs) {
+ std::vector<const char *> Features;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ getMIPSTargetFeatures(D, Args, Features);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ getARMTargetFeatures(D, Triple, Args, Features);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ getPPCTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::sparc:
+ getSparcTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::aarch64:
+ getAArch64TargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ getX86TargetFeatures(Triple, Args, Features);
+ break;
+ }
+
+ // Find the last of each feature.
+ llvm::StringMap<unsigned> LastOpt;
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ const char *Name = Features[I];
+ assert(Name[0] == '-' || Name[0] == '+');
+ LastOpt[Name + 1] = I;
+ }
+
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ // If this feature was overridden, ignore it.
+ const char *Name = Features[I];
+ llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
+ assert(LastI != LastOpt.end());
+ unsigned Last = LastI->second;
+ if (Last != I)
+ continue;
+
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(Name);
+ }
+}
+
static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
@@ -1532,117 +1726,75 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
-SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
- : Kind(0), BlacklistFile(""), MsanTrackOrigins(false),
- AsanZeroBaseShadow(false) {
- unsigned AllKinds = 0; // All kinds of sanitizers that were turned on
- // at least once (possibly, disabled further).
- const Driver &D = TC.getDriver();
- for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) {
- unsigned Add, Remove;
- if (!parse(D, Args, *I, Add, Remove, true))
- continue;
- (*I)->claim();
- Kind |= Add;
- Kind &= ~Remove;
- AllKinds |= Add;
- }
+static void CollectArgsForIntegratedAssembler(Compilation &C,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const Driver &D) {
+ if (UseRelaxAll(C, Args))
+ CmdArgs.push_back("-mrelax-all");
- UbsanTrapOnError =
- Args.hasArg(options::OPT_fcatch_undefined_behavior) ||
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, false);
+ // When passing -I arguments to the assembler we sometimes need to
+ // unconditionally take the next argument. For example, when parsing
+ // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
+ // -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
+ // arg after parsing the '-I' arg.
+ bool TakeNextArg = false;
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior) &&
- !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, true)) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fcatch-undefined-behavior"
- << "-fno-sanitize-undefined-trap-on-error";
- }
+ // When using an integrated assembler, translate -Wa, and -Xassembler
+ // options.
+ for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
+ options::OPT_Xassembler),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
- // Warn about undefined sanitizer options that require runtime support.
- if (UbsanTrapOnError && notAllowedWithTrap()) {
- if (Args.hasArg(options::OPT_fcatch_undefined_behavior))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fcatch-undefined-behavior";
- else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error,
- false))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NotAllowedWithTrap)
- << "-fsanitize-undefined-trap-on-error";
- }
-
- // Only one runtime library can be used at once.
- bool NeedsAsan = needsAsanRt();
- bool NeedsTsan = needsTsanRt();
- bool NeedsMsan = needsMsanRt();
- if (NeedsAsan && NeedsTsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsTsanRt);
- if (NeedsAsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsAsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
- if (NeedsTsan && NeedsMsan)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << lastArgumentForKind(D, Args, NeedsTsanRt)
- << lastArgumentForKind(D, Args, NeedsMsanRt);
-
- // If -fsanitize contains extra features of ASan, it should also
- // explicitly contain -fsanitize=address (probably, turned off later in the
- // command line).
- if ((Kind & AddressFull) != 0 && (AllKinds & Address) == 0)
- D.Diag(diag::warn_drv_unused_sanitizer)
- << lastArgumentForKind(D, Args, AddressFull)
- << "-fsanitize=address";
-
- // Parse -f(no-)sanitize-blacklist options.
- if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist)) {
- if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- std::string BLPath = BLArg->getValue();
- bool BLExists = false;
- if (!llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
- BlacklistFile = BLPath;
- else
- D.Diag(diag::err_drv_no_such_file) << BLPath;
- }
- } else {
- // If no -fsanitize-blacklist option is specified, try to look up for
- // blacklist in the resource directory.
- std::string BLPath;
- bool BLExists = false;
- if (getDefaultBlacklistForKind(D, Kind, BLPath) &&
- !llvm::sys::fs::exists(BLPath, BLExists) && BLExists)
- BlacklistFile = BLPath;
- }
-
- // Parse -f(no-)sanitize-memory-track-origins options.
- if (NeedsMsan)
- MsanTrackOrigins =
- Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
- options::OPT_fno_sanitize_memory_track_origins,
- /* Default */false);
-
- // Parse -f(no-)sanitize-address-zero-base-shadow options.
- if (NeedsAsan) {
- bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android);
- bool ZeroBaseShadowDefault = IsAndroid;
- AsanZeroBaseShadow =
- Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow,
- options::OPT_fno_sanitize_address_zero_base_shadow,
- ZeroBaseShadowDefault);
- // Zero-base shadow is a requirement on Android.
- if (IsAndroid && !AsanZeroBaseShadow) {
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fno-sanitize-address-zero-base-shadow"
- << lastArgumentForKind(D, Args, Address);
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ StringRef Value = A->getValue(i);
+ if (TakeNextArg) {
+ CmdArgs.push_back(Value.data());
+ TakeNextArg = false;
+ continue;
+ }
+
+ if (Value == "-force_cpusubtype_ALL") {
+ // Do nothing, this is the default and we don't support anything else.
+ } else if (Value == "-L") {
+ CmdArgs.push_back("-msave-temp-labels");
+ } else if (Value == "--fatal-warnings") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-fatal-assembler-warnings");
+ } else if (Value == "--noexecstack") {
+ CmdArgs.push_back("-mnoexecstack");
+ } else if (Value.startswith("-I")) {
+ CmdArgs.push_back(Value.data());
+ // We need to consume the next argument if the current arg is a plain
+ // -I. The next arg will be the include directory.
+ if (Value == "-I")
+ TakeNextArg = true;
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
}
- }
+}
+
+static void addProfileRTLinux(
+ const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+ if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)))
+ return;
+
+ // The profile runtime is located in the Linux library directory and has name
+ // "libclang_rt.profile-<ArchName>.a".
+ SmallString<128> LibProfile(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(
+ LibProfile, "lib", "linux",
+ Twine("libclang_rt.profile-") + TC.getArchName() + ".a");
+
+ CmdArgs.push_back(Args.MakeArgString(LibProfile));
}
static void addSanitizerRTLinkFlagsLinux(
@@ -1673,6 +1825,7 @@ static void addSanitizerRTLinkFlagsLinux(
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lrt");
CmdArgs.push_back("-ldl");
+ CmdArgs.push_back("-lm");
// If possible, use a dynamic symbols file to export the symbols from the
// runtime library. If we can't do so, use -export-dynamic instead to export
@@ -1690,16 +1843,15 @@ static void addSanitizerRTLinkFlagsLinux(
/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if(TC.getTriple().getEnvironment() == llvm::Triple::Android) {
+ if (TC.getTriple().getEnvironment() == llvm::Triple::Android) {
SmallString<128> LibAsan(TC.getDriver().ResourceDir);
llvm::sys::path::append(LibAsan, "lib", "linux",
(Twine("libclang_rt.asan-") +
TC.getArchName() + "-android.so"));
CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
} else {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true);
- }
}
}
@@ -1707,18 +1859,24 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
/// This needs to be called before we add the C run-time (malloc, etc).
static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true);
- }
}
/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
/// This needs to be called before we add the C run-time (malloc, etc).
static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared))
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true);
- }
+}
+
+/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
+/// This needs to be called before we add the C run-time (malloc, etc).
+static void addLsanRTLinux(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true);
}
/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
@@ -1726,9 +1884,6 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args,
static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, bool IsCXX,
bool HasOtherSanitizerRt) {
- if (Args.hasArg(options::OPT_shared))
- return;
-
// Need a copy of sanitizer_common. This could come from another sanitizer
// runtime; if we're not including one, include our own copy.
if (!HasOtherSanitizerRt)
@@ -1742,22 +1897,42 @@ static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
}
+static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true);
+}
+
+static bool shouldUseFramePointerForTarget(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ // Don't use a frame pointer on linux if optimizing for certain targets.
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ if (Triple.isOSLinux())
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ if (!A->getOption().matches(options::OPT_O0))
+ return false;
+ return true;
+ case llvm::Triple::xcore:
+ return false;
+ default:
+ return true;
+ }
+}
+
static bool shouldUseFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
options::OPT_fomit_frame_pointer))
return A->getOption().matches(options::OPT_fno_omit_frame_pointer);
- // Don't use a frame pointer on linux x86 and x86_64 if optimizing.
- if ((Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::x86) &&
- Triple.getOS() == llvm::Triple::Linux) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- }
-
- return true;
+ return shouldUseFramePointerForTarget(Args, Triple);
}
static bool shouldUseLeafFramePointer(const ArgList &Args,
@@ -1766,38 +1941,11 @@ static bool shouldUseLeafFramePointer(const ArgList &Args,
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
- // Don't use a leaf frame pointer on linux x86 and x86_64 if optimizing.
- if ((Triple.getArch() == llvm::Triple::x86_64 ||
- Triple.getArch() == llvm::Triple::x86) &&
- Triple.getOS() == llvm::Triple::Linux) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- }
-
- return true;
+ return shouldUseFramePointerForTarget(Args, Triple);
}
-/// If the PWD environment variable is set, add a CC1 option to specify the
-/// debug compilation directory.
+/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
- struct stat StatPWDBuf, StatDotBuf;
-
- const char *pwd = ::getenv("PWD");
- if (!pwd)
- return;
-
- if (llvm::sys::path::is_absolute(pwd) &&
- stat(pwd, &StatPWDBuf) == 0 &&
- stat(".", &StatDotBuf) == 0 &&
- StatPWDBuf.st_ino == StatDotBuf.st_ino &&
- StatPWDBuf.st_dev == StatDotBuf.st_dev) {
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(Args.MakeArgString(pwd));
- return;
- }
-
- // Fall back to using getcwd.
SmallString<128> cwd;
if (!llvm::sys::fs::current_path(cwd)) {
CmdArgs.push_back("-fdebug-compilation-dir");
@@ -1854,6 +2002,37 @@ static bool isOptimizationLevelFast(const ArgList &Args) {
return false;
}
+/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
+static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ return true;
+
+ if (A->getOption().matches(options::OPT_O0))
+ return false;
+
+ assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");
+
+ // Vectorize -Os.
+ StringRef S(A->getValue());
+ if (S == "s")
+ return true;
+
+ // Don't vectorize -Oz.
+ if (S == "z")
+ return false;
+
+ unsigned OptLevel = 0;
+ if (S.getAsInteger(10, OptLevel))
+ return false;
+
+ return OptLevel > 1;
+ }
+
+ return false;
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -1896,35 +2075,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
- if (UseRelaxAll(C, Args))
- CmdArgs.push_back("-mrelax-all");
-
- // When using an integrated assembler, translate -Wa, and -Xassembler
- // options.
- for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA,
- options::OPT_Xassembler),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- A->claim();
-
- for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
- StringRef Value = A->getValue(i);
-
- if (Value == "-force_cpusubtype_ALL") {
- // Do nothing, this is the default and we don't support anything else.
- } else if (Value == "-L") {
- CmdArgs.push_back("-msave-temp-labels");
- } else if (Value == "--fatal-warnings") {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-fatal-assembler-warnings");
- } else if (Value == "--noexecstack") {
- CmdArgs.push_back("-mnoexecstack");
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
- }
- }
- }
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
// Also ignore explicit -force_cpusubtype_ALL option.
(void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -2071,7 +2222,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Inroduce a Darwin-specific hack. If the default is PIC but the flags
+ // Introduce a Darwin-specific hack. If the default is PIC but the flags
// specified while enabling PIC enabled level 1 PIC, just force it back to
// level 2 PIC instead. This matches the behavior of Darwin GCC (based on my
// informal testing).
@@ -2082,8 +2233,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// PIC or PIE options above, if these show up, PIC is disabled.
llvm::Triple Triple(TripleStr);
if (KernelOrKext &&
- (Triple.getOS() != llvm::Triple::IOS ||
- Triple.isOSVersionLT(6)))
+ (!Triple.isiOS() || Triple.isOSVersionLT(6)))
PIC = PIE = false;
if (Args.hasArg(options::OPT_static))
PIC = PIE = false;
@@ -2134,6 +2284,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
+ options::OPT_freg_struct_return)) {
+ if (getToolChain().getArch() != llvm::Triple::x86) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << getToolChain().getTriple().str();
+ } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
+ CmdArgs.push_back("-fpcc-struct-return");
+ } else {
+ assert(A->getOption().matches(options::OPT_freg_struct_return));
+ CmdArgs.push_back("-freg-struct-return");
+ }
+ }
+
if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
CmdArgs.push_back("-mrtd");
@@ -2149,11 +2312,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
options::OPT_fstrict_aliasing;
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
- options::OPT_fno_strict_aliasing,
- getToolChain().IsStrictAliasingDefault()))
+ options::OPT_fno_strict_aliasing, true))
CmdArgs.push_back("-relaxed-aliasing");
- if (Args.hasArg(options::OPT_fstruct_path_tbaa))
- CmdArgs.push_back("-struct-path-tbaa");
+ if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
+ options::OPT_fno_struct_path_tbaa))
+ CmdArgs.push_back("-no-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
@@ -2201,8 +2364,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_fmath_errno,
- options::OPT_fno_math_errno))
- MathErrno = A->getOption().getID() == options::OPT_fmath_errno;
+ options::OPT_fno_math_errno)) {
+ // Turning on -ffast_math (with either flag) removes the need for MathErrno.
+ // However, turning *off* -ffast_math merely restores the toolchain default
+ // (which may be false).
+ if (A->getOption().getID() == options::OPT_fno_math_errno ||
+ A->getOption().getID() == options::OPT_ffast_math ||
+ A->getOption().getID() == options::OPT_Ofast)
+ MathErrno = false;
+ else if (A->getOption().getID() == options::OPT_fmath_errno)
+ MathErrno = true;
+ }
if (MathErrno)
CmdArgs.push_back("-fmath-errno");
@@ -2349,8 +2521,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- // Add target specific cpu and features flags.
- switch(getToolChain().getTriple().getArch()) {
+ // Add the target cpu
+ std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple ETriple(ETripleStr);
+ std::string CPU = getCPUName(Args, ETriple);
+ if (!CPU.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPU));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
+ CmdArgs.push_back("-mfpmath");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ // Add the target features
+ getTargetFeatures(D, ETriple, Args, CmdArgs);
+
+ // Add target specific flags.
+ switch(getToolChain().getArch()) {
default:
break;
@@ -2366,15 +2555,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddMIPSTargetArgs(Args, CmdArgs);
break;
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- AddPPCTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::r600:
- AddR600TargetArgs(Args, CmdArgs);
- break;
-
case llvm::Triple::sparc:
AddSparcTargetArgs(Args, CmdArgs);
break;
@@ -2389,7 +2569,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
-
+ // Add clang-cl arguments.
+ if (getToolChain().getDriver().IsCLMode())
+ AddClangCLArgs(Args, CmdArgs);
// Pass the linker version in use.
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
@@ -2407,7 +2589,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Arg *Unsupported;
if (types::isCXX(InputType) &&
getToolChain().getTriple().isOSDarwin() &&
- getToolChain().getTriple().getArch() == llvm::Triple::x86) {
+ getToolChain().getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
@@ -2437,9 +2619,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
if (A->getOption().matches(options::OPT_gline_tables_only))
CmdArgs.push_back("-gline-tables-only");
+ else if (A->getOption().matches(options::OPT_gdwarf_2))
+ CmdArgs.push_back("-gdwarf-2");
+ else if (A->getOption().matches(options::OPT_gdwarf_3))
+ CmdArgs.push_back("-gdwarf-3");
+ else if (A->getOption().matches(options::OPT_gdwarf_4))
+ CmdArgs.push_back("-gdwarf-4");
else if (!A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_ggdb0))
- CmdArgs.push_back("-g");
+ !A->getOption().matches(options::OPT_ggdb0)) {
+ // Default is dwarf-2 for darwin.
+ if (getToolChain().getTriple().isOSDarwin())
+ CmdArgs.push_back("-gdwarf-2");
+ else
+ CmdArgs.push_back("-g");
+ }
}
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
@@ -2447,16 +2640,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gcolumn_info))
CmdArgs.push_back("-dwarf-column-info");
+ // FIXME: Move backend command line options to the module.
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
// FIXME: Currently only works on Linux.
- if (getToolChain().getTriple().getOS() == llvm::Triple::Linux &&
+ if (getToolChain().getTriple().isOSLinux() &&
Args.hasArg(options::OPT_gsplit_dwarf)) {
CmdArgs.push_back("-g");
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-split-dwarf=Enable");
}
+ // -ggnu-pubnames turns on gnu style pubnames in the backend.
+ if (Args.hasArg(options::OPT_ggnu_pubnames)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-gnu-dwarf-pub-sections");
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section);
+
Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections);
Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections);
@@ -2475,12 +2677,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-coverage-file");
SmallString<128> CoverageFilename(Output.getFilename());
if (llvm::sys::path::is_relative(CoverageFilename.str())) {
- if (const char *pwd = ::getenv("PWD")) {
- if (llvm::sys::path::is_absolute(pwd)) {
- SmallString<128> Pwd(pwd);
- llvm::sys::path::append(Pwd, CoverageFilename.str());
- CoverageFilename.swap(Pwd);
- }
+ SmallString<128> Pwd;
+ if (!llvm::sys::fs::current_path(Pwd)) {
+ llvm::sys::path::append(Pwd, CoverageFilename.str());
+ CoverageFilename.swap(Pwd);
}
}
CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
@@ -2505,7 +2705,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_working_directory);
bool ARCMTEnabled = false;
- if (!Args.hasArg(options::OPT_fno_objc_arc)) {
+ if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
options::OPT_ccc_arcmt_modify,
options::OPT_ccc_arcmt_migrate)) {
@@ -2529,6 +2729,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
}
+ } else {
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
+ Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
}
if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
@@ -2540,14 +2744,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
- options::OPT_objcmt_migrate_subscripting)) {
+ options::OPT_objcmt_migrate_subscripting,
+ options::OPT_objcmt_migrate_property)) {
// None specified, means enable them all.
CmdArgs.push_back("-objcmt-migrate-literals");
CmdArgs.push_back("-objcmt-migrate-subscripting");
+ CmdArgs.push_back("-objcmt-migrate-property");
} else {
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
}
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_white_list_dir_path);
}
// Add preprocessing options like -I, -D, etc. if we are using the
@@ -2563,16 +2785,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// preprocessed inputs and configure concludes that -fPIC is not supported.
Args.ClaimAllArgs(options::OPT_D);
- // Manually translate -O to -O2 and -O4 to -O3; let clang reject
- // others.
+ // Manually translate -O4 to -O3; let clang reject others.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- if (A->getOption().matches(options::OPT_O4))
+ if (A->getOption().matches(options::OPT_O4)) {
CmdArgs.push_back("-O3");
- else if (A->getOption().matches(options::OPT_O) &&
- A->getValue()[0] == '\0')
- CmdArgs.push_back("-O2");
- else
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
A->render(Args, CmdArgs);
+ }
}
// Don't warn about unused -flto. This can happen when we're preprocessing or
@@ -2586,7 +2806,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_w);
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
- // (-ansi is equivalent to -std=c89).
+ // (-ansi is equivalent to -std=c89 or -std=c++98).
//
// If a std is supplied, only add -trigraphs if it follows the
// option.
@@ -2619,13 +2839,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
}
- // Map the bizarre '-Wwrite-strings' flag to a more sensible
- // '-fconst-strings'; this better indicates its actual behavior.
- if (Args.hasFlag(options::OPT_Wwrite_strings, options::OPT_Wno_write_strings,
- false)) {
- // For perfect compatibility with GCC, we do this even in the presence of
- // '-w'. This flag names something other than a warning for GCC.
- CmdArgs.push_back("-fconst-strings");
+ // GCC's behavior for -Wwrite-strings is a bit strange:
+ // * In C, this "warning flag" changes the types of string literals from
+ // 'char[N]' to 'const char[N]', and thus triggers an unrelated warning
+ // for the discarded qualifier.
+ // * In C++, this is just a normal warning flag.
+ //
+ // Implementing this warning correctly in C is hard, so we follow GCC's
+ // behavior for now. FIXME: Directly diagnose uses of a string literal as
+ // a non-const char* in C, rather than using this crude hack.
+ if (!types::isCXX(InputType)) {
+ DiagnosticsEngine::Level DiagLevel = D.getDiags().getDiagnosticLevel(
+ diag::warn_deprecated_string_literal_conversion_c, SourceLocation());
+ if (DiagLevel > DiagnosticsEngine::Ignored)
+ CmdArgs.push_back("-fconst-strings");
}
// GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
@@ -2663,11 +2890,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
+ CmdArgs.push_back("-foperator-arrow-depth");
+ CmdArgs.push_back(A->getValue());
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
CmdArgs.push_back("-fconstexpr-depth");
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
+ CmdArgs.push_back("-fconstexpr-steps");
+ CmdArgs.push_back(A->getValue());
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
CmdArgs.push_back("-fbracket-depth");
CmdArgs.push_back(A->getValue());
@@ -2759,11 +2996,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
- Args.AddLastArg(CmdArgs, options::OPT_faltivec);
+ // AltiVec language extensions aren't relevant for assembling.
+ if (!isa<PreprocessJobAction>(JA) ||
+ Output.getType() != types::TY_PP_Asm)
+ Args.AddLastArg(CmdArgs, options::OPT_faltivec);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
- SanitizerArgs Sanitize(getToolChain(), Args);
+ const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
Sanitize.addArgs(Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fsanitize_recover,
@@ -2778,10 +3018,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Report an error for -faltivec on anything other than PowerPC.
if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
- if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc ||
- getToolChain().getTriple().getArch() == llvm::Triple::ppc64))
+ if (!(getToolChain().getArch() == llvm::Triple::ppc ||
+ getToolChain().getArch() == llvm::Triple::ppc64 ||
+ getToolChain().getArch() == llvm::Triple::ppc64le))
D.Diag(diag::err_drv_argument_only_allowed_with)
- << A->getAsString(Args) << "ppc/ppc64";
+ << A->getAsString(Args) << "ppc/ppc64/ppc64le";
if (getToolChain().SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
@@ -2822,8 +3063,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (A->getOption().matches(options::OPT_fno_strict_overflow))
CmdArgs.push_back("-fwrapv");
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
+ options::OPT_fno_reroll_loops))
+ if (A->getOption().matches(options::OPT_freroll_loops))
+ CmdArgs.push_back("-freroll-loops");
+
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
- Args.AddLastArg(CmdArgs, options::OPT_funroll_loops);
+ Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
+ options::OPT_fno_unroll_loops);
Args.AddLastArg(CmdArgs, options::OPT_pthread);
@@ -2876,13 +3124,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
}
// -mkernel implies -mstrict-align; don't add the redundant option.
- if (Args.hasArg(options::OPT_mstrict_align) && !KernelOrKext) {
- CmdArgs.push_back("-backend-option");
- CmdArgs.push_back("-arm-strict-align");
+ if (!KernelOrKext) {
+ if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+ options::OPT_munaligned_access)) {
+ if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-strict-align");
+ } else {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-no-strict-align");
+ }
+ }
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
+ options::OPT_mno_restrict_it)) {
+ if (A->getOption().matches(options::OPT_mrestrict_it)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-restrict-it");
+ } else {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-no-restrict-it");
+ }
}
// Forward -f options with positive and negative forms; we translate
// these by hand.
+ if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) {
+ StringRef fname = A->getValue();
+ if (!llvm::sys::fs::exists(fname))
+ D.Diag(diag::err_drv_no_such_file) << fname;
+ else
+ A->render(Args, CmdArgs);
+ }
if (Args.hasArg(options::OPT_mkernel)) {
if (!Args.hasArg(options::OPT_fapple_kext) && types::isCXX(InputType))
@@ -2926,6 +3200,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // -fmodule-maps enables module map processing (off by default) for header
+ // checking. It is implied by -fmodules.
+ if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
+ false)) {
+ CmdArgs.push_back("-fmodule-maps");
+ }
+
+ // -fmodules-decluse checks that modules used are declared so (off by
+ // default).
+ if (Args.hasFlag(options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodules-decluse");
+ }
+
+ // -fmodule-name specifies the module that is currently being built (or
+ // used for header checking by -fmodule-maps).
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ // -fmodule-map-file can be used to specify a file containing module
+ // definitions.
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
// If a module path was provided, pass it along. Otherwise, use a temporary
// directory.
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) {
@@ -2981,7 +3284,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums,
options::OPT_fno_short_enums,
- getToolChain().getTriple().getArch() ==
+ getToolChain().getArch() ==
llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
@@ -2996,11 +3299,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-threadsafe-statics");
// -fuse-cxa-atexit is default.
- if (!Args.hasFlag(options::OPT_fuse_cxa_atexit,
- options::OPT_fno_use_cxa_atexit,
- getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
- getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
- getToolChain().getTriple().getArch() != llvm::Triple::hexagon) ||
+ if (!Args.hasFlag(
+ options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
+ getToolChain().getTriple().getOS() != llvm::Triple::Cygwin &&
+ getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
@@ -3018,13 +3322,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))))
CmdArgs.push_back("-fms-compatibility");
- // -fmsc-version=1300 is default.
+ // -fmsc-version=1700 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
Args.hasArg(options::OPT_fmsc_version)) {
StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
if (msc_ver.empty())
- CmdArgs.push_back("-fmsc-version=1300");
+ CmdArgs.push_back("-fmsc-version=1700");
else
CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
}
@@ -3062,12 +3366,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
// -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
- // legacy is the default.
- if (objcRuntime.isNonFragile()) {
+ // legacy is the default. Next runtime is always legacy dispatch and
+ // -fno-objc-legacy-dispatch gets ignored silently.
+ if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
objcRuntime.isLegacyDispatchDefaultForArch(
- getToolChain().getTriple().getArch()))) {
+ getToolChain().getArch()))) {
if (getToolChain().UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
@@ -3075,12 +3380,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // -fobjc-default-synthesize-properties=1 is default. This only has an effect
- // if the nonfragile objc abi is used.
- if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) {
- CmdArgs.push_back("-fobjc-default-synthesize-properties");
- }
-
+ // When ObjectiveC legacy runtime is in effect on MacOSX,
+ // turn on the option to do Array/Dictionary subscripting
+ // by default.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86 &&
+ getToolChain().getTriple().isMacOSX() &&
+ !getToolChain().getTriple().isMacOSXVersionLT(10, 7) &&
+ objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
+ objcRuntime.isNeXTFamily())
+ CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
+
// -fencode-extended-block-signature=1 is default.
if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
CmdArgs.push_back("-fencode-extended-block-signature");
@@ -3160,16 +3469,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar))
A->render(Args, CmdArgs);
- // -fno-pascal-strings is default, only pass non-default. If the tool chain
- // happened to translate to -mpascal-strings, we want to back translate here.
- //
- // FIXME: This is gross; that translation should be pulled from the
- // tool chain.
+ // -fno-pascal-strings is default, only pass non-default.
if (Args.hasFlag(options::OPT_fpascal_strings,
options::OPT_fno_pascal_strings,
- false) ||
- Args.hasFlag(options::OPT_mpascal_strings,
- options::OPT_mno_pascal_strings,
false))
CmdArgs.push_back("-fpascal-strings");
@@ -3184,7 +3486,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fpack-struct=1");
}
- if (KernelOrKext) {
+ if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
if (!Args.hasArg(options::OPT_fcommon))
CmdArgs.push_back("-fno-common");
Args.ClaimAllArgs(options::OPT_fno_common);
@@ -3284,6 +3586,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
(ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
CmdArgs.push_back("-fcolor-diagnostics");
+ if (Args.hasArg(options::OPT_fansi_escape_codes))
+ CmdArgs.push_back("-fansi-escape-codes");
+
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
@@ -3303,31 +3608,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fasm-blocks");
- // If -Ofast is the optimization level, then -fvectorize should be enabled.
- // This alias option is being used to simplify the hasFlag logic.
- OptSpecifier VectorizeAliasOption = OFastEnabled ? options::OPT_Ofast :
+ // Enable vectorization per default according to the optimization level
+ // selected. For optimization levels that want vectorization we use the alias
+ // option to simplify the hasFlag logic.
+ bool EnableVec = shouldEnableVectorizerAtOLevel(Args);
+ OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
options::OPT_fvectorize;
-
- // -fvectorize is default.
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
- options::OPT_fno_vectorize, true)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
- }
- // -fno-slp-vectorize is default.
+ // -fslp-vectorize is default.
if (Args.hasFlag(options::OPT_fslp_vectorize,
- options::OPT_fno_slp_vectorize, false)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_slp_vectorize, true))
CmdArgs.push_back("-vectorize-slp");
- }
// -fno-slp-vectorize-aggressive is default.
if (Args.hasFlag(options::OPT_fslp_vectorize_aggressive,
- options::OPT_fno_slp_vectorize_aggressive, false)) {
- CmdArgs.push_back("-backend-option");
+ options::OPT_fno_slp_vectorize_aggressive, false))
CmdArgs.push_back("-vectorize-slp-aggressive");
- }
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
@@ -3354,13 +3653,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
+ // le32-specific flags:
+ // -fno-math-builtin: clang should not convert math builtins to intrinsics
+ // by default.
+ if (getToolChain().getArch() == llvm::Triple::le32) {
+ CmdArgs.push_back("-fno-math-builtin");
+ }
+
// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
//
// FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941.
#if 0
if (getToolChain().getTriple().isOSDarwin() &&
- (getToolChain().getTriple().getArch() == llvm::Triple::arm ||
- getToolChain().getTriple().getArch() == llvm::Triple::thumb)) {
+ (getToolChain().getArch() == llvm::Triple::arm ||
+ getToolChain().getArch() == llvm::Triple::thumb)) {
if (!Args.hasArg(options::OPT_fbuiltin_strcat))
CmdArgs.push_back("-fno-builtin-strcat");
if (!Args.hasArg(options::OPT_fbuiltin_strcpy))
@@ -3457,7 +3763,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
- (getToolChain().getTriple().getOS() == llvm::Triple::Linux) &&
+ getToolChain().getTriple().isOSLinux() &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
const char *SplitDwarfOut;
if (SplitDwarf) {
@@ -3467,7 +3773,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Finally add the compile command to the compilation.
- C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ if (Args.hasArg(options::OPT__SLASH_fallback)) {
+ tools::visualstudio::Compile CL(getToolChain());
+ Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args,
+ LinkingOutput);
+ C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand));
+ } else {
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ }
+
// Handle the debug info splitting at object creation time if we're
// creating an object.
@@ -3492,38 +3806,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
- // Disable warnings for clang -E -use-gold-plugin -emit-llvm foo.c
- Args.ClaimAllArgs(options::OPT_use_gold_plugin);
+ // Disable warnings for clang -E -emit-llvm foo.c
Args.ClaimAllArgs(options::OPT_emit_llvm);
}
-void ClangAs::AddARMTargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- const Driver &D = getToolChain().getDriver();
- llvm::Triple Triple = getToolChain().getTriple();
-
- // Set the CPU based on -march= and -mcpu=.
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(Args.MakeArgString(getARMTargetCPU(Args, Triple)));
-
- // Honor -mfpu=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
- addFPUArgs(D, A, Args, CmdArgs);
-
- // Honor -mfpmath=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ))
- addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple));
-}
-
-void ClangAs::AddX86TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- // Set the CPU based on -march=.
- if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) {
- CmdArgs.push_back("-target-cpu");
- CmdArgs.push_back(CPUName);
- }
-}
-
/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
@@ -3649,6 +3935,67 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
return runtime;
}
+void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ // The /LDd option implies /MTd. The dependent lib part can be overridden,
+ // but defining _DEBUG is sticky.
+ RTOptionID = options::OPT__SLASH_MTd;
+
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+ RTOptionID = A->getOption().getID();
+
+ switch(RTOptionID) {
+ case options::OPT__SLASH_MD:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrt");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrtd");
+ break;
+ case options::OPT__SLASH_MT:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmt");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmtd");
+ break;
+ default:
+ llvm_unreachable("Unexpected option ID.");
+ }
+
+ // This provides POSIX compatibility (maps 'open' to '_open'), which most
+ // users want. The /Za flag to cl.exe turns this off, but it's not
+ // implemented in clang.
+ CmdArgs.push_back("--dependent-lib=oldnames");
+
+ // FIXME: Make this default for the win32 triple.
+ CmdArgs.push_back("-cxx-abi");
+ CmdArgs.push_back("microsoft");
+
+ if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ A->render(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-format");
+ if (Args.hasArg(options::OPT__SLASH_fallback))
+ CmdArgs.push_back("msvc-fallback");
+ else
+ CmdArgs.push_back("msvc");
+ }
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -3663,8 +4010,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_w);
// and "clang -emit-llvm -c foo.s"
Args.ClaimAllArgs(options::OPT_emit_llvm);
- // and "clang -use-gold-plugin -c foo.s"
- Args.ClaimAllArgs(options::OPT_use_gold_plugin);
// Invoke ourselves in -cc1as mode.
//
@@ -3687,25 +4032,18 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-main-file-name");
CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));
- if (UseRelaxAll(C, Args))
- CmdArgs.push_back("-relax-all");
-
- // Add target specific cpu and features flags.
- switch(getToolChain().getTriple().getArch()) {
- default:
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- AddARMTargetArgs(Args, CmdArgs);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- AddX86TargetArgs(Args, CmdArgs);
- break;
+ // Add the target cpu
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ std::string CPU = getCPUName(Args, Triple);
+ if (!CPU.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPU));
}
+ // Add the target features
+ const Driver &D = getToolChain().getDriver();
+ getTargetFeatures(D, Triple, Args, CmdArgs);
+
// Ignore explicit -force_cpusubtype_ALL option.
(void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -3755,8 +4093,9 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: Add -static support, once we have it.
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
- options::OPT_Xassembler);
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
+ getToolChain().getDriver());
+
Args.AddAllArgs(CmdArgs, options::OPT_mllvm);
assert(Output.isFilename() && "Unexpected lipo output.");
@@ -3773,7 +4112,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// creating an object.
// TODO: Currently only works on linux with newer objcopy.
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
- (getToolChain().getTriple().getOS() == llvm::Triple::Linux))
+ getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
SplitDebugName(Args, Inputs));
}
@@ -3795,6 +4134,11 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
A->getOption().matches(options::OPT_g_Group))
continue;
+ // Don't forward any -W arguments to assembly and link steps.
+ if ((isa<AssembleJobAction>(JA) || isa<LinkJobAction>(JA)) &&
+ A->getOption().matches(options::OPT_W_Group))
+ continue;
+
// It is unfortunate that we have to claim here, as this means
// we will basically never report anything interesting for
// platforms using a generic gcc, even if we are just using gcc
@@ -3816,6 +4160,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("ppc");
else if (Arch == llvm::Triple::ppc64)
CmdArgs.push_back("ppc64");
+ else if (Arch == llvm::Triple::ppc64le)
+ CmdArgs.push_back("ppc64le");
else
CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName()));
}
@@ -3827,7 +4173,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
// here.
if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc)
CmdArgs.push_back("-m32");
- else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64)
+ else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 ||
+ Arch == llvm::Triple::ppc64le)
CmdArgs.push_back("-m64");
if (Output.isFilename()) {
@@ -3890,7 +4237,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const char *GCCName;
if (!customGCCName.empty())
GCCName = customGCCName.c_str();
- else if (D.CCCIsCXX) {
+ else if (D.CCCIsCXX()) {
GCCName = "g++";
} else
GCCName = "gcc";
@@ -4152,7 +4499,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Libraries
//----------------------------------------------------------------------------
if (incStdLib && incDefLibs) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -4179,10 +4526,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
- C.addCommand(
- new Command(
- JA, *this,
- Args.MakeArgString(Linker), CmdArgs));
+ C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
}
// Hexagon tools end.
@@ -4206,7 +4550,7 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) {
.Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
.Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
llvm::Triple::x86)
- .Case("x86_64", llvm::Triple::x86_64)
+ .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
// This is derived from the driver driver.
.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
.Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm)
@@ -4266,6 +4610,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
SourceAction = SourceAction->getInputs()[0];
}
+ // If -no_integrated_as is used add -Q to the darwin assember driver to make
+ // sure it runs its system assembler not clang's integrated assembler.
+ if (Args.hasArg(options::OPT_no_integrated_as))
+ CmdArgs.push_back("-Q");
+
// Forward -g, assuming we are dealing with an actual assembly file.
if (SourceAction->getType() == types::TY_Asm ||
SourceAction->getType() == types::TY_PP_Asm) {
@@ -4279,12 +4628,12 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
AddDarwinArch(Args, CmdArgs);
// Use -force_cpusubtype_ALL on x86 by default.
- if (getToolChain().getTriple().getArch() == llvm::Triple::x86 ||
- getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
+ if (getToolChain().getArch() == llvm::Triple::x86 ||
+ getToolChain().getArch() == llvm::Triple::x86_64 ||
Args.hasArg(options::OPT_force__cpusubtype__ALL))
CmdArgs.push_back("-force_cpusubtype_ALL");
- if (getToolChain().getTriple().getArch() != llvm::Triple::x86_64 &&
+ if (getToolChain().getArch() != llvm::Triple::x86_64 &&
(((Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext)) &&
(!getDarwinToolChain().isTargetIPhoneOS() ||
@@ -4375,6 +4724,9 @@ void darwin::Link::AddLinkArgs(Compilation &C,
CmdArgs.push_back("-demangle");
}
+ if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
+ CmdArgs.push_back("-export_dynamic");
+
// If we are using LTO, then automatically create a temporary file path for
// the linker to use, so that it's lifetime will extend past a possible
// dsymutil step.
@@ -4573,7 +4925,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
Args.AddLastArg(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_m_Separate);
Args.AddAllArgs(CmdArgs, options::OPT_r);
// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
@@ -4582,9 +4933,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
CmdArgs.push_back("-ObjC");
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export_dynamic");
-
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -4681,19 +5029,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
- SanitizerArgs Sanitize(getToolChain(), Args);
- // If we're building a dynamic lib with -fsanitize=address,
- // unresolved symbols may appear. Mark all
- // of them as dynamic_lookup. Linking executables is handled in
- // lib/Driver/ToolChains.cpp.
- if (Sanitize.needsAsanRt()) {
- if (Args.hasArg(options::OPT_dynamiclib) ||
- Args.hasArg(options::OPT_bundle)) {
- CmdArgs.push_back("-undefined");
- CmdArgs.push_back("dynamic_lookup");
- }
- }
-
if (Args.hasArg(options::OPT_fopenmp))
// This is more complicated in gcc...
CmdArgs.push_back("-lgomp");
@@ -4733,7 +5068,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
// link_ssp spec is empty.
@@ -4858,18 +5193,17 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
std::string LibPath = "/usr/lib/";
llvm::Triple::ArchType Arch = T.getArch();
switch (Arch) {
- case llvm::Triple::x86:
- GCCLibPath += ("i386-" + T.getVendorName() + "-" +
- T.getOSName()).str() + "/4.5.2/";
- break;
- case llvm::Triple::x86_64:
- GCCLibPath += ("i386-" + T.getVendorName() + "-" +
- T.getOSName()).str();
- GCCLibPath += "/4.5.2/amd64/";
- LibPath += "amd64/";
- break;
- default:
- assert(0 && "Unsupported architecture");
+ case llvm::Triple::x86:
+ GCCLibPath +=
+ ("i386-" + T.getVendorName() + "-" + T.getOSName()).str() + "/4.5.2/";
+ break;
+ case llvm::Triple::x86_64:
+ GCCLibPath += ("i386-" + T.getVendorName() + "-" + T.getOSName()).str();
+ GCCLibPath += "/4.5.2/amd64/";
+ LibPath += "amd64/";
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
}
ArgStringList CmdArgs;
@@ -4915,7 +5249,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
}
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
}
@@ -4930,7 +5264,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (getToolChain().getDriver().CCCIsCXX)
+ if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lgcc_s");
if (!Args.hasArg(options::OPT_shared)) {
@@ -5072,6 +5406,40 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ // When building 32-bit code on OpenBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ if (getToolChain().getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("--32");
+ else if (getToolChain().getArch() == llvm::Triple::ppc) {
+ CmdArgs.push_back("-mppc");
+ CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::mips64 ||
+ getToolChain().getArch() == llvm::Triple::mips64el) {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else
+ CmdArgs.push_back("-EL");
+
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ if (LastPICArg &&
+ (LastPICArg->getOption().matches(options::OPT_fPIC) ||
+ LastPICArg->getOption().matches(options::OPT_fpic) ||
+ LastPICArg->getOption().matches(options::OPT_fPIE) ||
+ LastPICArg->getOption().matches(options::OPT_fpie))) {
+ CmdArgs.push_back("-KPIC");
+ }
+ }
+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -5105,6 +5473,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else if (getToolChain().getArch() == llvm::Triple::mips64el)
+ CmdArgs.push_back("-EL");
+
if ((!Args.hasArg(options::OPT_nostdlib)) &&
(!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-e");
@@ -5126,6 +5499,9 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Args.hasArg(options::OPT_nopie))
+ CmdArgs.push_back("-nopie");
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -5168,7 +5544,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5298,7 +5674,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5321,23 +5697,21 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- std::string myarch = "-lclang_rt.";
- const llvm::Triple &T = getToolChain().getTriple();
- llvm::Triple::ArchType Arch = T.getArch();
- switch (Arch) {
- case llvm::Triple::arm:
- myarch += ("arm");
- break;
- case llvm::Triple::x86:
- myarch += ("i386");
- break;
- case llvm::Triple::x86_64:
- myarch += ("amd64");
- break;
- default:
- assert(0 && "Unsupported architecture");
- }
- CmdArgs.push_back(Args.MakeArgString(myarch));
+ StringRef MyArch;
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ MyArch = "arm";
+ break;
+ case llvm::Triple::x86:
+ MyArch = "i386";
+ break;
+ case llvm::Triple::x86_64:
+ MyArch = "amd64";
+ break;
+ default:
+ llvm_unreachable("Unsupported architecture");
+ }
+ CmdArgs.push_back(Args.MakeArgString("-lclang_rt." + MyArch));
}
if (!Args.hasArg(options::OPT_nostdlib) &&
@@ -5374,7 +5748,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -5534,11 +5908,31 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
+ // Tell the linker to load the plugin. This has to come before AddLinkerInputs
+ // as gold requires -plugin to come before any -plugin-opt that -Wl might
+ // forward.
+ if (D.IsUsingLTO(Args)) {
+ CmdArgs.push_back("-plugin");
+ std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
+ CmdArgs.push_back(Args.MakeArgString(Plugin));
+
+ // Try to pass driver level flags relevant to LTO code generation down to
+ // the plugin.
+
+ // Handle flags for selecting CPU variants.
+ std::string CPU = getCPUName(Args, ToolChain.getTriple());
+ if (!CPU.empty()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
+ CPU));
+ }
+ }
+
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
@@ -5618,11 +6012,45 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
if (getToolChain().getArch() == llvm::Triple::x86)
CmdArgs.push_back("--32");
- // Set byte order explicitly
- if (getToolChain().getArch() == llvm::Triple::mips)
- CmdArgs.push_back("-EB");
- else if (getToolChain().getArch() == llvm::Triple::mipsel)
- CmdArgs.push_back("-EL");
+ // Pass the target CPU to GNU as for ARM, since the source code might
+ // not have the correct .cpu annotation.
+ if (getToolChain().getArch() == llvm::Triple::arm) {
+ std::string MArch(getARMTargetCPU(Args, getToolChain().getTriple()));
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
+ }
+
+ if (getToolChain().getArch() == llvm::Triple::mips ||
+ getToolChain().getArch() == llvm::Triple::mipsel ||
+ getToolChain().getArch() == llvm::Triple::mips64 ||
+ getToolChain().getArch() == llvm::Triple::mips64el) {
+ StringRef CPUName;
+ StringRef ABIName;
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(CPUName.data());
+
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+
+ if (getToolChain().getArch() == llvm::Triple::mips ||
+ getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ else
+ CmdArgs.push_back("-EL");
+
+ Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ if (LastPICArg &&
+ (LastPICArg->getOption().matches(options::OPT_fPIC) ||
+ LastPICArg->getOption().matches(options::OPT_fpic) ||
+ LastPICArg->getOption().matches(options::OPT_fPIE) ||
+ LastPICArg->getOption().matches(options::OPT_fpie))) {
+ CmdArgs.push_back("-KPIC");
+ }
+ }
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
@@ -5706,34 +6134,39 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ unsigned Major, Minor, Micro;
+ getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
+ bool useLibgcc = true;
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
+ if (getToolChain().getArch() == llvm::Triple::x86 ||
+ getToolChain().getArch() == llvm::Triple::x86_64)
+ useLibgcc = false;
+ }
+
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
- // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
- // the default system libraries. Just mimic this for now.
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lgcc_eh");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lgcc_s");
- CmdArgs.push_back("--no-as-needed");
- }
- CmdArgs.push_back("-lgcc");
-
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lgcc");
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lgcc_eh");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lgcc_s");
- CmdArgs.push_back("--no-as-needed");
+ if (useLibgcc) {
+ if (Args.hasArg(options::OPT_static)) {
+ // libgcc_eh depends on libc, so resolve as much as possible,
+ // pull in any new requirements from libc and then get the rest
+ // of libgcc.
+ CmdArgs.push_back("-lgcc_eh");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
}
}
@@ -5776,10 +6209,16 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::ppc64le) {
+ CmdArgs.push_back("-a64");
+ CmdArgs.push_back("-mppc64le");
+ CmdArgs.push_back("-many");
} else if (getToolChain().getArch() == llvm::Triple::arm) {
StringRef MArch = getToolChain().getArchName();
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
CmdArgs.push_back("-mfpu=neon");
+ if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a")
+ CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
StringRef ARMFloatABI = getARMFloatABI(getToolChain().getDriver(), Args,
getToolChain().getTriple());
@@ -5794,7 +6233,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getArch() == llvm::Triple::mips64el) {
StringRef CPUName;
StringRef ABIName;
- getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName);
+ getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -5808,12 +6247,31 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-EL");
+ if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+ if (StringRef(A->getValue()) == "2008")
+ CmdArgs.push_back(Args.MakeArgString("-mnan=2008"));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfp64)) {
+ if (A->getOption().matches(options::OPT_mfp32))
+ CmdArgs.push_back(Args.MakeArgString("-mfp32"));
+ else
+ CmdArgs.push_back(Args.MakeArgString("-mfp64"));
+ }
+
Args.AddLastArg(CmdArgs, options::OPT_mips16, options::OPT_mno_mips16);
Args.AddLastArg(CmdArgs, options::OPT_mmicromips,
options::OPT_mno_micromips);
Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp);
Args.AddLastArg(CmdArgs, options::OPT_mdspr2, options::OPT_mno_dspr2);
+ if (Arg *A = Args.getLastArg(options::OPT_mmsa, options::OPT_mno_msa)) {
+ // Do not use AddLastArg because not all versions of MIPS assembler
+ // support -mmsa / -mno-msa options.
+ if (A->getOption().matches(options::OPT_mmsa))
+ CmdArgs.push_back(Args.MakeArgString("-mmsa"));
+ }
+
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
options::OPT_fpic, options::OPT_fno_pic,
options::OPT_fPIE, options::OPT_fno_PIE,
@@ -5826,8 +6284,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-KPIC");
}
} else if (getToolChain().getArch() == llvm::Triple::systemz) {
- // At the moment we always produce z10 code.
- CmdArgs.push_back("-march=z10");
+ // Always pass an -march option, since our default of z10 is later
+ // than the GNU assembler's default.
+ StringRef CPUName = getSystemZTargetCPU(Args);
+ CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -5845,6 +6305,14 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ // Handle the debug info splitting at object creation time if we're
+ // creating an object.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ getToolChain().getTriple().isOSLinux())
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs));
}
static void AddLibgcc(llvm::Triple Triple, const Driver &D,
@@ -5852,23 +6320,23 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D,
bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static);
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
if (StaticLibgcc || isAndroid) {
- if (D.CCCIsCXX)
+ if (D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
} else {
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
- if (!D.CCCIsCXX)
+ if (!D.CCCIsCXX())
CmdArgs.push_back("--no-as-needed");
}
if (StaticLibgcc && !isAndroid)
CmdArgs.push_back("-lgcc_eh");
- else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
+ else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
CmdArgs.push_back("-lgcc");
// According to Android ABI, we have to link with libdl if we are
@@ -5885,6 +6353,39 @@ static bool hasMipsN32ABIArg(const ArgList &Args) {
return A && (A->getValue() == StringRef("n32"));
}
+static StringRef getLinuxDynamicLinker(const ArgList &Args,
+ const toolchains::Linux &ToolChain) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android)
+ return "/system/bin/linker";
+ else if (ToolChain.getArch() == llvm::Triple::x86)
+ return "/lib/ld-linux.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::aarch64)
+ return "/lib/ld-linux-aarch64.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::thumb) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ return "/lib/ld-linux-armhf.so.3";
+ else
+ return "/lib/ld-linux.so.3";
+ } else if (ToolChain.getArch() == llvm::Triple::mips ||
+ ToolChain.getArch() == llvm::Triple::mipsel)
+ return "/lib/ld.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::mips64 ||
+ ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (hasMipsN32ABIArg(Args))
+ return "/lib32/ld.so.1";
+ else
+ return "/lib64/ld.so.1";
+ } else if (ToolChain.getArch() == llvm::Triple::ppc)
+ return "/lib/ld.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
+ ToolChain.getArch() == llvm::Triple::ppc64le ||
+ ToolChain.getArch() == llvm::Triple::systemz)
+ return "/lib64/ld64.so.1";
+ else
+ return "/lib64/ld-linux-x86-64.so.2";
+}
+
void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -5895,7 +6396,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = ToolChain.getDriver();
const bool isAndroid =
ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
- SanitizerArgs Sanitize(getToolChain(), Args);
+ const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
(Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow());
@@ -5982,36 +6483,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
- if (isAndroid)
- CmdArgs.push_back("/system/bin/linker");
- else if (ToolChain.getArch() == llvm::Triple::x86)
- CmdArgs.push_back("/lib/ld-linux.so.2");
- else if (ToolChain.getArch() == llvm::Triple::aarch64)
- CmdArgs.push_back("/lib/ld-linux-aarch64.so.1");
- else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb) {
- if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
- CmdArgs.push_back("/lib/ld-linux-armhf.so.3");
- else
- CmdArgs.push_back("/lib/ld-linux.so.3");
- }
- else if (ToolChain.getArch() == llvm::Triple::mips ||
- ToolChain.getArch() == llvm::Triple::mipsel)
- CmdArgs.push_back("/lib/ld.so.1");
- else if (ToolChain.getArch() == llvm::Triple::mips64 ||
- ToolChain.getArch() == llvm::Triple::mips64el) {
- if (hasMipsN32ABIArg(Args))
- CmdArgs.push_back("/lib32/ld.so.1");
- else
- CmdArgs.push_back("/lib64/ld.so.1");
- }
- else if (ToolChain.getArch() == llvm::Triple::ppc)
- CmdArgs.push_back("/lib/ld.so.1");
- else if (ToolChain.getArch() == llvm::Triple::ppc64 ||
- ToolChain.getArch() == llvm::Triple::systemz)
- CmdArgs.push_back("/lib64/ld64.so.1");
- else
- CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2");
+ CmdArgs.push_back(Args.MakeArgString(
+ D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
}
CmdArgs.push_back("-o");
@@ -6022,7 +6495,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!isAndroid) {
const char *crt1 = NULL;
if (!Args.hasArg(options::OPT_shared)){
- if (IsPIE)
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (IsPIE)
crt1 = "Scrt1.o";
else
crt1 = "crt1.o";
@@ -6059,7 +6534,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Tell the linker to load the plugin. This has to come before AddLinkerInputs
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
- if (D.IsUsingLTO(Args) || Args.hasArg(options::OPT_use_gold_plugin)) {
+ if (D.IsUsingLTO(Args)) {
CmdArgs.push_back("-plugin");
std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
CmdArgs.push_back(Args.MakeArgString(Plugin));
@@ -6067,20 +6542,13 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Try to pass driver level flags relevant to LTO code generation down to
// the plugin.
- // Handle architecture-specific flags for selecting CPU variants.
- if (ToolChain.getArch() == llvm::Triple::x86 ||
- ToolChain.getArch() == llvm::Triple::x86_64)
+ // Handle flags for selecting CPU variants.
+ std::string CPU = getCPUName(Args, ToolChain.getTriple());
+ if (!CPU.empty()) {
CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
- getX86TargetCPU(Args, ToolChain.getTriple())));
- else if (ToolChain.getArch() == llvm::Triple::arm ||
- ToolChain.getArch() == llvm::Triple::thumb)
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
- getARMTargetCPU(Args, ToolChain.getTriple())));
-
- // FIXME: Factor out logic for MIPS, PPC, and other targets to support this
- // as well.
+ Args.MakeArgString(Twine("-plugin-opt=mcpu=") +
+ CPU));
+ }
}
@@ -6091,17 +6559,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
// Call these before we add the C++ ABI library.
if (Sanitize.needsUbsanRt())
- addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX,
+ addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(),
Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
- Sanitize.needsMsanRt());
+ Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
if (Sanitize.needsAsanRt())
addAsanRTLinux(getToolChain(), Args, CmdArgs);
if (Sanitize.needsTsanRt())
addTsanRTLinux(getToolChain(), Args, CmdArgs);
if (Sanitize.needsMsanRt())
addMsanRTLinux(getToolChain(), Args, CmdArgs);
+ if (Sanitize.needsLsanRt())
+ addLsanRTLinux(getToolChain(), Args, CmdArgs);
+ if (Sanitize.needsDfsanRt())
+ addDfsanRTLinux(getToolChain(), Args, CmdArgs);
- if (D.CCCIsCXX &&
+ // The profile runtime also needs access to system libraries.
+ addProfileRTLinux(getToolChain(), Args, CmdArgs);
+
+ if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
@@ -6157,8 +6632,6 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
-
C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
}
@@ -6219,7 +6692,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -6367,7 +6840,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (D.CCCIsCXX) {
+ if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
@@ -6439,22 +6912,223 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles)) {
+ !Args.hasArg(options::OPT_nostartfiles) &&
+ !C.getDriver().IsCLMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
}
CmdArgs.push_back("-nologo");
+ bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
+
+ if (DLL) {
+ CmdArgs.push_back(Args.MakeArgString("-dll"));
+
+ SmallString<128> ImplibName(Output.getFilename());
+ llvm::sys::path::replace_extension(ImplibName, "lib");
+ CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") +
+ ImplibName.str()));
+ }
+
+ if (getToolChain().getSanitizerArgs().needsAsanRt()) {
+ CmdArgs.push_back(Args.MakeArgString("-debug"));
+ CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
+ SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir);
+ llvm::sys::path::append(LibSanitizer, "lib", "windows");
+ if (DLL) {
+ llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib");
+ } else {
+ llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib");
+ }
+ // FIXME: Handle 64-bit.
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+ }
+
Args.AddAllArgValues(CmdArgs, options::OPT_l);
+ Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
// Add filenames immediately.
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
if (it->isFilename())
CmdArgs.push_back(it->getFilename());
+ else
+ it->getInputArg().renderAsInput(Args, CmdArgs);
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+
+void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
+}
+
+// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
+// If one cannot be found, return FallbackName.
+// We do this special search to prevent clang-cl from falling back onto itself
+// if it's available as cl.exe on the path.
+static std::string FindFallback(const char *FallbackName,
+ const char *ClangProgramPath) {
+ llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
+ if (!OptPath.hasValue())
+ return FallbackName;
+
+#ifdef LLVM_ON_WIN32
+ const StringRef PathSeparators = ";";
+#else
+ const StringRef PathSeparators = ":";
+#endif
+
+ SmallVector<StringRef, 8> PathSegments;
+ llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators);
+
+ for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
+ const StringRef &PathSegment = PathSegments[i];
+ if (PathSegment.empty())
+ continue;
+
+ SmallString<128> FilePath(PathSegment);
+ llvm::sys::path::append(FilePath, FallbackName);
+ if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
+ !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
+ return FilePath.str();
+ }
+
+ return FallbackName;
+}
+
+Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+ CmdArgs.push_back("/nologo");
+ CmdArgs.push_back("/c"); // Compile only.
+ CmdArgs.push_back("/W0"); // No warnings.
+
+ // The goal is to be able to invoke this tool correctly based on
+ // any flag accepted by clang-cl.
+
+ // These are spelled the same way in clang and cl.exe,.
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+ Args.AddAllArgs(CmdArgs, options::OPT_I);
+
+ // Optimization level.
+ if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
+ if (A->getOption().getID() == options::OPT_O0) {
+ CmdArgs.push_back("/Od");
+ } else {
+ StringRef OptLevel = A->getValue();
+ if (OptLevel == "1" || OptLevel == "2" || OptLevel == "s")
+ A->render(Args, CmdArgs);
+ else if (OptLevel == "3")
+ CmdArgs.push_back("/Ox");
+ }
+ }
+
+ // Flags for which clang-cl have an alias.
+ // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
+
+ if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR"
+ : "/GR-");
+ if (Args.hasArg(options::OPT_fsyntax_only))
+ CmdArgs.push_back("/Zs");
+
+ std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
+ for (size_t I = 0, E = Includes.size(); I != E; ++I)
+ CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I]));
+
+ // Flags that can simply be passed through.
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
+
+ // The order of these flags is relevant, so pick the last one.
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
+ options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
+ A->render(Args, CmdArgs);
+
+
+ // Input filename.
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
+ CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+
+ // Output filename.
+ assert(Output.getType() == types::TY_Object);
+ const char *Fo = Args.MakeArgString(std::string("/Fo") +
+ Output.getFilename());
+ CmdArgs.push_back(Fo);
+
+ const Driver &D = getToolChain().getDriver();
+ std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());
+
+ return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs);
+}
+
+
+/// XCore Tools
+// We pass assemble and link construction to the xcc tool.
+
+void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ CmdArgs.push_back("-c");
+
+ if (Args.hasArg(options::OPT_g_Group)) {
+ CmdArgs.push_back("-g");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h
index d647171..d5b2848 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.h
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h
@@ -14,12 +14,14 @@
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/Compiler.h"
namespace clang {
class ObjCRuntime;
namespace driver {
+ class Command;
class Driver;
namespace toolchains {
@@ -27,40 +29,53 @@ namespace toolchains {
}
namespace tools {
+using llvm::opt::ArgStringList;
/// \brief Clang compiler tool.
class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
public:
- static const char *getBaseInputName(const ArgList &Args,
+ static const char *getBaseInputName(const llvm::opt::ArgList &Args,
const InputInfoList &Inputs);
- static const char *getBaseInputStem(const ArgList &Args,
+ static const char *getBaseInputStem(const llvm::opt::ArgList &Args,
const InputInfoList &Inputs);
- static const char *getDependencyFileName(const ArgList &Args,
+ static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
const InputInfoList &Inputs);
private:
- void AddPreprocessingOptions(Compilation &C,
- const JobAction &JA,
+ void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
const Driver &D,
- const ArgList &Args,
- ArgStringList &CmdArgs,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
const InputInfo &Output,
const InputInfoList &Inputs) const;
- void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddARMTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
bool KernelOrKext) const;
- void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddPPCTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddR600TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddHexagonTargetArgs (const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddR600TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddX86TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void AddHexagonTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
- ObjCRuntime AddObjCRuntimeArgs(const ArgList &args, ArgStringList &cmdArgs,
+ ObjCRuntime AddObjCRuntimeArgs(const llvm::opt::ArgList &args,
+ llvm::opt::ArgStringList &cmdArgs,
RewriteKind rewrite) const;
+ void AddClangCLArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
public:
Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {}
@@ -71,14 +86,12 @@ namespace tools {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
/// \brief Clang integrated assembler tool.
class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
- void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
- void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const;
public:
ClangAs(const ToolChain &TC) : Tool("clang::as",
"clang integrated assembler", TC) {}
@@ -90,7 +103,7 @@ namespace tools {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -104,16 +117,16 @@ namespace gcc {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
/// RenderExtraToolArgs - Render any arguments necessary to force
/// the particular tool mode.
- virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const = 0;
+ virtual void
+ RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const = 0;
};
-
class LLVM_LIBRARY_VISIBILITY Preprocess : public Common {
public:
Preprocess(const ToolChain &TC) : Common("gcc::Preprocess",
@@ -123,7 +136,7 @@ namespace gcc {
virtual bool hasIntegratedCPP() const { return false; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
};
class LLVM_LIBRARY_VISIBILITY Precompile : public Common {
@@ -135,7 +148,7 @@ namespace gcc {
virtual bool hasIntegratedCPP() const { return true; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
};
class LLVM_LIBRARY_VISIBILITY Compile : public Common {
@@ -147,7 +160,7 @@ namespace gcc {
virtual bool hasIntegratedCPP() const { return true; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
};
class LLVM_LIBRARY_VISIBILITY Assemble : public Common {
@@ -158,7 +171,7 @@ namespace gcc {
virtual bool hasIntegratedCPP() const { return false; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Common {
@@ -170,7 +183,7 @@ namespace gcc {
virtual bool isLinkJob() const { return true; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
};
} // end namespace gcc
@@ -185,11 +198,11 @@ namespace hexagon {
virtual bool hasIntegratedCPP() const { return false; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -202,11 +215,11 @@ namespace hexagon {
virtual bool isLinkJob() const { return true; }
virtual void RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace hexagon.
@@ -218,7 +231,8 @@ namespace darwin {
class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool {
virtual void anchor();
protected:
- void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const;
+ void AddDarwinArch(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
const toolchains::Darwin &getDarwinToolChain() const {
return reinterpret_cast<const toolchains::Darwin&>(getToolChain());
@@ -239,14 +253,15 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public DarwinTool {
bool NeedsTempPath(const InputInfoList &Inputs) const;
- void AddLinkArgs(Compilation &C, const ArgList &Args,
- ArgStringList &CmdArgs, const InputInfoList &Inputs) const;
+ void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const;
public:
Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {}
@@ -257,7 +272,7 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -270,7 +285,7 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -285,7 +300,7 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -299,7 +314,7 @@ namespace darwin {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
@@ -317,7 +332,7 @@ namespace openbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -330,7 +345,7 @@ namespace openbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace openbsd
@@ -347,7 +362,7 @@ namespace bitrig {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -360,7 +375,7 @@ namespace bitrig {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace bitrig
@@ -377,7 +392,7 @@ namespace freebsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -390,7 +405,7 @@ namespace freebsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace freebsd
@@ -408,7 +423,7 @@ namespace netbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -423,7 +438,7 @@ namespace netbsd {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace netbsd
@@ -439,7 +454,7 @@ namespace gnutools {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -452,7 +467,7 @@ namespace gnutools {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
}
@@ -468,7 +483,7 @@ namespace minix {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -481,7 +496,7 @@ namespace minix {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace minix
@@ -498,7 +513,7 @@ namespace solaris {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -511,7 +526,7 @@ namespace solaris {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace solaris
@@ -528,7 +543,7 @@ namespace auroraux {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -541,7 +556,7 @@ namespace auroraux {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace auroraux
@@ -558,7 +573,7 @@ namespace dragonfly {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -571,14 +586,14 @@ namespace dragonfly {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
};
} // end namespace dragonfly
/// Visual studio tools.
namespace visualstudio {
- class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {}
@@ -588,11 +603,64 @@ namespace visualstudio {
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
- const ArgList &TCArgs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Compile : public Tool {
+ public:
+ Compile(const ToolChain &TC) : Tool("visualstudio::Compile", "compiler", TC) {}
+
+ virtual bool hasIntegratedAssembler() const { return true; }
+ virtual bool hasIntegratedCPP() const { return true; }
+ virtual bool isLinkJob() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const;
+
+ Command *GetCommand(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
};
} // end namespace visualstudio
+namespace XCore {
+ // For XCore, we do not need to instantiate tools for PreProcess, PreCompile and Compile.
+ // We simply use "clang -cc1" for those actions.
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("XCore::Assemble",
+ "XCore-as", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("XCore::Link",
+ "XCore-ld", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+ virtual bool isLinkJob() const { return true; }
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace XCore.
+
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
index 7d22596..d947ae7 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Types.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include <cassert>
#include <string.h>
@@ -28,7 +29,7 @@ static const TypeInfo TypeInfos[] = {
#include "clang/Driver/Types.def"
#undef TYPE
};
-static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]);
+static const unsigned numTypes = llvm::array_lengthof(TypeInfos);
static const TypeInfo &getInfo(unsigned id) {
assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
@@ -43,7 +44,13 @@ types::ID types::getPreprocessedType(ID Id) {
return getInfo(Id).PreprocessedType;
}
-const char *types::getTypeTempSuffix(ID Id) {
+const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
+ if (Id == TY_Object && CLMode)
+ return "obj";
+ if (Id == TY_Image && CLMode)
+ return "exe";
+ if (Id == TY_PP_Asm && CLMode)
+ return "asm";
return getInfo(Id).TempSuffix;
}
@@ -132,8 +139,10 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
.Case("f", TY_PP_Fortran)
.Case("F", TY_Fortran)
.Case("s", TY_PP_Asm)
+ .Case("asm", TY_PP_Asm)
.Case("S", TY_Asm)
.Case("o", TY_Object)
+ .Case("obj", TY_Object)
.Case("ii", TY_PP_CXX)
.Case("mi", TY_PP_ObjC)
.Case("mm", TY_ObjCXX)
@@ -180,9 +189,7 @@ types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
}
// FIXME: Why don't we just put this list in the defs file, eh.
-void types::getCompilationPhases(
- ID Id,
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &P) {
+void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
if (Id != TY_Object) {
if (getPreprocessedType(Id) != TY_INVALID) {
P.push_back(phases::Preprocess);
diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
index 622c492..2b6320a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
@@ -10,12 +10,12 @@
#include "ToolChains.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Version.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
@@ -31,6 +31,7 @@
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
+using namespace llvm::opt;
Windows::Windows(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
@@ -44,7 +45,7 @@ Tool *Windows::buildLinker() const {
Tool *Windows::buildAssembler() const {
if (getTriple().getEnvironment() == llvm::Triple::MachO)
return new tools::darwin::Assemble(*this);
- getDriver().Diag(clang::diag::err_no_external_windows_assembler);
+ getDriver().Diag(clang::diag::err_no_external_assembler);
return NULL;
}
@@ -125,7 +126,8 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
strncpy(partialKey, subKey, partialKeyLength);
partialKey[partialKeyLength] = '\0';
HKEY hTopKey = NULL;
- lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
+ lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
+ &hTopKey);
if (lResult == ERROR_SUCCESS) {
char keyName[256];
int bestIndex = -1;
@@ -144,33 +146,34 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
char numBuf[32];
strncpy(numBuf, sp, sizeof(numBuf) - 1);
numBuf[sizeof(numBuf) - 1] = '\0';
- double value = strtod(numBuf, NULL);
- if (value > bestValue) {
- bestIndex = (int)index;
- bestValue = value;
+ double dvalue = strtod(numBuf, NULL);
+ if (dvalue > bestValue) {
+ // Test that InstallDir is indeed there before keeping this index.
+ // Open the chosen key path remainder.
strcpy(bestName, keyName);
+ // Append rest of key.
+ strncat(bestName, nextKey, sizeof(bestName) - 1);
+ bestName[sizeof(bestName) - 1] = '\0';
+ lResult = RegOpenKeyEx(hTopKey, bestName, 0,
+ KEY_READ | KEY_WOW64_32KEY, &hKey);
+ if (lResult == ERROR_SUCCESS) {
+ lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+ (LPBYTE)value, &valueSize);
+ if (lResult == ERROR_SUCCESS) {
+ bestIndex = (int)index;
+ bestValue = dvalue;
+ returnValue = true;
+ }
+ RegCloseKey(hKey);
+ }
}
size = sizeof(keyName) - 1;
}
- // If we found the highest versioned key, open the key and get the value.
- if (bestIndex != -1) {
- // Append rest of key.
- strncat(bestName, nextKey, sizeof(bestName) - 1);
- bestName[sizeof(bestName) - 1] = '\0';
- // Open the chosen key path remainder.
- lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
- if (lResult == ERROR_SUCCESS) {
- lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
- (LPBYTE)value, &valueSize);
- if (lResult == ERROR_SUCCESS)
- returnValue = true;
- RegCloseKey(hKey);
- }
- }
RegCloseKey(hTopKey);
}
} else {
- lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
+ lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY,
+ &hKey);
if (lResult == ERROR_SUCCESS) {
lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
(LPBYTE)value, &valueSize);
@@ -282,8 +285,8 @@ void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
- llvm::sys::Path P(getDriver().ResourceDir);
- P.appendComponent("include");
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P.str());
}
OpenPOWER on IntegriCloud