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.cpp146
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Compilation.cpp242
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Driver.cpp2109
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp44
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/InputInfo.h89
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Job.cpp189
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Multilib.cpp334
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Phases.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp338
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tool.cpp21
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp420
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp3603
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.h782
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp8013
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.h654
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Types.cpp231
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp338
17 files changed, 17579 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
new file mode 100644
index 0000000..86a48fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp
@@ -0,0 +1,146 @@
+//===--- Action.cpp - Abstract compilation steps --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Action.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+using namespace clang::driver;
+using namespace llvm::opt;
+
+Action::~Action() {
+ if (OwnsInputs) {
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ delete *it;
+ }
+}
+
+const char *Action::getClassName(ActionClass AC) {
+ switch (AC) {
+ case InputClass: return "input";
+ case BindArchClass: return "bind-arch";
+ case PreprocessJobClass: return "preprocessor";
+ case PrecompileJobClass: return "precompiler";
+ case AnalyzeJobClass: return "analyzer";
+ case MigrateJobClass: return "migrator";
+ case CompileJobClass: return "compiler";
+ case AssembleJobClass: return "assembler";
+ case LinkJobClass: return "linker";
+ case LipoJobClass: return "lipo";
+ case DsymutilJobClass: return "dsymutil";
+ case VerifyDebugInfoJobClass: return "verify-debug-info";
+ case VerifyPCHJobClass: return "verify-pch";
+ }
+
+ llvm_unreachable("invalid class");
+}
+
+void InputAction::anchor() {}
+
+InputAction::InputAction(const Arg &_Input, types::ID _Type)
+ : Action(InputClass, _Type), Input(_Input) {
+}
+
+void BindArchAction::anchor() {}
+
+BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
+ : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) {
+}
+
+void JobAction::anchor() {}
+
+JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
+ : Action(Kind, Input, Type) {
+}
+
+JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
+ : Action(Kind, Inputs, Type) {
+}
+
+void PreprocessJobAction::anchor() {}
+
+PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PreprocessJobClass, Input, OutputType) {
+}
+
+void PrecompileJobAction::anchor() {}
+
+PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(PrecompileJobClass, Input, OutputType) {
+}
+
+void AnalyzeJobAction::anchor() {}
+
+AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AnalyzeJobClass, Input, OutputType) {
+}
+
+void MigrateJobAction::anchor() {}
+
+MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
+ : JobAction(MigrateJobClass, Input, OutputType) {
+}
+
+void CompileJobAction::anchor() {}
+
+CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
+ : JobAction(CompileJobClass, Input, OutputType) {
+}
+
+void AssembleJobAction::anchor() {}
+
+AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
+ : JobAction(AssembleJobClass, Input, OutputType) {
+}
+
+void LinkJobAction::anchor() {}
+
+LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(LinkJobClass, Inputs, Type) {
+}
+
+void LipoJobAction::anchor() {}
+
+LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(LipoJobClass, Inputs, Type) {
+}
+
+void DsymutilJobAction::anchor() {}
+
+DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(DsymutilJobClass, Inputs, Type) {
+}
+
+void VerifyJobAction::anchor() {}
+
+VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
+ types::ID Type)
+ : JobAction(Kind, Input, Type) {
+ assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
+ "ActionClass is not a valid VerifyJobAction");
+}
+
+VerifyJobAction::VerifyJobAction(ActionClass Kind, ActionList &Inputs,
+ types::ID Type)
+ : JobAction(Kind, Inputs, Type) {
+ assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
+ "ActionClass is not a valid VerifyJobAction");
+}
+
+void VerifyDebugInfoJobAction::anchor() {}
+
+VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
+ types::ID Type)
+ : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {
+}
+
+void VerifyPCHJobAction::anchor() {}
+
+VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
+ : VerifyJobAction(VerifyPCHJobClass, Input, Type) {
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
new file mode 100644
index 0000000..49b7edd
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp
@@ -0,0 +1,242 @@
+//===--- Compilation.cpp - Compilation Task 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/Compilation.h"
+#include "clang/Driver/Action.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/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang;
+using namespace llvm::opt;
+
+Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
+ InputArgList *_Args, DerivedArgList *_TranslatedArgs)
+ : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
+ TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
+ ForDiagnostics(false) {}
+
+Compilation::~Compilation() {
+ delete TranslatedArgs;
+ delete Args;
+
+ // Free any derived arg lists.
+ for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
+ DerivedArgList*>::iterator it = TCArgs.begin(),
+ ie = TCArgs.end(); it != ie; ++it)
+ if (it->second != TranslatedArgs)
+ delete it->second;
+
+ // Free the actions, if built.
+ for (ActionList::iterator it = Actions.begin(), ie = Actions.end();
+ it != ie; ++it)
+ delete *it;
+
+ // Free redirections of stdout/stderr.
+ if (Redirects) {
+ delete Redirects[1];
+ delete Redirects[2];
+ delete [] Redirects;
+ }
+}
+
+const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
+ const char *BoundArch) {
+ if (!TC)
+ TC = &DefaultToolChain;
+
+ DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
+ if (!Entry) {
+ Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
+ if (!Entry)
+ Entry = TranslatedArgs;
+ }
+
+ return *Entry;
+}
+
+bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
+ // 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?
+
+ // 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 (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
+ return true;
+
+ if (std::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.
+
+ if (IssueErrors)
+ getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
+ << EC.message();
+ return false;
+ }
+ return true;
+}
+
+bool Compilation::CleanupFileList(const ArgStringList &Files,
+ bool IssueErrors) const {
+ bool Success = true;
+ for (ArgStringList::const_iterator
+ it = Files.begin(), ie = Files.end(); it != ie; ++it)
+ Success &= CleanupFile(*it, IssueErrors);
+ return Success;
+}
+
+bool Compilation::CleanupFileMap(const ArgStringMap &Files,
+ const JobAction *JA,
+ bool IssueErrors) const {
+ bool Success = true;
+ for (ArgStringMap::const_iterator
+ it = Files.begin(), ie = Files.end(); it != ie; ++it) {
+
+ // If specified, only delete the files associated with the JobAction.
+ // Otherwise, delete all files in the map.
+ if (JA && it->first != JA)
+ continue;
+ Success &= CleanupFile(it->second, IssueErrors);
+ }
+ return Success;
+}
+
+int Compilation::ExecuteCommand(const Command &C,
+ const Command *&FailingCommand) const {
+ if ((getDriver().CCPrintOptions ||
+ getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
+ raw_ostream *OS = &llvm::errs();
+
+ // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
+ // output stream.
+ if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
+ std::string Error;
+ OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, Error,
+ llvm::sys::fs::F_Append |
+ llvm::sys::fs::F_Text);
+ if (!Error.empty()) {
+ getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
+ << Error;
+ FailingCommand = &C;
+ delete OS;
+ return 1;
+ }
+ }
+
+ if (getDriver().CCPrintOptions)
+ *OS << "[Logging clang options]";
+
+ C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
+
+ if (OS != &llvm::errs())
+ delete OS;
+ }
+
+ std::string Error;
+ bool 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;
+ }
+
+ if (Res)
+ FailingCommand = &C;
+
+ return ExecutionFailed ? 1 : Res;
+}
+
+typedef SmallVectorImpl< std::pair<int, const Command *> > FailingCommandList;
+
+static bool ActionFailed(const Action *A,
+ const FailingCommandList &FailingCommands) {
+
+ if (FailingCommands.empty())
+ return false;
+
+ for (FailingCommandList::const_iterator CI = FailingCommands.begin(),
+ CE = FailingCommands.end(); CI != CE; ++CI)
+ if (A == &(CI->second->getSource()))
+ return true;
+
+ for (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI)
+ if (ActionFailed(*AI, FailingCommands))
+ return true;
+
+ return false;
+}
+
+static bool InputsOk(const Command &C,
+ const FailingCommandList &FailingCommands) {
+ return !ActionFailed(&C.getSource(), FailingCommands);
+}
+
+void Compilation::ExecuteJob(const Job &J,
+ FailingCommandList &FailingCommands) const {
+ if (const Command *C = dyn_cast<Command>(&J)) {
+ if (!InputsOk(*C, FailingCommands))
+ return;
+ const Command *FailingCommand = nullptr;
+ if (int Res = ExecuteCommand(*C, FailingCommand))
+ FailingCommands.push_back(std::make_pair(Res, FailingCommand));
+ } else {
+ const JobList *Jobs = cast<JobList>(&J);
+ for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end();
+ it != ie; ++it)
+ ExecuteJob(**it, FailingCommands);
+ }
+}
+
+void Compilation::initCompilationForDiagnostics() {
+ ForDiagnostics = true;
+
+ // Free actions and jobs.
+ DeleteContainerPointers(Actions);
+ Jobs.clear();
+
+ // Clear temporary/results file lists.
+ TempFiles.clear();
+ ResultFiles.clear();
+ FailureResultFiles.clear();
+
+ // Remove any user specified output. Claim any unclaimed arguments, so as
+ // to avoid emitting warnings about unused args.
+ OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
+ options::OPT_MMD };
+ for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
+ if (TranslatedArgs->hasArg(OutputOpts[i]))
+ TranslatedArgs->eraseArg(OutputOpts[i]);
+ }
+ TranslatedArgs->ClaimAllArgs();
+
+ // Redirect stdout/stderr to /dev/null.
+ Redirects = new const StringRef*[3]();
+ Redirects[0] = nullptr;
+ Redirects[1] = new const StringRef();
+ Redirects[2] = new const StringRef();
+}
+
+StringRef Compilation::getSysRoot() const {
+ return getDriver().SysRoot;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
new file mode 100644
index 0000000..ef26bfa
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp
@@ -0,0 +1,2109 @@
+//===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Driver.h"
+#include "InputInfo.h"
+#include "ToolChains.h"
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <memory>
+
+using namespace clang::driver;
+using namespace clang;
+using namespace llvm::opt;
+
+Driver::Driver(StringRef ClangExecutable,
+ StringRef DefaultTargetTriple,
+ DiagnosticsEngine &Diags)
+ : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
+ ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
+ UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
+ DefaultImageName("a.out"),
+ DriverTitle("clang LLVM compiler"),
+ CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
+ CCLogDiagnosticsFilename(nullptr),
+ CCCPrintBindings(false),
+ CCPrintHeaders(false), CCLogDiagnostics(false),
+ CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
+ CCCUsePCH(true), SuppressMissingInputWarning(false) {
+
+ Name = llvm::sys::path::stem(ClangExecutable);
+ Dir = llvm::sys::path::parent_path(ClangExecutable);
+
+ // Compute the path to the resource directory.
+ StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
+ SmallString<128> P(Dir);
+ if (ClangResourceDir != "")
+ llvm::sys::path::append(P, ClangResourceDir);
+ else
+ llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING);
+ ResourceDir = P.str();
+}
+
+Driver::~Driver() {
+ delete Opts;
+
+ llvm::DeleteContainerSeconds(ToolChains);
+}
+
+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;
+ std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ getIncludeExcludeOptionFlagMasks();
+
+ unsigned MissingArgIndex, MissingArgCount;
+ InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(),
+ MissingArgIndex, MissingArgCount,
+ IncludedFlagsBitmask,
+ ExcludedFlagsBitmask);
+
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diag(clang::diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+
+ // Check for unsupported options.
+ for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
+ it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().hasFlag(options::Unsupported)) {
+ Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
+ continue;
+ }
+
+ // Warn about -mcpu= without an argument.
+ if (A->getOption().matches(options::OPT_mcpu_EQ) &&
+ A->containsValue("")) {
+ Diag(clang::diag::warn_drv_empty_joined_argument) <<
+ A->getAsString(*Args);
+ }
+ }
+
+ 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;
+}
+
+// Determine which compilation mode we are in. We look for options which
+// affect the phase, starting with the earliest phases, and record which
+// option we used to determine the final phase.
+phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg)
+const {
+ Arg *PhaseArg = nullptr;
+ phases::ID FinalPhase;
+
+ // -{E,EP,P,M,MM} only run the preprocessor.
+ if (CCCIsCPP() ||
+ (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
+ FinalPhase = phases::Preprocess;
+
+ // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT__analyze,
+ options::OPT__analyze_auto)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_S))) {
+ FinalPhase = phases::Compile;
+
+ // -c only runs up to the assembler.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
+ FinalPhase = phases::Assemble;
+
+ // Otherwise do everything.
+ } else
+ FinalPhase = phases::Link;
+
+ if (FinalPhaseArg)
+ *FinalPhaseArg = PhaseArg;
+
+ return FinalPhase;
+}
+
+static Arg* MakeInputArg(DerivedArgList &Args, OptTable *Opts,
+ StringRef Value) {
+ Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value,
+ Args.getBaseArgs().MakeIndex(Value), Value.data());
+ Args.AddSynthesizedArg(A);
+ A->claim();
+ return A;
+}
+
+DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
+ DerivedArgList *DAL = new DerivedArgList(Args);
+
+ bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
+ for (ArgList::const_iterator it = Args.begin(),
+ ie = Args.end(); it != ie; ++it) {
+ const Arg *A = *it;
+
+ // Unfortunately, we have to parse some forwarding options (-Xassembler,
+ // -Xlinker, -Xpreprocessor) because we either integrate their functionality
+ // (assembler and preprocessor), or bypass a previous driver ('collect2').
+
+ // Rewrite linker options, to replace --no-demangle with a custom internal
+ // option.
+ if ((A->getOption().matches(options::OPT_Wl_COMMA) ||
+ A->getOption().matches(options::OPT_Xlinker)) &&
+ A->containsValue("--no-demangle")) {
+ // Add the rewritten no-demangle argument.
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_Xlinker__no_demangle));
+
+ // Add the remaining values as Xlinker arguments.
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i)
+ if (StringRef(A->getValue(i)) != "--no-demangle")
+ DAL->AddSeparateArg(A, Opts->getOption(options::OPT_Xlinker),
+ A->getValue(i));
+
+ continue;
+ }
+
+ // Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by
+ // some build systems. We don't try to be complete here because we don't
+ // care to encourage this usage model.
+ if (A->getOption().matches(options::OPT_Wp_COMMA) &&
+ (A->getValue(0) == StringRef("-MD") ||
+ A->getValue(0) == StringRef("-MMD"))) {
+ // Rewrite to -MD/-MMD along with -MF.
+ if (A->getValue(0) == StringRef("-MD"))
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_MD));
+ else
+ DAL->AddFlagArg(A, Opts->getOption(options::OPT_MMD));
+ if (A->getNumValues() == 2)
+ DAL->AddSeparateArg(A, Opts->getOption(options::OPT_MF),
+ A->getValue(1));
+ continue;
+ }
+
+ // Rewrite reserved library names.
+ if (A->getOption().matches(options::OPT_l)) {
+ StringRef Value = A->getValue();
+
+ // Rewrite unless -nostdlib is present.
+ if (!HasNostdlib && Value == "stdc++") {
+ DAL->AddFlagArg(A, Opts->getOption(
+ options::OPT_Z_reserved_lib_stdcxx));
+ continue;
+ }
+
+ // Rewrite unconditionally.
+ if (Value == "cc_kext") {
+ DAL->AddFlagArg(A, Opts->getOption(
+ options::OPT_Z_reserved_lib_cckext));
+ continue;
+ }
+ }
+
+ // 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);
+ }
+
+ // Add a default value of -mlinker-version=, if one was given and the user
+ // didn't specify one.
+#if defined(HOST_LINK_VERSION)
+ if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+ DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
+ HOST_LINK_VERSION);
+ DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
+ }
+#endif
+
+ return DAL;
+}
+
+Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
+ llvm::PrettyStackTraceString CrashInfo("Compilation construction");
+
+ // FIXME: Handle environment options which affect driver behavior, somewhere
+ // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS.
+
+ if (char *env = ::getenv("COMPILER_PATH")) {
+ StringRef CompilerPath = env;
+ while (!CompilerPath.empty()) {
+ std::pair<StringRef, StringRef> Split
+ = 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 CCCPrintActions;
+
+ InputArgList *Args = ParseArgStrings(ArgList.slice(1));
+
+ // -no-canonical-prefixes is used very early in main.
+ Args->ClaimAllArgs(options::OPT_no_canonical_prefixes);
+
+ // Ignore -pipe.
+ Args->ClaimAllArgs(options::OPT_pipe);
+
+ // Extract -ccc args.
+ //
+ // FIXME: We need to figure out where this behavior should live. Most of it
+ // should be outside in the client; the parts that aren't should have proper
+ // options, either by introducing new ones or by overloading gcc ones like -V
+ // or -b.
+ CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases);
+ CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings);
+ 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 MSVC-style Win32.
+ llvm::Triple T(DefaultTargetTriple);
+ T.setOS(llvm::Triple::Win32);
+ T.setEnvironment(llvm::Triple::MSVC);
+ 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))
+ Dir = InstalledDir = A->getValue();
+ for (arg_iterator it = Args->filtered_begin(options::OPT_B),
+ ie = Args->filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+ PrefixDirs.push_back(A->getValue(0));
+ }
+ 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;
+
+ if (const Arg *A = Args->getLastArg(options::OPT_resource_dir))
+ ResourceDir = A->getValue();
+
+ // Perform the default argument translations.
+ DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
+
+ // Owned by the host.
+ const ToolChain &TC = getToolChain(*Args);
+
+ // The compilation takes ownership of Args.
+ Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs);
+
+ if (!HandleImmediateArgs(*C))
+ return C;
+
+ // Construct the list of inputs.
+ InputList Inputs;
+ BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
+
+ // Construct the list of abstract actions to perform for this compilation. On
+ // MachO targets this uses the driver-driver and universal actions.
+ if (TC.getTriple().isOSBinFormatMachO())
+ BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
+ Inputs, C->getActions());
+ else
+ BuildActions(C->getDefaultToolChain(), C->getArgs(), Inputs,
+ C->getActions());
+
+ if (CCCPrintActions) {
+ PrintActions(*C);
+ return C;
+ }
+
+ BuildJobs(*C);
+
+ return C;
+}
+
+// When clang crashes, produce diagnostic information including the fully
+// preprocessed source file(s). Request that the developer attach the
+// diagnostic information to a bug report.
+void Driver::generateCompilationDiagnostics(Compilation &C,
+ const Command *FailingCommand) {
+ if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
+ return;
+
+ // Don't try to generate diagnostics for link or dsymutil jobs.
+ if (FailingCommand && (FailingCommand->getCreator().isLinkJob() ||
+ FailingCommand->getCreator().isDsymutilJob()))
+ return;
+
+ // Print the version of the compiler.
+ PrintVersion(C, llvm::errs());
+
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "PLEASE submit a bug report to " BUG_REPORT_URL " and include the "
+ "crash backtrace, preprocessed source, and associated run script.";
+
+ // Suppress driver output and emit preprocessor output to temp file.
+ Mode = CPPMode;
+ CCGenDiagnostics = true;
+
+ // Save the original job command(s).
+ std::string Cmd;
+ llvm::raw_string_ostream OS(Cmd);
+ if (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.getJobs().Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true);
+ OS.flush();
+
+ // Keep track of whether we produce any errors while trying to produce
+ // preprocessed sources.
+ DiagnosticErrorTrap Trap(Diags);
+
+ // Suppress tool output.
+ C.initCompilationForDiagnostics();
+
+ // Construct the list of inputs.
+ InputList Inputs;
+ BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs);
+
+ for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) {
+ bool IgnoreInput = false;
+
+ // Ignore input from stdin or any inputs that cannot be preprocessed.
+ // Check type first as not all linker inputs have a value.
+ if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
+ IgnoreInput = true;
+ } else if (!strcmp(it->second->getValue(), "-")) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s) - ignoring input from stdin"
+ ".";
+ IgnoreInput = true;
+ }
+
+ if (IgnoreInput) {
+ it = Inputs.erase(it);
+ ie = Inputs.end();
+ } else {
+ ++it;
+ }
+ }
+
+ if (Inputs.empty()) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s) - no preprocessable inputs.";
+ return;
+ }
+
+ // Don't attempt to generate preprocessed files if multiple -arch options are
+ // used, unless they're all duplicates.
+ llvm::StringSet<> ArchNames;
+ for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
+ it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().matches(options::OPT_arch)) {
+ StringRef ArchName = A->getValue();
+ ArchNames.insert(ArchName);
+ }
+ }
+ if (ArchNames.size() > 1) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s) - cannot generate "
+ "preprocessed source with multiple -arch options.";
+ return;
+ }
+
+ // Construct the list of abstract actions to perform for this compilation. On
+ // Darwin OSes this uses the driver-driver and builds universal actions.
+ const ToolChain &TC = C.getDefaultToolChain();
+ if (TC.getTriple().isOSBinFormatMachO())
+ BuildUniversalActions(TC, C.getArgs(), Inputs, C.getActions());
+ else
+ BuildActions(TC, C.getArgs(), Inputs, C.getActions());
+
+ BuildJobs(C);
+
+ // If there were errors building the compilation, quit now.
+ if (Trap.hasErrorOccurred()) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s).";
+ return;
+ }
+
+ // Generate preprocessed output.
+ SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
+ C.ExecuteJob(C.getJobs(), FailingCommands);
+
+ // If the command succeeded, we are done.
+ if (FailingCommands.empty()) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "\n********************\n\n"
+ "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
+ "Preprocessed source(s) and associated run script(s) are located at:";
+ ArgStringList Files = C.getTempFiles();
+ for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end();
+ it != ie; ++it) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << *it;
+ std::string Script = StringRef(*it).rsplit('.').first;
+ // In some cases (modules) we'll dump extra data to help with reproducing
+ // the crash into a directory next to the output.
+ SmallString<128> VFS;
+ if (llvm::sys::fs::exists(Script + ".cache")) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << Script + ".cache";
+ VFS = llvm::sys::path::filename(Script + ".cache");
+ llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
+ }
+
+ std::string Err;
+ Script += ".sh";
+ llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err, llvm::sys::fs::F_Excl);
+ if (!Err.empty()) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating run script: " + Script + " " + Err;
+ } else {
+ // Replace the original filename with the preprocessed one.
+ size_t I, E;
+ I = Cmd.find("-main-file-name ");
+ assert (I != std::string::npos && "Expected to find -main-file-name");
+ I += 16;
+ E = Cmd.find(" ", I);
+ assert (E != std::string::npos && "-main-file-name missing argument?");
+ StringRef OldFilename = StringRef(Cmd).slice(I, E);
+ StringRef NewFilename = llvm::sys::path::filename(*it);
+ I = StringRef(Cmd).rfind(OldFilename);
+ E = I + OldFilename.size();
+ I = Cmd.rfind(" ", I) + 1;
+ Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size());
+ if (!VFS.empty()) {
+ // Add the VFS overlay to the reproduction script.
+ I += NewFilename.size();
+ Cmd.insert(I, std::string(" -ivfsoverlay ") + VFS.c_str());
+ }
+ ScriptOS << Cmd;
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
+ }
+ }
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "\n\n********************";
+ } else {
+ // Failure, remove preprocessed files.
+ if (!C.getArgs().hasArg(options::OPT_save_temps))
+ C.CleanupFileList(C.getTempFiles(), true);
+
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Error generating preprocessed source(s).";
+ }
+}
+
+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.getJobs().Print(llvm::errs(), "\n", true);
+ return 0;
+ }
+
+ // If there were errors building the compilation, quit now.
+ if (Diags.hasErrorOccurred())
+ return 1;
+
+ C.ExecuteJob(C.getJobs(), FailingCommands);
+
+ // Remove temp files.
+ C.CleanupFileList(C.getTempFiles());
+
+ // If the command succeeded, we are done.
+ if (FailingCommands.empty())
+ return 0;
+
+ // Otherwise, remove result files and print extra information about abnormal
+ // failures.
+ for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it =
+ FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) {
+ int Res = it->first;
+ const Command *FailingCommand = it->second;
+
+ // Remove result files if we're not saving temps.
+ if (!C.getArgs().hasArg(options::OPT_save_temps)) {
+ const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());
+ C.CleanupFileMap(C.getResultFiles(), JA, true);
+
+ // Failure result files are valid unless we crashed.
+ if (Res < 0)
+ C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
+ }
+
+ // Print extra information about abnormal failures, if possible.
+ //
+ // This is ad-hoc, but we don't want to be excessively noisy. If the result
+ // status was 1, assume the command failed normally. In particular, if it
+ // was the compiler then assume it gave a reasonable error code. Failures
+ // in other tools are less common, and they generally have worse
+ // diagnostics, so always print the diagnostic there.
+ const Tool &FailingTool = FailingCommand->getCreator();
+
+ if (!FailingCommand->getCreator().hasGoodDiagnostics() || Res != 1) {
+ // FIXME: See FIXME above regarding result code interpretation.
+ if (Res < 0)
+ Diag(clang::diag::err_drv_command_signalled)
+ << FailingTool.getShortName();
+ else
+ Diag(clang::diag::err_drv_command_failed)
+ << FailingTool.getShortName() << Res;
+ }
+ }
+ return 0;
+}
+
+void Driver::PrintHelp(bool ShowHidden) const {
+ unsigned IncludedFlagsBitmask;
+ unsigned ExcludedFlagsBitmask;
+ std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ getIncludeExcludeOptionFlagMasks();
+
+ ExcludedFlagsBitmask |= options::NoDriverOption;
+ if (!ShowHidden)
+ ExcludedFlagsBitmask |= HelpHidden;
+
+ getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
+ IncludedFlagsBitmask, ExcludedFlagsBitmask);
+}
+
+void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
+ OS << getClangFullVersion() << '\n';
+ const ToolChain &TC = C.getDefaultToolChain();
+ OS << "Target: " << TC.getTripleString() << '\n';
+
+ // Print the threading model.
+ //
+ // FIXME: Implement correctly.
+ OS << "Thread model: " << "posix" << '\n';
+}
+
+/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
+/// option.
+static void PrintDiagnosticCategories(raw_ostream &OS) {
+ // Skip the empty category.
+ for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories();
+ i != max; ++i)
+ OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
+}
+
+bool Driver::HandleImmediateArgs(const Compilation &C) {
+ // The order these options are handled in gcc is all over the place, but we
+ // don't expect inconsistencies w.r.t. that to matter in practice.
+
+ if (C.getArgs().hasArg(options::OPT_dumpmachine)) {
+ llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n';
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_dumpversion)) {
+ // Since -dumpversion is only implemented for pedantic GCC compatibility, we
+ // return an answer which matches our definition of __VERSION__.
+ //
+ // If we want to return a more correct answer some day, then we should
+ // introduce a non-pedantically GCC compatible mode to Clang in which we
+ // provide sensible definitions for -dumpversion, __VERSION__, etc.
+ llvm::outs() << "4.2.1\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) {
+ PrintDiagnosticCategories(llvm::outs());
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_help) ||
+ C.getArgs().hasArg(options::OPT__help_hidden)) {
+ PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT__version)) {
+ // Follow gcc behavior and use stdout for --version and stderr for -v.
+ PrintVersion(C, llvm::outs());
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_v) ||
+ C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
+ PrintVersion(C, llvm::errs());
+ SuppressMissingInputWarning = true;
+ }
+
+ 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(),
+ ie = TC.getProgramPaths().end(); it != ie; ++it) {
+ if (it != TC.getProgramPaths().begin())
+ llvm::outs() << ':';
+ llvm::outs() << *it;
+ }
+ llvm::outs() << "\n";
+ llvm::outs() << "libraries: =" << ResourceDir;
+
+ StringRef sysroot = C.getSysRoot();
+
+ for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(),
+ ie = TC.getFilePaths().end(); it != ie; ++it) {
+ llvm::outs() << ':';
+ const char *path = it->c_str();
+ if (path[0] == '=')
+ llvm::outs() << sysroot << path + 1;
+ else
+ llvm::outs() << path;
+ }
+ llvm::outs() << "\n";
+ return false;
+ }
+
+ // FIXME: The following handlers should use a callback mechanism, we don't
+ // know what the client would like to do.
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
+ llvm::outs() << GetFilePath(A->getValue(), TC) << "\n";
+ return false;
+ }
+
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
+ llvm::outs() << GetProgramPath(A->getValue(), TC) << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
+ llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
+ const MultilibSet &Multilibs = TC.getMultilibs();
+
+ for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
+ I != E; ++I) {
+ llvm::outs() << *I << "\n";
+ }
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
+ const MultilibSet &Multilibs = TC.getMultilibs();
+ for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
+ I != E; ++I) {
+ if (I->gccSuffix().empty())
+ llvm::outs() << ".\n";
+ else {
+ StringRef Suffix(I->gccSuffix());
+ assert(Suffix.front() == '/');
+ llvm::outs() << Suffix.substr(1) << "\n";
+ }
+ }
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+ // FIXME: This should print out "lib/../lib", "lib/../lib64", or
+ // "lib/../lib32" as appropriate for the toolchain. For now, print
+ // nothing because it's not supported yet.
+ return false;
+ }
+
+ return true;
+}
+
+static unsigned PrintActions1(const Compilation &C, Action *A,
+ std::map<Action*, unsigned> &Ids) {
+ if (Ids.count(A))
+ return Ids[A];
+
+ std::string str;
+ llvm::raw_string_ostream os(str);
+
+ os << Action::getClassName(A->getKind()) << ", ";
+ if (InputAction *IA = dyn_cast<InputAction>(A)) {
+ os << "\"" << IA->getInputArg().getValue() << "\"";
+ } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
+ os << '"' << BIA->getArchName() << '"'
+ << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}";
+ } else {
+ os << "{";
+ for (Action::iterator it = A->begin(), ie = A->end(); it != ie;) {
+ os << PrintActions1(C, *it, Ids);
+ ++it;
+ if (it != ie)
+ os << ", ";
+ }
+ os << "}";
+ }
+
+ unsigned Id = Ids.size();
+ Ids[A] = Id;
+ llvm::errs() << Id << ": " << os.str() << ", "
+ << types::getTypeName(A->getType()) << "\n";
+
+ return Id;
+}
+
+void Driver::PrintActions(const Compilation &C) const {
+ std::map<Action*, unsigned> Ids;
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it)
+ PrintActions1(C, *it, Ids);
+}
+
+/// \brief Check whether the given input tree contains any compilation or
+/// assembly actions.
+static bool ContainsCompileOrAssembleAction(const Action *A) {
+ if (isa<CompileJobAction>(A) || isa<AssembleJobAction>(A))
+ return true;
+
+ for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
+ if (ContainsCompileOrAssembleAction(*it))
+ return true;
+
+ return false;
+}
+
+void Driver::BuildUniversalActions(const ToolChain &TC,
+ DerivedArgList &Args,
+ const InputList &BAInputs,
+ ActionList &Actions) const {
+ llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
+ // Collect the list of architectures. Duplicates are allowed, but should only
+ // be handled once (in the order seen).
+ llvm::StringSet<> ArchNames;
+ SmallVector<const char *, 4> Archs;
+ for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
+ it != ie; ++it) {
+ Arg *A = *it;
+
+ if (A->getOption().matches(options::OPT_arch)) {
+ // Validate the option here; we don't save the type here because its
+ // particular spelling may participate in other driver choices.
+ llvm::Triple::ArchType Arch =
+ tools::darwin::getArchTypeForMachOArchName(A->getValue());
+ if (Arch == llvm::Triple::UnknownArch) {
+ Diag(clang::diag::err_drv_invalid_arch_name)
+ << A->getAsString(Args);
+ continue;
+ }
+
+ A->claim();
+ if (ArchNames.insert(A->getValue()))
+ Archs.push_back(A->getValue());
+ }
+ }
+
+ // When there is no explicit arch for this platform, make sure we still bind
+ // the architecture (to the default) so that -Xarch_ is handled correctly.
+ if (!Archs.size())
+ Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));
+
+ ActionList SingleActions;
+ BuildActions(TC, Args, BAInputs, SingleActions);
+
+ // Add in arch bindings for every top level action, as well as lipo and
+ // dsymutil steps if needed.
+ for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) {
+ Action *Act = SingleActions[i];
+
+ // Make sure we can lipo this kind of output. If not (and it is an actual
+ // output) then we disallow, since we can't create an output file with the
+ // right name without overwriting it. We could remove this oddity by just
+ // changing the output names to include the arch, which would also fix
+ // -save-temps. Compatibility wins for now.
+
+ if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
+ Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
+ << types::getTypeName(Act->getType());
+
+ ActionList Inputs;
+ for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
+ Inputs.push_back(new BindArchAction(Act, Archs[i]));
+ if (i != 0)
+ Inputs.back()->setOwnsInputs(false);
+ }
+
+ // Lipo if necessary, we do it this way because we need to set the arch flag
+ // so that -Xarch_ gets overwritten.
+ if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
+ Actions.append(Inputs.begin(), Inputs.end());
+ else
+ Actions.push_back(new LipoJobAction(Inputs, Act->getType()));
+
+ // Handle debug info queries.
+ Arg *A = Args.getLastArg(options::OPT_g_Group);
+ if (A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_gstabs) &&
+ ContainsCompileOrAssembleAction(Actions.back())) {
+
+ // Add a 'dsymutil' step if necessary, when debug info is enabled and we
+ // have a compile input. We need to run 'dsymutil' ourselves in such cases
+ // because the debug info will refer to a temporary object file which
+ // will be removed at the end of the compilation process.
+ if (Act->getType() == types::TY_Image) {
+ ActionList Inputs;
+ Inputs.push_back(Actions.back());
+ Actions.pop_back();
+ Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
+ }
+
+ // Verify the debug info output.
+ if (Args.hasArg(options::OPT_verify_debug_info)) {
+ Action *VerifyInput = Actions.back();
+ Actions.pop_back();
+ Actions.push_back(new VerifyDebugInfoJobAction(VerifyInput,
+ types::TY_Nothing));
+ }
+ }
+ }
+}
+
+/// \brief Check that the file referenced by Value exists. If it doesn't,
+/// issue a diagnostic and return false.
+static bool DiagnoseInputExistence(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;
+
+ if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value))
+ 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, DerivedArgList &Args,
+ InputList &Inputs) const {
+ // Track the current user specified (-x) input. We also explicitly track the
+ // argument used to set the type; we only want to claim the type when we
+ // actually use it, so we warn about unused -x arguments.
+ types::ID InputType = types::TY_Nothing;
+ Arg *InputTypeArg = nullptr;
+
+ // 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;
+
+ if (A->getOption().getKind() == Option::InputClass) {
+ const char *Value = A->getValue();
+ types::ID Ty = types::TY_INVALID;
+
+ // Infer the input type if necessary.
+ if (InputType == types::TY_Nothing) {
+ // If there was an explicit arg for this, claim it.
+ if (InputTypeArg)
+ InputTypeArg->claim();
+
+ // stdin must be handled specially.
+ if (memcmp(Value, "-", 2) == 0) {
+ // If running with -E, treat as a C input (this changes the builtin
+ // macros, for example). This may be overridden by -ObjC below.
+ //
+ // 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())
+ Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
+ : clang::diag::err_drv_unknown_stdin_type);
+ Ty = types::TY_C;
+ } else {
+ // Otherwise lookup by extension.
+ // Fallback is C if invoked as C preprocessor or Object otherwise.
+ // We use a host hook here because Darwin at least has its own
+ // idea of what .s is.
+ if (const char *Ext = strrchr(Value, '.'))
+ Ty = TC.LookupTypeForExtension(Ext + 1);
+
+ if (Ty == types::TY_INVALID) {
+ if (CCCIsCPP())
+ Ty = types::TY_C;
+ else
+ Ty = types::TY_Object;
+ }
+
+ // 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()) {
+ types::ID OldTy = Ty;
+ Ty = types::lookupCXXTypeForCType(Ty);
+
+ if (Ty != OldTy)
+ Diag(clang::diag::warn_drv_treating_input_as_cxx)
+ << getTypeName(OldTy) << getTypeName(Ty);
+ }
+ }
+
+ // -ObjC and -ObjC++ override the default language, but only for "source
+ // files". We just treat everything that isn't a linker input as a
+ // source file.
+ //
+ // FIXME: Clean this up if we move the phase sequence into the type.
+ if (Ty != types::TY_Object) {
+ if (Args.hasArg(options::OPT_ObjC))
+ Ty = types::TY_ObjC;
+ else if (Args.hasArg(options::OPT_ObjCXX))
+ Ty = types::TY_ObjCXX;
+ }
+ } else {
+ assert(InputTypeArg && "InputType set w/o InputTypeArg");
+ InputTypeArg->claim();
+ Ty = InputType;
+ }
+
+ if (DiagnoseInputExistence(*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 (DiagnoseInputExistence(*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 (DiagnoseInputExistence(*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.
+ Inputs.push_back(std::make_pair(types::TY_Object, A));
+
+ } else if (A->getOption().matches(options::OPT_x)) {
+ InputTypeArg = A;
+ InputType = types::lookupTypeForTypeSpecifier(A->getValue());
+ A->claim();
+
+ // Follow gcc behavior and treat as linker input for invalid -x
+ // options. Its not clear why we shouldn't just revert to unknown; but
+ // this isn't very important, we might as well be bug compatible.
+ if (!InputType) {
+ Diag(clang::diag::err_drv_unknown_language) << A->getValue();
+ InputType = types::TY_Object;
+ }
+ }
+ }
+ if (CCCIsCPP() && Inputs.empty()) {
+ // If called as standalone preprocessor, stdin is processed
+ // if no other input is present.
+ Arg *A = MakeInputArg(Args, Opts, "-");
+ Inputs.push_back(std::make_pair(types::TY_C, A));
+ }
+}
+
+void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
+
+ if (!SuppressMissingInputWarning && Inputs.empty()) {
+ Diag(clang::diag::err_drv_no_input_files);
+ return;
+ }
+
+ 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;
+
+ llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
+ for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
+ types::ID InputType = Inputs[i].first;
+ const Arg *InputArg = Inputs[i].second;
+
+ PL.clear();
+ types::getCompilationPhases(InputType, PL);
+
+ // If the first step comes after the final phase we are doing as part of
+ // this compilation, warn the user about it.
+ phases::ID InitialPhase = PL[0];
+ if (InitialPhase > FinalPhase) {
+ // Claim here to avoid the more general unused warning.
+ InputArg->claim();
+
+ // Suppress all unused style warnings with -Qunused-arguments
+ if (Args.hasArg(options::OPT_Qunused_arguments))
+ continue;
+
+ // Special case when final phase determined by binary name, rather than
+ // by a command-line argument with a corresponding Arg.
+ if (CCCIsCPP())
+ Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
+ << InputArg->getAsString(Args)
+ << getPhaseName(InitialPhase);
+ // Special case '-E' warning on a previously preprocessed file to make
+ // more sense.
+ else if (InitialPhase == phases::Compile &&
+ FinalPhase == phases::Preprocess &&
+ getPreprocessedType(InputType) == types::TY_INVALID)
+ Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
+ << InputArg->getAsString(Args)
+ << !!FinalPhaseArg
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+ else
+ Diag(clang::diag::warn_drv_input_file_unused)
+ << InputArg->getAsString(Args)
+ << getPhaseName(InitialPhase)
+ << !!FinalPhaseArg
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
+ continue;
+ }
+
+ // Build the pipeline for this file.
+ std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
+ for (SmallVectorImpl<phases::ID>::iterator
+ i = PL.begin(), e = PL.end(); i != e; ++i) {
+ phases::ID Phase = *i;
+
+ // We are done if this step is past what the user requested.
+ if (Phase > FinalPhase)
+ break;
+
+ // Queue linker inputs.
+ if (Phase == phases::Link) {
+ assert((i + 1) == e && "linking must be final compilation step.");
+ LinkerInputs.push_back(Current.release());
+ break;
+ }
+
+ // Some types skip the assembler phase (e.g., llvm-bc), but we can't
+ // encode this in the steps because the intermediate type depends on
+ // arguments. Just special case here.
+ if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm)
+ continue;
+
+ // Otherwise construct the appropriate action.
+ Current.reset(ConstructPhaseAction(Args, Phase, Current.release()));
+ if (Current->getType() == types::TY_Nothing)
+ break;
+ }
+
+ // If we ended with something, add to the output list.
+ if (Current)
+ Actions.push_back(Current.release());
+ }
+
+ // Add a link action if necessary.
+ if (!LinkerInputs.empty())
+ Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+
+ // If we are linking, claim any options which are obviously only used for
+ // compilation.
+ 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,
+ Action *Input) const {
+ llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
+ // Build the appropriate action.
+ switch (Phase) {
+ case phases::Link: llvm_unreachable("link action invalid here.");
+ case phases::Preprocess: {
+ types::ID OutputTy;
+ // -{M, MM} alter the output type.
+ if (Args.hasArg(options::OPT_M, options::OPT_MM)) {
+ OutputTy = types::TY_Dependencies;
+ } else {
+ OutputTy = Input->getType();
+ if (!Args.hasFlag(options::OPT_frewrite_includes,
+ options::OPT_fno_rewrite_includes, false) &&
+ !CCGenDiagnostics)
+ OutputTy = types::getPreprocessedType(OutputTy);
+ assert(OutputTy != types::TY_INVALID &&
+ "Cannot preprocess this input type!");
+ }
+ return new PreprocessJobAction(Input, OutputTy);
+ }
+ case phases::Precompile: {
+ types::ID OutputTy = types::TY_PCH;
+ if (Args.hasArg(options::OPT_fsyntax_only)) {
+ // Syntax checks should not emit a PCH file
+ OutputTy = types::TY_Nothing;
+ }
+ return new PrecompileJobAction(Input, OutputTy);
+ }
+ case phases::Compile: {
+ if (Args.hasArg(options::OPT_fsyntax_only)) {
+ return new CompileJobAction(Input, types::TY_Nothing);
+ } else if (Args.hasArg(options::OPT_rewrite_objc)) {
+ return new CompileJobAction(Input, types::TY_RewrittenObjC);
+ } else if (Args.hasArg(options::OPT_rewrite_legacy_objc)) {
+ return new CompileJobAction(Input, types::TY_RewrittenLegacyObjC);
+ } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) {
+ return new AnalyzeJobAction(Input, types::TY_Plist);
+ } else if (Args.hasArg(options::OPT__migrate)) {
+ return new MigrateJobAction(Input, types::TY_Remap);
+ } else if (Args.hasArg(options::OPT_emit_ast)) {
+ return new CompileJobAction(Input, types::TY_AST);
+ } else if (Args.hasArg(options::OPT_module_file_info)) {
+ return new CompileJobAction(Input, types::TY_ModuleFile);
+ } else if (Args.hasArg(options::OPT_verify_pch)) {
+ return new VerifyPCHJobAction(Input, types::TY_Nothing);
+ } else if (IsUsingLTO(Args)) {
+ 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);
+ }
+ }
+ case phases::Assemble:
+ return new AssembleJobAction(Input, types::TY_Object);
+ }
+
+ llvm_unreachable("invalid phase in ConstructPhaseAction");
+}
+
+bool Driver::IsUsingLTO(const ArgList &Args) const {
+ if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false))
+ return true;
+
+ return false;
+}
+
+void Driver::BuildJobs(Compilation &C) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+
+ Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
+
+ // It is an error to provide a -o option if we are making multiple output
+ // files.
+ if (FinalOutput) {
+ unsigned NumOutputs = 0;
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it)
+ if ((*it)->getType() != types::TY_Nothing)
+ ++NumOutputs;
+
+ if (NumOutputs > 1) {
+ Diag(clang::diag::err_drv_output_argument_with_multiple_files);
+ FinalOutput = nullptr;
+ }
+ }
+
+ // Collect the list of architectures.
+ llvm::StringSet<> ArchNames;
+ if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) {
+ for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
+ it != ie; ++it) {
+ Arg *A = *it;
+ if (A->getOption().matches(options::OPT_arch))
+ ArchNames.insert(A->getValue());
+ }
+ }
+
+ for (ActionList::const_iterator it = C.getActions().begin(),
+ ie = C.getActions().end(); it != ie; ++it) {
+ Action *A = *it;
+
+ // If we are linking an image for multiple archs then the linker wants
+ // -arch_multiple and -final_output <final image name>. Unfortunately, this
+ // doesn't fit in cleanly because we have to pass this information down.
+ //
+ // FIXME: This is a hack; find a cleaner way to integrate this into the
+ // process.
+ const char *LinkingOutput = nullptr;
+ if (isa<LipoJobAction>(A)) {
+ if (FinalOutput)
+ LinkingOutput = FinalOutput->getValue();
+ else
+ LinkingOutput = DefaultImageName.c_str();
+ }
+
+ InputInfo II;
+ BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+ /*BoundArch*/nullptr,
+ /*AtTopLevel*/ true,
+ /*MultipleArchs*/ ArchNames.size() > 1,
+ /*LinkingOutput*/ LinkingOutput,
+ II);
+ }
+
+ // If the user passed -Qunused-arguments or there were errors, don't warn
+ // about any unused arguments.
+ if (Diags.hasErrorOccurred() ||
+ C.getArgs().hasArg(options::OPT_Qunused_arguments))
+ return;
+
+ // 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;
+
+ // FIXME: It would be nice to be able to send the argument to the
+ // DiagnosticsEngine, so that extra values, position, and so on could be
+ // printed.
+ if (!A->isClaimed()) {
+ if (A->getOption().hasFlag(options::NoArgumentUnused))
+ continue;
+
+ // Suppress the warning automatically if this is just a flag, and it is an
+ // instance of an argument we already claimed.
+ const Option &Opt = A->getOption();
+ if (Opt.getKind() == Option::FlagClass) {
+ bool DuplicateClaimed = false;
+
+ for (arg_iterator it = C.getArgs().filtered_begin(&Opt),
+ ie = C.getArgs().filtered_end(); it != ie; ++it) {
+ if ((*it)->isClaimed()) {
+ DuplicateClaimed = true;
+ break;
+ }
+ }
+
+ if (DuplicateClaimed)
+ continue;
+ }
+
+ Diag(clang::diag::warn_drv_unused_argument)
+ << A->getAsString(C.getArgs());
+ }
+ }
+}
+
+static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
+ const JobAction *JA,
+ const ActionList *&Inputs) {
+ const Tool *ToolForJob = nullptr;
+
+ // See if we should look for a compiler with an integrated assembler. We match
+ // bottom up, so what we are actually looking for is an assembler job with a
+ // compiler input.
+
+ if (TC->useIntegratedAs() &&
+ !C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT_via_file_asm) &&
+ !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 =
+ TC->SelectTool(cast<JobAction>(**Inputs->begin()));
+ if (!Compiler)
+ return nullptr;
+ if (Compiler->hasIntegratedAssembler()) {
+ Inputs = &(*Inputs)[0]->getInputs();
+ ToolForJob = Compiler;
+ }
+ }
+
+ // Otherwise use the tool for the current job.
+ if (!ToolForJob)
+ ToolForJob = TC->SelectTool(*JA);
+
+ // See if we should use an integrated preprocessor. We do so when we have
+ // exactly one input, since this is the only use case we care about
+ // (irrelevant since we don't support combine yet).
+ if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) &&
+ !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
+ !C.getArgs().hasArg(options::OPT_traditional_cpp) &&
+ !C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT_rewrite_objc) &&
+ ToolForJob->hasIntegratedCPP())
+ Inputs = &(*Inputs)[0]->getInputs();
+
+ return ToolForJob;
+}
+
+void Driver::BuildJobsForAction(Compilation &C,
+ const Action *A,
+ const ToolChain *TC,
+ const char *BoundArch,
+ bool AtTopLevel,
+ bool MultipleArchs,
+ const char *LinkingOutput,
+ InputInfo &Result) const {
+ llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
+
+ if (const InputAction *IA = dyn_cast<InputAction>(A)) {
+ // FIXME: It would be nice to not claim this here; maybe the old scheme of
+ // just using Args was better?
+ const Arg &Input = IA->getInputArg();
+ Input.claim();
+ if (Input.getOption().matches(options::OPT_INPUT)) {
+ const char *Name = Input.getValue();
+ Result = InputInfo(Name, A->getType(), Name);
+ } else
+ Result = InputInfo(&Input, A->getType(), "");
+ return;
+ }
+
+ if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
+ const ToolChain *TC;
+ const char *ArchName = BAA->getArchName();
+
+ if (ArchName)
+ TC = &getToolChain(C.getArgs(), ArchName);
+ else
+ TC = &C.getDefaultToolChain();
+
+ BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
+ AtTopLevel, MultipleArchs, LinkingOutput, Result);
+ return;
+ }
+
+ const ActionList *Inputs = &A->getInputs();
+
+ const JobAction *JA = cast<JobAction>(A);
+ const Tool *T = SelectToolForJob(C, TC, JA, Inputs);
+ if (!T)
+ return;
+
+ // Only use pipes when there is exactly one input.
+ InputInfoList InputInfos;
+ for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
+ it != ie; ++it) {
+ // Treat dsymutil and verify sub-jobs as being at the top-level too, they
+ // shouldn't get temporary output names.
+ // FIXME: Clean this up.
+ bool SubJobAtTopLevel = false;
+ if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A)))
+ SubJobAtTopLevel = true;
+
+ InputInfo II;
+ BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
+ LinkingOutput, II);
+ InputInfos.push_back(II);
+ }
+
+ // Always use the first input as the base input.
+ const char *BaseInput = InputInfos[0].getBaseInput();
+
+ // ... except dsymutil actions, which use their actual input as the base
+ // input.
+ if (JA->getType() == types::TY_dSYM)
+ BaseInput = InputInfos[0].getFilename();
+
+ // Determine the place to write output to, if any.
+ if (JA->getType() == types::TY_Nothing)
+ Result = InputInfo(A->getType(), BaseInput);
+ else
+ Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
+ AtTopLevel, MultipleArchs),
+ A->getType(), BaseInput);
+
+ if (CCCPrintBindings && !CCGenDiagnostics) {
+ llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
+ << " - \"" << T->getName() << "\", inputs: [";
+ for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
+ llvm::errs() << InputInfos[i].getAsString();
+ if (i + 1 != e)
+ llvm::errs() << ", ";
+ }
+ llvm::errs() << "], output: " << Result.getAsString() << "\n";
+ } else {
+ T->ConstructJob(C, *JA, Result, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
+ }
+}
+
+/// \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,
+ const char *BoundArch,
+ bool AtTopLevel,
+ bool MultipleArchs) const {
+ llvm::PrettyStackTraceString CrashInfo("Computing output path");
+ // Output to a user requested destination?
+ if (AtTopLevel && !isa<DsymutilJobAction>(JA) &&
+ !isa<VerifyJobAction>(JA)) {
+ if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
+ return C.addResultFile(FinalOutput->getValue(), &JA);
+ }
+
+ // For /P, preprocess to file named after BaseInput.
+ if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
+ assert(AtTopLevel && isa<PreprocessJobAction>(JA));
+ StringRef BaseName = llvm::sys::path::filename(BaseInput);
+ StringRef NameArg;
+ if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
+ NameArg = A->getValue();
+ return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName,
+ types::TY_PP_C), &JA);
+ }
+
+ // Default to writing to stdout?
+ if (AtTopLevel && !CCGenDiagnostics &&
+ (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) &&
+ !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(), IsCLMode()));
+ return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+ }
+
+ SmallString<128> BasePath(BaseInput);
+ StringRef BaseName;
+
+ // Dsymutil actions should use the full path.
+ if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))
+ BaseName = BasePath;
+ else
+ BaseName = llvm::sys::path::filename(BasePath);
+
+ // Determine what the derived output name should be.
+ const char *NamedOutput;
+
+ 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);
+ NamedOutput = C.getArgs().MakeArgString(Output.c_str());
+ } else
+ NamedOutput = DefaultImageName.c_str();
+ } else {
+ 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;
+ if (!types::appendSuffixForType(JA.getType()))
+ End = BaseName.rfind('.');
+ SmallString<128> Suffixed(BaseName.substr(0, End));
+ if (MultipleArchs && BoundArch) {
+ Suffixed += "-";
+ Suffixed.append(BoundArch);
+ }
+ Suffixed += '.';
+ Suffixed += Suffix;
+ NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
+ }
+
+ // If we're saving temps and the temp file conflicts with the input file,
+ // then avoid overwriting input file.
+ if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) &&
+ NamedOutput == BaseName) {
+
+ bool SameFile = false;
+ SmallString<256> Result;
+ llvm::sys::fs::current_path(Result);
+ llvm::sys::path::append(Result, BaseName);
+ llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile);
+ // Must share the same path to conflict.
+ if (SameFile) {
+ StringRef Name = llvm::sys::path::filename(BaseInput);
+ std::pair<StringRef, StringRef> Split = Name.split('.');
+ std::string TmpName =
+ GetTemporaryPath(Split.first,
+ types::getTypeTempSuffix(JA.getType(), IsCLMode()));
+ return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+ }
+ }
+
+ // As an annoying special case, PCH generation doesn't strip the pathname.
+ if (JA.getType() == types::TY_PCH) {
+ llvm::sys::path::remove_filename(BasePath);
+ if (BasePath.empty())
+ BasePath = NamedOutput;
+ else
+ llvm::sys::path::append(BasePath, NamedOutput);
+ return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()), &JA);
+ } else {
+ return C.addResultFile(NamedOutput, &JA);
+ }
+}
+
+std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // attempting to use this prefix when looking for file paths.
+ for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(),
+ ie = PrefixDirs.end(); it != ie; ++it) {
+ std::string Dir(*it);
+ if (Dir.empty())
+ continue;
+ if (Dir[0] == '=')
+ Dir = SysRoot + Dir.substr(1);
+ SmallString<128> P(Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
+ return P.str();
+ }
+
+ 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();
+ for (ToolChain::path_list::const_iterator
+ it = List.begin(), ie = List.end(); it != ie; ++it) {
+ std::string Dir(*it);
+ if (Dir.empty())
+ continue;
+ if (Dir[0] == '=')
+ Dir = SysRoot + Dir.substr(1);
+ SmallString<128> P(Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
+ return P.str();
+ }
+
+ return Name;
+}
+
+std::string Driver::GetProgramPath(const char *Name,
+ const ToolChain &TC) const {
+ // FIXME: Needs a better variable than DefaultTargetTriple
+ std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name);
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // 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) {
+ 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 {
+ 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) {
+ 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.
+ std::string P(llvm::sys::FindProgramByName(TargetSpecificExecutable));
+ if (!P.empty())
+ return P;
+
+ P = llvm::sys::FindProgramByName(Name);
+ if (!P.empty())
+ return P;
+
+ return Name;
+}
+
+std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
+ const {
+ SmallString<128> Path;
+ std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
+ if (EC) {
+ Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return "";
+ }
+
+ return Path.str();
+}
+
+/// \brief Compute target triple from args.
+///
+/// This routine provides the logic to compute a target triple from various
+/// args passed to the driver and the default triple string.
+static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
+ const ArgList &Args,
+ StringRef DarwinArchName) {
+ // FIXME: Already done in Compilation *Driver::BuildCompilation
+ if (const Arg *A = Args.getLastArg(options::OPT_target))
+ DefaultTargetTriple = A->getValue();
+
+ llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+
+ // Handle Apple-specific options available here.
+ if (Target.isOSBinFormatMachO()) {
+ // If an explict Darwin arch name is given, that trumps all.
+ if (!DarwinArchName.empty()) {
+ tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
+ return Target;
+ }
+
+ // Handle the Darwin '-arch' flag.
+ if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+ StringRef ArchName = A->getValue();
+ tools::darwin::setTripleTypeForMachOArchName(Target, ArchName);
+ }
+ }
+
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian)) {
+ if (Target.getArch() == llvm::Triple::mips)
+ Target.setArch(llvm::Triple::mipsel);
+ else if (Target.getArch() == llvm::Triple::mips64)
+ Target.setArch(llvm::Triple::mips64el);
+ else if (Target.getArch() == llvm::Triple::aarch64_be)
+ Target.setArch(llvm::Triple::aarch64);
+ else if (Target.getArch() == llvm::Triple::arm64_be)
+ Target.setArch(llvm::Triple::arm64);
+ } else {
+ if (Target.getArch() == llvm::Triple::mipsel)
+ Target.setArch(llvm::Triple::mips);
+ else if (Target.getArch() == llvm::Triple::mips64el)
+ Target.setArch(llvm::Triple::mips64);
+ else if (Target.getArch() == llvm::Triple::aarch64)
+ Target.setArch(llvm::Triple::aarch64_be);
+ else if (Target.getArch() == llvm::Triple::arm64)
+ Target.setArch(llvm::Triple::arm64_be);
+ }
+ }
+
+ // Skip further flag support on OSes which don't support '-m32' or '-m64'.
+ if (Target.getArchName() == "tce" ||
+ Target.getOS() == llvm::Triple::AuroraUX ||
+ Target.getOS() == llvm::Triple::Minix)
+ return Target;
+
+ // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
+ if (Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
+ options::OPT_m32, options::OPT_m16)) {
+ llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
+
+ if (A->getOption().matches(options::OPT_m64))
+ AT = Target.get64BitArchVariant().getArch();
+ else if (A->getOption().matches(options::OPT_mx32) &&
+ Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
+ AT = llvm::Triple::x86_64;
+ Target.setEnvironment(llvm::Triple::GNUX32);
+ } else if (A->getOption().matches(options::OPT_m32))
+ AT = Target.get32BitArchVariant().getArch();
+ else if (A->getOption().matches(options::OPT_m16) &&
+ Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
+ AT = llvm::Triple::x86;
+ Target.setEnvironment(llvm::Triple::CODE16);
+ }
+
+ if (AT != llvm::Triple::UnknownArch)
+ Target.setArch(AT);
+ }
+
+ return Target;
+}
+
+const ToolChain &Driver::getToolChain(const ArgList &Args,
+ StringRef DarwinArchName) const {
+ llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args,
+ DarwinArchName);
+
+ ToolChain *&TC = ToolChains[Target.str()];
+ if (!TC) {
+ switch (Target.getOS()) {
+ case llvm::Triple::AuroraUX:
+ TC = new toolchains::AuroraUX(*this, Target, Args);
+ break;
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS:
+ TC = new toolchains::DarwinClang(*this, Target, Args);
+ break;
+ case llvm::Triple::DragonFly:
+ TC = new toolchains::DragonFly(*this, Target, Args);
+ break;
+ case llvm::Triple::OpenBSD:
+ TC = new toolchains::OpenBSD(*this, Target, Args);
+ break;
+ case llvm::Triple::Bitrig:
+ TC = new toolchains::Bitrig(*this, Target, Args);
+ break;
+ case llvm::Triple::NetBSD:
+ TC = new toolchains::NetBSD(*this, Target, Args);
+ break;
+ case llvm::Triple::FreeBSD:
+ TC = new toolchains::FreeBSD(*this, Target, Args);
+ break;
+ case llvm::Triple::Minix:
+ TC = new toolchains::Minix(*this, Target, Args);
+ break;
+ case llvm::Triple::Linux:
+ if (Target.getArch() == llvm::Triple::hexagon)
+ TC = new toolchains::Hexagon_TC(*this, Target, Args);
+ else
+ TC = new toolchains::Linux(*this, Target, Args);
+ break;
+ case llvm::Triple::Solaris:
+ TC = new toolchains::Solaris(*this, Target, Args);
+ break;
+ case llvm::Triple::Win32:
+ switch (Target.getEnvironment()) {
+ default:
+ if (Target.isOSBinFormatELF())
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ else if (Target.isOSBinFormatMachO())
+ TC = new toolchains::MachO(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ break;
+ case llvm::Triple::GNU:
+ // FIXME: We need a MinGW toolchain. Use the default Generic_GCC
+ // toolchain for now as the default case would below otherwise.
+ if (Target.isOSBinFormatELF())
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ break;
+ case llvm::Triple::MSVC:
+ case llvm::Triple::UnknownEnvironment:
+ TC = new toolchains::Windows(*this, Target, Args);
+ break;
+ }
+ break;
+ default:
+ // TCE is an OSless target
+ if (Target.getArchName() == "tce") {
+ TC = new toolchains::TCEToolChain(*this, Target, Args);
+ break;
+ }
+ // If Hexagon is configured as an OSless target
+ if (Target.getArch() == llvm::Triple::hexagon) {
+ TC = new toolchains::Hexagon_TC(*this, Target, Args);
+ break;
+ }
+ if (Target.getArch() == llvm::Triple::xcore) {
+ TC = new toolchains::XCore(*this, Target, Args);
+ break;
+ }
+ if (Target.isOSBinFormatELF()) {
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ break;
+ }
+ if (Target.getObjectFormat() == llvm::Triple::MachO) {
+ TC = new toolchains::MachO(*this, Target, Args);
+ break;
+ }
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ break;
+ }
+ }
+ return *TC;
+}
+
+bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
+ // Check if user requested no clang, or clang doesn't understand this type (we
+ // only handle single inputs for now).
+ if (JA.size() != 1 ||
+ !types::isAcceptedByClang((*JA.begin())->getType()))
+ return false;
+
+ // Otherwise make sure this is an action clang understands.
+ if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
+ !isa<CompileJobAction>(JA))
+ return false;
+
+ return true;
+}
+
+/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
+/// grouped values as integers. Numbers which are not provided are set to 0.
+///
+/// \return True if the entire string was parsed (9.2), or all groups were
+/// parsed (10.3.5extrastuff).
+bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
+ unsigned &Minor, unsigned &Micro,
+ bool &HadExtra) {
+ HadExtra = false;
+
+ Major = Minor = Micro = 0;
+ if (*Str == '\0')
+ return true;
+
+ char *End;
+ Major = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (*End != '.')
+ return false;
+
+ Str = End+1;
+ Minor = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (*End != '.')
+ return false;
+
+ Str = End+1;
+ Micro = (unsigned) strtol(Str, &End, 10);
+ if (*Str != '\0' && *End == '\0')
+ return true;
+ if (Str == End)
+ return false;
+ 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);
+}
+
+bool clang::driver::isOptimizationLevelFast(const llvm::opt::ArgList &Args) {
+ return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
new file mode 100644
index 0000000..6ff1cba
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp
@@ -0,0 +1,44 @@
+//===--- DriverOptions.cpp - Driver Options Table -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.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) static const char *const NAME[] = VALUE;
+#include "clang/Driver/Options.inc"
+#undef PREFIX
+
+static const OptTable::Info InfoTable[] = {
+#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, ALIASARGS },
+#include "clang/Driver/Options.inc"
+#undef OPTION
+};
+
+namespace {
+
+class DriverOptTable : public OptTable {
+public:
+ DriverOptTable()
+ : OptTable(InfoTable, llvm::array_lengthof(InfoTable)) {}
+};
+
+}
+
+OptTable *clang::driver::createDriverOptTable() {
+ return new DriverOptTable();
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
new file mode 100644
index 0000000..4eedd22
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h
@@ -0,0 +1,89 @@
+//===--- InputInfo.h - Input Source & Type Information ----------*- 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_INPUTINFO_H_
+#define CLANG_LIB_DRIVER_INPUTINFO_H_
+
+#include "clang/Driver/Types.h"
+#include "llvm/Option/Arg.h"
+#include <cassert>
+#include <string>
+
+namespace clang {
+namespace driver {
+
+/// InputInfo - Wrapper for information about an input source.
+class InputInfo {
+ // FIXME: The distinction between filenames and inputarg here is
+ // gross; we should probably drop the idea of a "linker
+ // input". Doing so means tweaking pipelining to still create link
+ // steps when it sees linker inputs (but not treat them as
+ // arguments), and making sure that arguments get rendered
+ // correctly.
+ enum Class {
+ Nothing,
+ Filename,
+ InputArg,
+ Pipe
+ };
+
+ union {
+ const char *Filename;
+ const llvm::opt::Arg *InputArg;
+ } Data;
+ Class Kind;
+ types::ID Type;
+ const char *BaseInput;
+
+public:
+ InputInfo() {}
+ InputInfo(types::ID _Type, const char *_BaseInput)
+ : Kind(Nothing), Type(_Type), BaseInput(_BaseInput) {
+ }
+ InputInfo(const char *_Filename, types::ID _Type, const char *_BaseInput)
+ : Kind(Filename), Type(_Type), BaseInput(_BaseInput) {
+ Data.Filename = _Filename;
+ }
+ InputInfo(const llvm::opt::Arg *_InputArg, types::ID _Type,
+ const char *_BaseInput)
+ : Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
+ Data.InputArg = _InputArg;
+ }
+
+ bool isNothing() const { return Kind == Nothing; }
+ bool isFilename() const { return Kind == Filename; }
+ bool isInputArg() const { return Kind == InputArg; }
+ types::ID getType() const { return Type; }
+ const char *getBaseInput() const { return BaseInput; }
+
+ const char *getFilename() const {
+ assert(isFilename() && "Invalid accessor.");
+ return Data.Filename;
+ }
+ const llvm::opt::Arg &getInputArg() const {
+ assert(isInputArg() && "Invalid accessor.");
+ return *Data.InputArg;
+ }
+
+ /// getAsString - Return a string name for this input, for
+ /// debugging.
+ std::string getAsString() const {
+ if (isFilename())
+ return std::string("\"") + getFilename() + '"';
+ else if (isInputArg())
+ return "(input arg)";
+ else
+ return "(nothing)";
+ }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
new file mode 100644
index 0000000..42cc1bc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp
@@ -0,0 +1,189 @@
+//===--- Job.cpp - Command to Execute -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.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() {}
+
+Command::Command(const Action &_Source, const Tool &_Creator,
+ 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)
+ .Cases("-dwarf-debug-flags", "-ivfsoverlay", 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") ||
+ FlagRef.startswith("-fmodules-cache-path="))
+ 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(nullptr);
+
+ return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
+ 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;
+
+ const Driver &D = getCreator().getToolChain().getDriver();
+ D.Diag(diag::warn_drv_invoking_fallback) << Fallback->getExecutable();
+
+ int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
+ return SecondaryStatus;
+}
+
+JobList::JobList() : Job(JobListClass) {}
+
+JobList::~JobList() {
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ delete *it;
+}
+
+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 JobList::clear() {
+ DeleteContainerPointers(Jobs);
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
new file mode 100644
index 0000000..484ce16
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp
@@ -0,0 +1,334 @@
+//===--- Multilib.cpp - Multilib 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/Multilib.h"
+#include "Tools.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+using namespace clang::driver;
+using namespace clang;
+using namespace llvm::opt;
+using namespace llvm::sys;
+
+/// normalize Segment to "/foo/bar" or "".
+static void normalizePathSegment(std::string &Segment) {
+ StringRef seg = Segment;
+
+ // Prune trailing "/" or "./"
+ while (1) {
+ StringRef last = *--path::end(seg);
+ if (last != ".")
+ break;
+ seg = path::parent_path(seg);
+ }
+
+ if (seg.empty() || seg == "/") {
+ Segment = "";
+ return;
+ }
+
+ // Add leading '/'
+ if (seg.front() != '/') {
+ Segment = "/" + seg.str();
+ } else {
+ Segment = seg;
+ }
+}
+
+Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
+ StringRef IncludeSuffix)
+ : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix) {
+ normalizePathSegment(this->GCCSuffix);
+ normalizePathSegment(this->OSSuffix);
+ normalizePathSegment(this->IncludeSuffix);
+}
+
+Multilib &Multilib::gccSuffix(StringRef S) {
+ GCCSuffix = S;
+ normalizePathSegment(GCCSuffix);
+ return *this;
+}
+
+Multilib &Multilib::osSuffix(StringRef S) {
+ OSSuffix = S;
+ normalizePathSegment(OSSuffix);
+ return *this;
+}
+
+Multilib &Multilib::includeSuffix(StringRef S) {
+ IncludeSuffix = S;
+ normalizePathSegment(IncludeSuffix);
+ return *this;
+}
+
+void Multilib::print(raw_ostream &OS) const {
+ assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/'));
+ if (GCCSuffix.empty())
+ OS << ".";
+ else {
+ OS << StringRef(GCCSuffix).drop_front();
+ }
+ OS << ";";
+ for (StringRef Flag : Flags) {
+ if (Flag.front() == '+')
+ OS << "@" << Flag.substr(1);
+ }
+}
+
+bool Multilib::isValid() const {
+ llvm::StringMap<int> FlagSet;
+ for (unsigned I = 0, N = Flags.size(); I != N; ++I) {
+ StringRef Flag(Flags[I]);
+ llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));
+
+ assert(StringRef(Flag).front() == '+' || StringRef(Flag).front() == '-');
+
+ if (SI == FlagSet.end())
+ FlagSet[Flag.substr(1)] = I;
+ else if (Flags[I] != Flags[SI->getValue()])
+ return false;
+ }
+ return true;
+}
+
+bool Multilib::operator==(const Multilib &Other) const {
+ // Check whether the flags sets match
+ // allowing for the match to be order invariant
+ llvm::StringSet<> MyFlags;
+ for (const auto &Flag : Flags)
+ MyFlags.insert(Flag);
+
+ for (const auto &Flag : Other.Flags)
+ if (MyFlags.find(Flag) == MyFlags.end())
+ return false;
+
+ if (osSuffix() != Other.osSuffix())
+ return false;
+
+ if (gccSuffix() != Other.gccSuffix())
+ return false;
+
+ if (includeSuffix() != Other.includeSuffix())
+ return false;
+
+ return true;
+}
+
+raw_ostream &clang::driver::operator<<(raw_ostream &OS, const Multilib &M) {
+ M.print(OS);
+ return OS;
+}
+
+MultilibSet &MultilibSet::Maybe(const Multilib &M) {
+ Multilib Opposite;
+ // Negate any '+' flags
+ for (StringRef Flag : M.flags()) {
+ if (Flag.front() == '+')
+ Opposite.flags().push_back(("-" + Flag.substr(1)).str());
+ }
+ return Either(M, Opposite);
+}
+
+MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2) {
+ std::vector<Multilib> Ms;
+ Ms.push_back(M1);
+ Ms.push_back(M2);
+ return Either(Ms);
+}
+
+MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3) {
+ std::vector<Multilib> Ms;
+ Ms.push_back(M1);
+ Ms.push_back(M2);
+ Ms.push_back(M3);
+ return Either(Ms);
+}
+
+MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3, const Multilib &M4) {
+ std::vector<Multilib> Ms;
+ Ms.push_back(M1);
+ Ms.push_back(M2);
+ Ms.push_back(M3);
+ Ms.push_back(M4);
+ return Either(Ms);
+}
+
+MultilibSet &MultilibSet::Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3, const Multilib &M4,
+ const Multilib &M5) {
+ std::vector<Multilib> Ms;
+ Ms.push_back(M1);
+ Ms.push_back(M2);
+ Ms.push_back(M3);
+ Ms.push_back(M4);
+ Ms.push_back(M5);
+ return Either(Ms);
+}
+
+static Multilib compose(const Multilib &Base, const Multilib &New) {
+ SmallString<128> GCCSuffix;
+ llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());
+ SmallString<128> OSSuffix;
+ llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());
+ SmallString<128> IncludeSuffix;
+ llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),
+ New.includeSuffix());
+
+ Multilib Composed(GCCSuffix.str(), OSSuffix.str(), IncludeSuffix.str());
+
+ Multilib::flags_list &Flags = Composed.flags();
+
+ Flags.insert(Flags.end(), Base.flags().begin(), Base.flags().end());
+ Flags.insert(Flags.end(), New.flags().begin(), New.flags().end());
+
+ return Composed;
+}
+
+MultilibSet &
+MultilibSet::Either(const std::vector<Multilib> &MultilibSegments) {
+ multilib_list Composed;
+
+ if (Multilibs.empty())
+ Multilibs.insert(Multilibs.end(), MultilibSegments.begin(),
+ MultilibSegments.end());
+ else {
+ for (const Multilib &New : MultilibSegments) {
+ for (const Multilib &Base : *this) {
+ Multilib MO = compose(Base, New);
+ if (MO.isValid())
+ Composed.push_back(MO);
+ }
+ }
+
+ Multilibs = Composed;
+ }
+
+ return *this;
+}
+
+MultilibSet &MultilibSet::FilterOut(const MultilibSet::FilterCallback &F) {
+ filterInPlace(F, Multilibs);
+ return *this;
+}
+
+MultilibSet &MultilibSet::FilterOut(std::string Regex) {
+ class REFilter : public MultilibSet::FilterCallback {
+ mutable llvm::Regex R;
+
+ public:
+ REFilter(std::string Regex) : R(Regex) {}
+ bool operator()(const Multilib &M) const override {
+ std::string Error;
+ if (!R.isValid(Error)) {
+ llvm::errs() << Error;
+ assert(false);
+ return false;
+ }
+ return R.match(M.gccSuffix());
+ }
+ };
+
+ REFilter REF(Regex);
+ filterInPlace(REF, Multilibs);
+ return *this;
+}
+
+void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
+
+void MultilibSet::combineWith(const MultilibSet &Other) {
+ Multilibs.insert(Multilibs.end(), Other.begin(), Other.end());
+}
+
+bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
+ class FilterFlagsMismatch : public MultilibSet::FilterCallback {
+ llvm::StringMap<bool> FlagSet;
+
+ public:
+ FilterFlagsMismatch(const std::vector<std::string> &Flags) {
+ // Stuff all of the flags into the FlagSet such that a true mappend
+ // indicates the flag was enabled, and a false mappend indicates the
+ // flag was disabled
+ for (StringRef Flag : Flags)
+ FlagSet[Flag.substr(1)] = isFlagEnabled(Flag);
+ }
+ bool operator()(const Multilib &M) const override {
+ for (StringRef Flag : M.flags()) {
+ llvm::StringMap<bool>::const_iterator SI = FlagSet.find(Flag.substr(1));
+ if (SI != FlagSet.end())
+ if (SI->getValue() != isFlagEnabled(Flag))
+ return true;
+ }
+ return false;
+ }
+ private:
+ bool isFlagEnabled(StringRef Flag) const {
+ char Indicator = Flag.front();
+ assert(Indicator == '+' || Indicator == '-');
+ return Indicator == '+';
+ }
+ };
+
+ FilterFlagsMismatch FlagsMismatch(Flags);
+
+ multilib_list Filtered = filterCopy(FlagsMismatch, Multilibs);
+
+ if (Filtered.size() == 0) {
+ return false;
+ } else if (Filtered.size() == 1) {
+ M = Filtered[0];
+ return true;
+ }
+
+ // TODO: pick the "best" multlib when more than one is suitable
+ assert(false);
+
+ return false;
+}
+
+void MultilibSet::print(raw_ostream &OS) const {
+ for (const Multilib &M : *this)
+ OS << M << "\n";
+}
+
+MultilibSet::multilib_list
+MultilibSet::filterCopy(const MultilibSet::FilterCallback &F,
+ const multilib_list &Ms) {
+ multilib_list Copy(Ms);
+ filterInPlace(F, Copy);
+ return Copy;
+}
+
+void MultilibSet::filterInPlace(const MultilibSet::FilterCallback &F,
+ multilib_list &Ms) {
+ Ms.erase(std::remove_if(Ms.begin(), Ms.end(),
+ [&F](const Multilib &M) { return F(M); }),
+ Ms.end());
+}
+
+raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
+ MS.print(OS);
+ return OS;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp
new file mode 100644
index 0000000..155e53b
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp
@@ -0,0 +1,26 @@
+//===--- Phases.cpp - Transformations on Driver Types ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Phases.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+
+using namespace clang::driver;
+
+const char *phases::getPhaseName(ID Id) {
+ switch (Id) {
+ case Preprocess: return "preprocessor";
+ case Precompile: return "precompiler";
+ case Compile: return "compiler";
+ case Assemble: return "assembler";
+ case Link: return "linker";
+ }
+
+ llvm_unreachable("Invalid phase id.");
+}
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..b64f027
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp
@@ -0,0 +1,338 @@
+//===--- 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/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include <memory>
+
+using namespace clang::driver;
+using namespace llvm::opt;
+
+void SanitizerArgs::clear() {
+ Kind = 0;
+ BlacklistFile = "";
+ MsanTrackOrigins = 0;
+ AsanZeroBaseShadow = false;
+ UbsanTrapOnError = false;
+ AsanSharedRuntime = 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.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, false);
+
+ // Warn about undefined sanitizer options that require runtime support.
+ if (UbsanTrapOnError && notAllowedWithTrap()) {
+ 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: Currently -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?
+
+ // 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;
+ std::unique_ptr<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[=level] options.
+ if (NeedsMsan) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,
+ options::OPT_fsanitize_memory_track_origins,
+ options::OPT_fno_sanitize_memory_track_origins)) {
+ if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
+ MsanTrackOrigins = 1;
+ } else if (A->getOption().matches(
+ options::OPT_fno_sanitize_memory_track_origins)) {
+ MsanTrackOrigins = 0;
+ } else {
+ StringRef S = A->getValue();
+ if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
+ MsanTrackOrigins > 2) {
+ D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
+ }
+ }
+ }
+
+ if (NeedsAsan) {
+ AsanSharedRuntime =
+ Args.hasArg(options::OPT_shared_libasan) ||
+ (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ AsanZeroBaseShadow =
+ (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+ }
+}
+
+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=" +
+ llvm::utostr(MsanTrackOrigins)));
+
+ // 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());
+ 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;
+ 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;
+ }
+ 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 = nullptr;
+ 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/Tool.cpp b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp
new file mode 100644
index 0000000..b93864f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp
@@ -0,0 +1,21 @@
+//===--- Tool.cpp - Compilation 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/Tool.h"
+
+using namespace clang::driver;
+
+Tool::Tool(const char *_Name, const char *_ShortName,
+ const ToolChain &TC) : Name(_Name), ShortName(_ShortName),
+ TheToolChain(TC)
+{
+}
+
+Tool::~Tool() {
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
new file mode 100644
index 0000000..4f90d08
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -0,0 +1,420 @@
+//===--- ToolChain.cpp - Collections of tools for one platform ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/SmallString.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)
+ : D(D), Triple(T), Args(A) {
+}
+
+ToolChain::~ToolChain() {
+}
+
+const Driver &ToolChain::getDriver() const {
+ return D;
+}
+
+bool ToolChain::useIntegratedAs() const {
+ return Args.hasFlag(options::OPT_fintegrated_as,
+ options::OPT_fno_integrated_as,
+ 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
+ // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
+ // only interesting special case is powerpc.
+ switch (Triple.getArch()) {
+ case llvm::Triple::ppc:
+ return "ppc";
+ case llvm::Triple::ppc64:
+ return "ppc64";
+ case llvm::Triple::ppc64le:
+ return "ppc64le";
+ default:
+ return Triple.getArchName();
+ }
+}
+
+bool ToolChain::IsUnwindTablesDefault() const {
+ return false;
+}
+
+Tool *ToolChain::getClang() const {
+ if (!Clang)
+ Clang.reset(new tools::Clang(*this));
+ return Clang.get();
+}
+
+Tool *ToolChain::buildAssembler() const {
+ return new tools::ClangAs(*this);
+}
+
+Tool *ToolChain::buildLinker() const {
+ llvm_unreachable("Linking is not supported by this toolchain");
+}
+
+Tool *ToolChain::getAssemble() const {
+ if (!Assemble)
+ Assemble.reset(buildAssembler());
+ return Assemble.get();
+}
+
+Tool *ToolChain::getClangAs() const {
+ if (!Assemble)
+ Assemble.reset(new tools::ClangAs(*this));
+ return Assemble.get();
+}
+
+Tool *ToolChain::getLink() const {
+ if (!Link)
+ Link.reset(buildLinker());
+ return Link.get();
+}
+
+Tool *ToolChain::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::AssembleJobClass:
+ return getAssemble();
+
+ case Action::LinkJobClass:
+ return getLink();
+
+ case Action::InputClass:
+ case Action::BindArchClass:
+ case Action::LipoJobClass:
+ case Action::DsymutilJobClass:
+ case Action::VerifyDebugInfoJobClass:
+ llvm_unreachable("Invalid tool kind.");
+
+ case Action::CompileJobClass:
+ case Action::PrecompileJobClass:
+ case Action::PreprocessJobClass:
+ case Action::AnalyzeJobClass:
+ case Action::MigrateJobClass:
+ case Action::VerifyPCHJobClass:
+ return getClang();
+ }
+
+ llvm_unreachable("Invalid tool kind.");
+}
+
+Tool *ToolChain::SelectTool(const JobAction &JA) const {
+ if (getDriver().ShouldUseClangCompiler(JA))
+ return getClang();
+ Action::ActionClass AC = JA.getKind();
+ if (AC == Action::AssembleJobClass && useIntegratedAs())
+ return getClangAs();
+ return getTool(AC);
+}
+
+std::string ToolChain::GetFilePath(const char *Name) const {
+ return D.GetFilePath(Name, *this);
+
+}
+
+std::string ToolChain::GetProgramPath(const char *Name) const {
+ return D.GetProgramPath(Name, *this);
+}
+
+std::string ToolChain::GetLinkerPath() const {
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ StringRef Suffix = A->getValue();
+
+ // If we're passed -fuse-ld= with no argument, or with the argument ld,
+ // then use whatever the default system linker is.
+ if (Suffix.empty() || Suffix == "ld")
+ return GetProgramPath("ld");
+
+ llvm::SmallString<8> LinkerName("ld.");
+ LinkerName.append(Suffix);
+
+ std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
+ if (llvm::sys::fs::exists(LinkerPath))
+ return LinkerPath;
+
+ getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
+ return "";
+ }
+
+ return GetProgramPath("ld");
+}
+
+
+types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+}
+
+bool ToolChain::HasNativeLLVMSupport() const {
+ return false;
+}
+
+bool ToolChain::isCrossCompiling() const {
+ llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
+ switch (HostTriple.getArch()) {
+ // The A32/T32/T16 instruction sets are not separate architectures in this
+ // context.
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
+ getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
+ default:
+ return HostTriple.getArch() != getArch();
+ }
+}
+
+ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
+ return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
+ VersionTuple());
+}
+
+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.isOSBinFormatMachO())
+ 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::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ // FIXME: Factor into subclasses.
+ llvm::Triple Triple = getTriple();
+ bool IsBigEndian = getTriple().getArch() == llvm::Triple::armeb ||
+ getTriple().getArch() == llvm::Triple::thumbeb;
+
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian))
+ IsBigEndian = false;
+ else
+ IsBigEndian = true;
+ }
+
+ // Thumb2 is the default for V7 on Darwin.
+ //
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ StringRef Suffix = Triple.isOSBinFormatMachO()
+ ? tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMCPUForMArch(Args, Triple))
+ : tools::arm::getLLVMArchSuffixForARM(tools::arm::getARMTargetCPU(Args, Triple));
+ bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") ||
+ Suffix.startswith("v7em") ||
+ (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO());
+ // FIXME: this is invalid for WindowsCE
+ if (getTriple().isOSWindows())
+ ThumbDefault = true;
+ std::string ArchName;
+ if (IsBigEndian)
+ ArchName = "armeb";
+ else
+ ArchName = "arm";
+
+ // Assembly files should start in ARM mode.
+ if (InputType != types::TY_PP_Asm &&
+ Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+ {
+ if (IsBigEndian)
+ ArchName = "thumbeb";
+ else
+ ArchName = "thumb";
+ }
+ Triple.setArchName(ArchName + Suffix.str());
+
+ return Triple.getTriple();
+ }
+ }
+}
+
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ return ComputeLLVMTriple(Args, InputType);
+}
+
+void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // Each toolchain should provide the appropriate include flags.
+}
+
+void ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+}
+
+void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
+
+ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
+ const ArgList &Args) const
+{
+ if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "compiler-rt")
+ return ToolChain::RLT_CompilerRT;
+ if (Value == "libgcc")
+ return ToolChain::RLT_Libgcc;
+ getDriver().Diag(diag::err_drv_invalid_rtlib_name)
+ << A->getAsString(Args);
+ }
+
+ return GetDefaultRuntimeLibType();
+}
+
+ToolChain::CXXStdlibType ToolChain::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;
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libstdcxx;
+}
+
+/// \brief Utility function to add a system include directory to CC1 arguments.
+/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ const Twine &Path) {
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
+/// \brief Utility function to add a system include directory with extern "C"
+/// semantics to CC1 arguments.
+///
+/// Note that this should be used rarely, and only for directories that
+/// historically and for legacy reasons are treated as having implicit extern
+/// "C" semantics. These semantics are *ignored* by and large today, but its
+/// important to preserve the preprocessor changes resulting from the
+/// classification.
+/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ const Twine &Path) {
+ CC1Args.push_back("-internal-externc-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
+void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ const Twine &Path) {
+ if (llvm::sys::fs::exists(Path))
+ addExternCSystemInclude(DriverArgs, CC1Args, Path);
+}
+
+/// \brief Utility function to add a list of system include directories to CC1.
+/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ ArrayRef<StringRef> Paths) {
+ for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end();
+ I != E; ++I) {
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(*I));
+ }
+}
+
+void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // Header search paths should be handled by each of the subclasses.
+ // Historically, they have not been, and instead have been handled inside of
+ // the CC1-layer frontend. As the logic is hoisted out, this generic function
+ // will slowly stop being called.
+ //
+ // While it is being called, replicate a bit of a hack to propagate the
+ // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
+ // header search paths with it. Once all systems are overriding this
+ // function, the CC1 flag and this line can be removed.
+ DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
+}
+
+void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+}
+
+void ToolChain::AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-lcc_kext");
+}
+
+bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
+ // (to keep the linker options consistent with gcc and clang itself).
+ if (!isOptimizationLevelFast(Args)) {
+ // Check if -ffast-math or -funsafe-math.
+ Arg *A =
+ Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations);
+
+ if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
+ A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
+ return false;
+ }
+ // If crtfastmath.o exists add it to the arguments.
+ std::string Path = GetFilePath("crtfastmath.o");
+ if (Path == "crtfastmath.o") // Not found.
+ return false;
+
+ CmdArgs.push_back(Args.MakeArgString(Path));
+ return true;
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
new file mode 100644
index 0000000..b46f69d
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -0,0 +1,3603 @@
+//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ToolChains.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.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/Program.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib> // ::getenv
+#include <system_error>
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+MachO::MachO(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ // We expect 'as', 'ld', etc. to be adjacent to our install dir.
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+/// Darwin - Darwin tool chain for i386 and x86_64.
+Darwin::Darwin(const Driver & D, const llvm::Triple & Triple,
+ const ArgList & Args)
+ : MachO(D, Triple, Args), TargetInitialized(false) {
+ // Compute the initial Darwin version from the triple
+ unsigned Major, Minor, Micro;
+ if (!Triple.getMacOSXVersion(Major, Minor, Micro))
+ getDriver().Diag(diag::err_drv_invalid_darwin_version) <<
+ Triple.getOSName();
+ llvm::raw_string_ostream(MacosxVersionMin)
+ << Major << '.' << Minor << '.' << Micro;
+
+ // FIXME: DarwinVersion is only used to find GCC's libexec directory.
+ // It should be removed when we stop supporting that.
+ DarwinVersion[0] = Minor + 4;
+ DarwinVersion[1] = Micro;
+ DarwinVersion[2] = 0;
+
+ // Compute the initial iOS version from the triple
+ Triple.getiOSVersion(Major, Minor, Micro);
+ llvm::raw_string_ostream(iOSVersionMin)
+ << Major << '.' << Minor << '.' << Micro;
+}
+
+types::ID MachO::LookupTypeForExtension(const char *Ext) const {
+ types::ID Ty = types::lookupTypeForExtension(Ext);
+
+ // Darwin always preprocesses assembly files (unless -x is used explicitly).
+ if (Ty == types::TY_PP_Asm)
+ return types::TY_Asm;
+
+ return Ty;
+}
+
+bool MachO::HasNativeLLVMSupport() const {
+ return true;
+}
+
+/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
+ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
+ if (isTargetIOSBased())
+ return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
+ if (isNonFragile)
+ return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
+ return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
+}
+
+/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
+bool Darwin::hasBlocksRuntime() const {
+ if (isTargetIOSBased())
+ return !isIPhoneOSVersionLT(3, 2);
+ else {
+ assert(isTargetMacOS() && "unexpected darwin target");
+ return !isMacosxVersionLT(10, 6);
+ }
+}
+
+static const char *GetArmArchForMArch(StringRef Value) {
+ return llvm::StringSwitch<const char*>(Value)
+ .Case("armv6k", "armv6")
+ .Case("armv6m", "armv6m")
+ .Case("armv5tej", "armv5")
+ .Case("xscale", "xscale")
+ .Case("armv4t", "armv4t")
+ .Case("armv7", "armv7")
+ .Cases("armv7a", "armv7-a", "armv7")
+ .Cases("armv7r", "armv7-r", "armv7")
+ .Cases("armv7em", "armv7e-m", "armv7em")
+ .Cases("armv7k", "armv7-k", "armv7k")
+ .Cases("armv7m", "armv7-m", "armv7m")
+ .Cases("armv7s", "armv7-s", "armv7s")
+ .Default(nullptr);
+}
+
+static const char *GetArmArchForMCpu(StringRef Value) {
+ return llvm::StringSwitch<const char *>(Value)
+ .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5")
+ .Cases("arm10e", "arm10tdmi", "armv5")
+ .Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5")
+ .Case("xscale", "xscale")
+ .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
+ .Case("cortex-m0", "armv6m")
+ .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "armv7")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "armv7")
+ .Cases("cortex-r4", "cortex-r5", "armv7r")
+ .Case("cortex-m3", "armv7m")
+ .Case("cortex-m4", "armv7em")
+ .Case("swift", "armv7s")
+ .Default(nullptr);
+}
+
+static bool isSoftFloatABI(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ);
+ if (!A)
+ return false;
+
+ return A->getOption().matches(options::OPT_msoft_float) ||
+ (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
+ A->getValue() == StringRef("soft"));
+}
+
+StringRef MachO::getMachOArchName(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getArchName();
+
+ case llvm::Triple::thumb:
+ case llvm::Triple::arm: {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ if (const char *Arch = GetArmArchForMArch(A->getValue()))
+ return Arch;
+
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ if (const char *Arch = GetArmArchForMCpu(A->getValue()))
+ return Arch;
+
+ return "arm";
+ }
+ }
+}
+
+Darwin::~Darwin() {
+}
+
+MachO::~MachO() {
+}
+
+
+std::string MachO::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
+
+ return Triple.getTriple();
+}
+
+std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
+
+ // If the target isn't initialized (e.g., an unknown Darwin platform, return
+ // the default triple).
+ if (!isTargetInitialized())
+ return Triple.getTriple();
+
+ SmallString<16> Str;
+ Str += isTargetIOSBased() ? "ios" : "macosx";
+ Str += getTargetVersion().getAsString();
+ Triple.setOSName(Str);
+
+ return Triple.getTriple();
+}
+
+void Generic_ELF::anchor() {}
+
+Tool *MachO::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::LipoJobClass:
+ if (!Lipo)
+ Lipo.reset(new tools::darwin::Lipo(*this));
+ return Lipo.get();
+ case Action::DsymutilJobClass:
+ if (!Dsymutil)
+ Dsymutil.reset(new tools::darwin::Dsymutil(*this));
+ return Dsymutil.get();
+ case Action::VerifyDebugInfoJobClass:
+ if (!VerifyDebug)
+ VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
+ return VerifyDebug.get();
+ default:
+ return ToolChain::getTool(AC);
+ }
+}
+
+Tool *MachO::buildLinker() const {
+ return new tools::darwin::Link(*this);
+}
+
+Tool *MachO::buildAssembler() const {
+ return new tools::darwin::Assemble(*this);
+}
+
+DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : Darwin(D, Triple, Args) {
+}
+
+void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
+ // For iOS, 64-bit, promote certain warnings to errors.
+ if (!isTargetMacOS() && getTriple().isArch64Bit()) {
+ // Always enable -Wdeprecated-objc-isa-usage and promote it
+ // to an error.
+ CC1Args.push_back("-Wdeprecated-objc-isa-usage");
+ CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
+
+ // Also error about implicit function declarations, as that
+ // can impact calling conventions.
+ CC1Args.push_back("-Werror=implicit-function-declaration");
+ }
+}
+
+/// \brief Determine whether Objective-C automated reference counting is
+/// enabled.
+static bool isObjCAutoRefCount(const ArgList &Args) {
+ return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
+}
+
+void DarwinClang::AddLinkARCArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Avoid linking compatibility stubs on i386 mac.
+ if (isTargetMacOS() && getArch() == llvm::Triple::x86)
+ return;
+
+ ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
+
+ if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
+ runtime.hasSubscripting())
+ return;
+
+ CmdArgs.push_back("-force_load");
+ 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())
+ P += "iphonesimulator";
+ else if (isTargetIPhoneOS())
+ P += "iphoneos";
+ else
+ P += "macosx";
+ P += ".a";
+
+ CmdArgs.push_back(Args.MakeArgString(P));
+}
+
+void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
+ StringRef DarwinStaticLib, bool AlwaysLink,
+ bool IsEmbedded) const {
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "lib", IsEmbedded ? "macho_embedded" : "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).
+ if (AlwaysLink || llvm::sys::fs::exists(P.str()))
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+}
+
+void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Darwin only supports the compiler-rt based runtime libraries.
+ switch (GetRuntimeLibType(Args)) {
+ case ToolChain::RLT_CompilerRT:
+ break;
+ default:
+ getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
+ << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
+ return;
+ }
+
+ // Darwin doesn't support real static executables, don't link any runtime
+ // libraries with -static.
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_fapple_kext) ||
+ Args.hasArg(options::OPT_mkernel))
+ return;
+
+ // Reject -static-libgcc for now, we can deal with this when and if someone
+ // cares. This is useful in situations where someone wants to statically link
+ // something like libstdc++, and needs its runtime support routines.
+ if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
+ getDriver().Diag(diag::err_drv_unsupported_opt)
+ << A->getAsString(Args);
+ return;
+ }
+
+ // If we are building profile support, link that library in.
+ if (Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)) {
+ // Select the appropriate runtime library for the target.
+ if (isTargetIOSBased())
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
+ else
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a");
+ }
+
+ const SanitizerArgs &Sanitize = getSanitizerArgs();
+
+ // Add Ubsan runtime library, if required.
+ if (Sanitize.needsUbsanRt()) {
+ // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
+ if (isTargetIOSBased()) {
+ getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
+ << "-fsanitize=undefined";
+ } else {
+ assert(isTargetMacOS() && "unexpected non OS X target");
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true);
+
+ // The Ubsan runtime library requires C++.
+ AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
+ }
+
+ // 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()) {
+ getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
+ << "-fsanitize=address";
+ } else {
+ 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);
+ }
+ }
+ }
+ }
+
+ // Otherwise link libSystem, then the dynamic runtime library, and finally any
+ // target specific static runtime library.
+ CmdArgs.push_back("-lSystem");
+
+ // Select the dynamic runtime library and the target specific static library.
+ if (isTargetIOSBased()) {
+ // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
+ // it never went into the SDK.
+ // Linking against libgcc_s.1 isn't needed for iOS 5.0+
+ if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
+ (getTriple().getArch() != llvm::Triple::arm64 &&
+ getTriple().getArch() != llvm::Triple::aarch64))
+ CmdArgs.push_back("-lgcc_s.1");
+
+ // We currently always need a static runtime library for iOS.
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a");
+ } else {
+ assert(isTargetMacOS() && "unexpected non MacOS platform");
+ // The dynamic runtime library was merged with libSystem for 10.6 and
+ // beyond; only 10.4 and 10.5 need an additional runtime library.
+ if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lgcc_s.10.4");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lgcc_s.10.5");
+
+ // For OS X, we thought we would only need a static runtime library when
+ // targeting 10.4, to provide versions of the static functions which were
+ // omitted from 10.4.dylib.
+ //
+ // Unfortunately, that turned out to not be true, because Darwin system
+ // headers can still use eprintf on i386, and it is not exported from
+ // libSystem. Therefore, we still must provide a runtime library just for
+ // the tiny tiny handful of projects that *might* use that symbol.
+ if (isMacosxVersionLT(10, 5)) {
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a");
+ } else {
+ if (getTriple().getArch() == llvm::Triple::x86)
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.eprintf.a");
+ AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a");
+ }
+ }
+}
+
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
+ const OptTable &Opts = getDriver().getOpts();
+
+ // Support allowing the SDKROOT environment variable used by xcrun and other
+ // Xcode tools to define the default sysroot, by making it the default for
+ // isysroot.
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ // Warn if the path does not exist.
+ if (!llvm::sys::fs::exists(A->getValue()))
+ getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
+ } else {
+ if (char *env = ::getenv("SDKROOT")) {
+ // We only use this value as the default if it is an absolute path,
+ // exists, and it is not the root path.
+ if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) &&
+ StringRef(env) != "/") {
+ Args.append(Args.MakeSeparateArg(
+ nullptr, Opts.getOption(options::OPT_isysroot), env));
+ }
+ }
+ }
+
+ Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
+ Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
+ Arg *iOSSimVersion = Args.getLastArg(
+ options::OPT_mios_simulator_version_min_EQ);
+
+ if (OSXVersion && (iOSVersion || iOSSimVersion)) {
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << OSXVersion->getAsString(Args)
+ << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args);
+ iOSVersion = iOSSimVersion = nullptr;
+ } else if (iOSVersion && iOSSimVersion) {
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << iOSVersion->getAsString(Args)
+ << iOSSimVersion->getAsString(Args);
+ iOSSimVersion = nullptr;
+ } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) {
+ // If no deployment target was specified on the command line, check for
+ // environment defines.
+ StringRef OSXTarget;
+ StringRef iOSTarget;
+ StringRef iOSSimTarget;
+ if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
+ OSXTarget = env;
+ if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
+ iOSTarget = env;
+ if (char *env = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET"))
+ iOSSimTarget = env;
+
+ // If no '-miphoneos-version-min' specified on the command line and
+ // IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default
+ // based on -isysroot.
+ if (iOSTarget.empty()) {
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ StringRef first, second;
+ StringRef isysroot = A->getValue();
+ std::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS"));
+ if (second != "")
+ iOSTarget = second.substr(0,3);
+ }
+ }
+
+ // If no OSX or iOS target has been specified and we're compiling for armv7,
+ // go ahead as assume we're targeting iOS.
+ StringRef MachOArchName = getMachOArchName(Args);
+ if (OSXTarget.empty() && iOSTarget.empty() &&
+ (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+ MachOArchName == "arm64"))
+ iOSTarget = iOSVersionMin;
+
+ // Handle conflicting deployment targets
+ //
+ // FIXME: Don't hardcode default here.
+
+ // Do not allow conflicts with the iOS simulator target.
+ if (!iOSSimTarget.empty() && (!OSXTarget.empty() || !iOSTarget.empty())) {
+ getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
+ << "IOS_SIMULATOR_DEPLOYMENT_TARGET"
+ << (!OSXTarget.empty() ? "MACOSX_DEPLOYMENT_TARGET" :
+ "IPHONEOS_DEPLOYMENT_TARGET");
+ }
+
+ // Allow conflicts among OSX and iOS for historical reasons, but choose the
+ // default platform.
+ if (!OSXTarget.empty() && !iOSTarget.empty()) {
+ if (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::thumb)
+ OSXTarget = "";
+ else
+ iOSTarget = "";
+ }
+
+ if (!OSXTarget.empty()) {
+ const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ OSXVersion = Args.MakeJoinedArg(nullptr, O, OSXTarget);
+ Args.append(OSXVersion);
+ } else if (!iOSTarget.empty()) {
+ const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
+ iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
+ Args.append(iOSVersion);
+ } else if (!iOSSimTarget.empty()) {
+ const Option O = Opts.getOption(
+ options::OPT_mios_simulator_version_min_EQ);
+ iOSSimVersion = Args.MakeJoinedArg(nullptr, O, iOSSimTarget);
+ Args.append(iOSSimVersion);
+ } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+ MachOArchName != "armv7em") {
+ // Otherwise, assume we are targeting OS X.
+ const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
+ OSXVersion = Args.MakeJoinedArg(nullptr, O, MacosxVersionMin);
+ Args.append(OSXVersion);
+ }
+ }
+
+ DarwinPlatformKind Platform;
+ if (OSXVersion)
+ Platform = MacOS;
+ else if (iOSVersion)
+ Platform = IPhoneOS;
+ else if (iOSSimVersion)
+ Platform = IPhoneOSSimulator;
+ else
+ llvm_unreachable("Unable to infer Darwin variant");
+
+ // Reject invalid architecture combinations.
+ if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 &&
+ getTriple().getArch() != llvm::Triple::x86_64)) {
+ getDriver().Diag(diag::err_drv_invalid_arch_for_deployment_target)
+ << getTriple().getArchName() << iOSSimVersion->getAsString(Args);
+ }
+
+ // Set the tool chain target information.
+ unsigned Major, Minor, Micro;
+ bool HadExtra;
+ if (Platform == MacOS) {
+ assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!");
+ if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major != 10 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << OSXVersion->getAsString(Args);
+ } else if (Platform == IPhoneOS || Platform == IPhoneOSSimulator) {
+ const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion;
+ assert(Version && "Unknown target platform!");
+ if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor,
+ Micro, HadExtra) || HadExtra ||
+ Major >= 10 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << Version->getAsString(Args);
+ } else
+ llvm_unreachable("unknown kind of Darwin platform");
+
+ // In GCC, the simulator historically was treated as being OS X in some
+ // contexts, like determining the link logic, despite generally being called
+ // with an iOS deployment target. For compatibility, we detect the
+ // simulator as iOS + x86, and treat it differently in a few contexts.
+ if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64))
+ Platform = IPhoneOSSimulator;
+
+ setTarget(Platform, Major, Minor, Micro);
+}
+
+void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx: {
+ // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
+ // it was previously found in the gcc lib dir. However, for all the Darwin
+ // platforms we care about it was -lstdc++.6, so we search for that
+ // explicitly if we can't see an obvious -lstdc++ candidate.
+
+ // Check in the sysroot first.
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ 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;
+ }
+ }
+ }
+
+ // 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") &&
+ llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib")) {
+ CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
+ return;
+ }
+
+ // Otherwise, let the linker search.
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+ }
+}
+
+void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+
+ // For Darwin platforms, use the compiler-rt-based support library
+ // instead of the gcc-provided one (which is also incidentally
+ // only present in the gcc lib dir, which makes it hard to find).
+
+ 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() ||
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ !isIPhoneOSVersionLT(6, 0)) {
+ llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
+ } else {
+ 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.
+ if (llvm::sys::fs::exists(P.str()))
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+}
+
+DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // FIXME: We really want to get out of the tool chain level argument
+ // translation business, as it makes the driver functionality much
+ // more opaque. For now, we follow gcc closely solely for the
+ // purpose of easily achieving feature parity & testability. Once we
+ // have something that works, we should reevaluate each translation
+ // and try to push it down into tool specific logic.
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(options::OPT_Xarch__)) {
+ // Skip this argument unless the architecture matches either the toolchain
+ // triple arch, or the arch being bound.
+ llvm::Triple::ArchType XarchArch =
+ tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
+ if (!(XarchArch == getArch() ||
+ (BoundArch && XarchArch ==
+ tools::darwin::getArchTypeForMachOArchName(BoundArch))))
+ continue;
+
+ Arg *OriginalArg = A;
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
+ unsigned Prev = Index;
+ std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
+
+ // If the argument parsing failed or more than one argument was
+ // consumed, the -Xarch_ argument's parameter tried to consume
+ // extra arguments. Emit an error and ignore.
+ //
+ // We also want to disallow any options which would alter the
+ // driver behavior; that isn't going to work in our model. We
+ // use isDriverOption() as an approximation, although things
+ // like -O4 are going to slip through.
+ if (!XarchArg || Index > Prev + 1) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
+ << A->getAsString(Args);
+ continue;
+ } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
+ << A->getAsString(Args);
+ continue;
+ }
+
+ XarchArg->setBaseArg(A);
+
+ A = XarchArg.release();
+ DAL->AddSynthesizedArg(A);
+
+ // Linker input arguments require custom handling. The problem is that we
+ // have already constructed the phase actions, so we can not treat them as
+ // "input arguments".
+ if (A->getOption().hasFlag(options::LinkerInput)) {
+ // Convert the argument into individual Zlinker_input_args.
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ DAL->AddSeparateArg(OriginalArg,
+ Opts.getOption(options::OPT_Zlinker_input),
+ A->getValue(i));
+
+ }
+ continue;
+ }
+ }
+
+ // Sob. These is strictly gcc compatible for the time being. Apple
+ // gcc translates options twice, which means that self-expanding
+ // options add duplicates.
+ switch ((options::ID) A->getOption().getID()) {
+ default:
+ DAL->append(A);
+ break;
+
+ case options::OPT_mkernel:
+ case options::OPT_fapple_kext:
+ DAL->append(A);
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
+ break;
+
+ case options::OPT_dependency_file:
+ DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF),
+ A->getValue());
+ break;
+
+ case options::OPT_gfull:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
+ break;
+
+ case options::OPT_gused:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
+ break;
+
+ case options::OPT_shared:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
+ break;
+
+ case options::OPT_fconstant_cfstrings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
+ break;
+
+ case options::OPT_fno_constant_cfstrings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
+ break;
+
+ case options::OPT_Wnonportable_cfstrings:
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
+ break;
+
+ case options::OPT_Wno_nonportable_cfstrings:
+ DAL->AddFlagArg(A,
+ Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
+ break;
+
+ case options::OPT_fpascal_strings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
+ break;
+
+ case options::OPT_fno_pascal_strings:
+ DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
+ break;
+ }
+ }
+
+ if (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64)
+ if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mtune_EQ),
+ "core2");
+
+ // Add the arch options based on the particular spelling of -arch, to match
+ // how the driver driver works.
+ if (BoundArch) {
+ StringRef Name = BoundArch;
+ const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
+ const Option MArch = Opts.getOption(options::OPT_march_EQ);
+
+ // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
+ // which defines the list of which architectures we accept.
+ if (Name == "ppc")
+ ;
+ else if (Name == "ppc601")
+ DAL->AddJoinedArg(nullptr, MCpu, "601");
+ else if (Name == "ppc603")
+ DAL->AddJoinedArg(nullptr, MCpu, "603");
+ else if (Name == "ppc604")
+ DAL->AddJoinedArg(nullptr, MCpu, "604");
+ else if (Name == "ppc604e")
+ DAL->AddJoinedArg(nullptr, MCpu, "604e");
+ else if (Name == "ppc750")
+ DAL->AddJoinedArg(nullptr, MCpu, "750");
+ else if (Name == "ppc7400")
+ DAL->AddJoinedArg(nullptr, MCpu, "7400");
+ else if (Name == "ppc7450")
+ DAL->AddJoinedArg(nullptr, MCpu, "7450");
+ else if (Name == "ppc970")
+ DAL->AddJoinedArg(nullptr, MCpu, "970");
+
+ else if (Name == "ppc64" || Name == "ppc64le")
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
+
+ else if (Name == "i386")
+ ;
+ else if (Name == "i486")
+ DAL->AddJoinedArg(nullptr, MArch, "i486");
+ else if (Name == "i586")
+ DAL->AddJoinedArg(nullptr, MArch, "i586");
+ else if (Name == "i686")
+ DAL->AddJoinedArg(nullptr, MArch, "i686");
+ else if (Name == "pentium")
+ DAL->AddJoinedArg(nullptr, MArch, "pentium");
+ else if (Name == "pentium2")
+ DAL->AddJoinedArg(nullptr, MArch, "pentium2");
+ else if (Name == "pentpro")
+ DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
+ else if (Name == "pentIIm3")
+ DAL->AddJoinedArg(nullptr, MArch, "pentium2");
+
+ else if (Name == "x86_64")
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
+ else if (Name == "x86_64h") {
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
+ DAL->AddJoinedArg(nullptr, MArch, "x86_64h");
+ }
+
+ else if (Name == "arm")
+ DAL->AddJoinedArg(nullptr, MArch, "armv4t");
+ else if (Name == "armv4t")
+ DAL->AddJoinedArg(nullptr, MArch, "armv4t");
+ else if (Name == "armv5")
+ DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
+ else if (Name == "xscale")
+ DAL->AddJoinedArg(nullptr, MArch, "xscale");
+ else if (Name == "armv6")
+ DAL->AddJoinedArg(nullptr, MArch, "armv6k");
+ else if (Name == "armv6m")
+ DAL->AddJoinedArg(nullptr, MArch, "armv6m");
+ else if (Name == "armv7")
+ DAL->AddJoinedArg(nullptr, MArch, "armv7a");
+ else if (Name == "armv7em")
+ DAL->AddJoinedArg(nullptr, MArch, "armv7em");
+ else if (Name == "armv7k")
+ DAL->AddJoinedArg(nullptr, MArch, "armv7k");
+ else if (Name == "armv7m")
+ DAL->AddJoinedArg(nullptr, MArch, "armv7m");
+ else if (Name == "armv7s")
+ DAL->AddJoinedArg(nullptr, MArch, "armv7s");
+ }
+
+ return DAL;
+}
+
+void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ // Embedded targets are simple at the moment, not supporting sanitizers and
+ // with different libraries for each member of the product { static, PIC } x
+ // { hard-float, soft-float }
+ llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
+ CompilerRT +=
+ tools::arm::getARMFloatABI(getDriver(), Args, getTriple()) == "hard"
+ ? "hard"
+ : "soft";
+ CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
+
+ AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
+}
+
+
+DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ // First get the generic Apple args, before moving onto Darwin-specific ones.
+ DerivedArgList *DAL = MachO::TranslateArgs(Args, BoundArch);
+ const OptTable &Opts = getDriver().getOpts();
+
+ // If no architecture is bound, none of the translations here are relevant.
+ if (!BoundArch)
+ return DAL;
+
+ // Add an explicit version min argument for the deployment target. We do this
+ // after argument translation because -Xarch_ arguments may add a version min
+ // argument.
+ AddDeploymentTarget(*DAL);
+
+ // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
+ // FIXME: It would be far better to avoid inserting those -static arguments,
+ // but we can't check the deployment target in the translation code until
+ // it is set here.
+ if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0) &&
+ getTriple().getArch() != llvm::Triple::arm64 &&
+ getTriple().getArch() != llvm::Triple::aarch64) {
+ for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
+ Arg *A = *it;
+ ++it;
+ if (A->getOption().getID() != options::OPT_mkernel &&
+ A->getOption().getID() != options::OPT_fapple_kext)
+ continue;
+ assert(it != ie && "unexpected argument translation");
+ A = *it;
+ assert(A->getOption().getID() == options::OPT_static &&
+ "missing expected -static argument");
+ it = DAL->getArgs().erase(it);
+ }
+ }
+
+ // Default to use libc++ on OS X 10.9+ and iOS 7+.
+ if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
+ (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
+ !Args.getLastArg(options::OPT_stdlib_EQ))
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
+ "libc++");
+
+ // Validate the C++ standard library choice.
+ CXXStdlibType Type = GetCXXStdlibType(*DAL);
+ if (Type == ToolChain::CST_Libcxx) {
+ // Check whether the target provides libc++.
+ StringRef where;
+
+ // Complain about targeting iOS < 5.0 in any way.
+ if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
+ where = "iOS 5.0";
+
+ if (where != StringRef()) {
+ getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment)
+ << where;
+ }
+ }
+
+ return DAL;
+}
+
+bool MachO::IsUnwindTablesDefault() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+bool MachO::UseDwarfDebugFlags() const {
+ if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
+ return S[0] != '\0';
+ return false;
+}
+
+bool Darwin::UseSjLjExceptions() const {
+ // Darwin uses SjLj exceptions on ARM.
+ return (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb);
+}
+
+bool MachO::isPICDefault() const {
+ return true;
+}
+
+bool MachO::isPIEDefault() const {
+ return false;
+}
+
+bool MachO::isPICDefaultForced() const {
+ return (getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::arm64 ||
+ getArch() == llvm::Triple::aarch64);
+}
+
+bool MachO::SupportsProfiling() const {
+ // Profiling instrumentation is only supported on x86.
+ return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64;
+}
+
+void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ VersionTuple TargetVersion = getTargetVersion();
+
+ // If we had an explicit -mios-simulator-version-min argument, honor that,
+ // otherwise use the traditional deployment targets. We can't just check the
+ // is-sim attribute because existing code follows this path, and the linker
+ // may not handle the argument.
+ //
+ // FIXME: We may be able to remove this, once we can verify no one depends on
+ // it.
+ if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ))
+ CmdArgs.push_back("-ios_simulator_version_min");
+ else if (isTargetIOSBased())
+ CmdArgs.push_back("-iphoneos_version_min");
+ else {
+ assert(isTargetMacOS() && "unexpected target");
+ CmdArgs.push_back("-macosx_version_min");
+ }
+
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+}
+
+void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ // Derived from startfile spec.
+ if (Args.hasArg(options::OPT_dynamiclib)) {
+ // Derived from darwin_dylib1 spec.
+ if (isTargetIOSSimulator()) {
+ ; // iOS simulator does not need dylib1.o.
+ } else if (isTargetIPhoneOS()) {
+ if (isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-ldylib1.o");
+ } else {
+ if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-ldylib1.o");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-ldylib1.10.5.o");
+ }
+ } else {
+ if (Args.hasArg(options::OPT_bundle)) {
+ if (!Args.hasArg(options::OPT_static)) {
+ // Derived from darwin_bundle1 spec.
+ if (isTargetIOSSimulator()) {
+ ; // iOS simulator does not need bundle1.o.
+ } else if (isTargetIPhoneOS()) {
+ if (isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-lbundle1.o");
+ } else {
+ if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lbundle1.o");
+ }
+ }
+ } else {
+ if (Args.hasArg(options::OPT_pg) && SupportsProfiling()) {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload)) {
+ CmdArgs.push_back("-lgcrt0.o");
+ } else {
+ CmdArgs.push_back("-lgcrt1.o");
+
+ // darwin_crt2 spec is empty.
+ }
+ // By default on OS X 10.8 and later, we don't link with a crt1.o
+ // file and the linker knows to use _main as the entry point. But,
+ // when compiling with -pg, we need to link with the gcrt1.o file,
+ // so pass the -no_new_main option to tell the linker to use the
+ // "start" symbol as the entry point.
+ if (isTargetMacOS() && !isMacosxVersionLT(10, 8))
+ CmdArgs.push_back("-no_new_main");
+ } else {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload)) {
+ CmdArgs.push_back("-lcrt0.o");
+ } else {
+ // Derived from darwin_crt1 spec.
+ if (isTargetIOSSimulator()) {
+ ; // iOS simulator does not need crt1.o.
+ } else if (isTargetIPhoneOS()) {
+ if (getArch() == llvm::Triple::arm64 ||
+ getArch() == llvm::Triple::aarch64)
+ ; // iOS does not need any crt1 files for arm64
+ else if (isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-lcrt1.o");
+ else if (isIPhoneOSVersionLT(6, 0))
+ CmdArgs.push_back("-lcrt1.3.1.o");
+ } else {
+ if (isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lcrt1.o");
+ else if (isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lcrt1.10.5.o");
+ else if (isMacosxVersionLT(10, 8))
+ CmdArgs.push_back("-lcrt1.10.6.o");
+
+ // darwin_crt2 spec is empty.
+ }
+ }
+ }
+ }
+ }
+
+ if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
+ isMacosxVersionLT(10, 5)) {
+ const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
+ CmdArgs.push_back(Str);
+ }
+}
+
+bool Darwin::SupportsObjCGC() const {
+ return isTargetMacOS();
+}
+
+void Darwin::CheckObjCARC() const {
+ if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
+ return;
+ getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
+}
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+
+/// \brief Parse a GCCVersion object out of a string of text.
+///
+/// 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, "", "", "" };
+ std::pair<StringRef, StringRef> First = VersionText.split('.');
+ std::pair<StringRef, StringRef> Second = First.second.split('.');
+
+ 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
+ // unspecified. This covers versions strings such as:
+ // 4.4
+ // 4.4.0
+ // 4.4.x
+ // 4.4.2-rc4
+ // 4.4.x-patched
+ // And retains any patch number it finds.
+ StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
+ if (!PatchText.empty()) {
+ if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
+ // Try to parse the number and any suffix.
+ if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
+ GoodVersion.Patch < 0)
+ return BadVersion;
+ GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
+ }
+ }
+
+ return GoodVersion;
+}
+
+/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
+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 (RHSPatch == -1)
+ return true;
+ if (Patch == -1)
+ return false;
+
+ // Otherwise just sort on the patch itself.
+ return Patch < RHSPatch;
+ }
+ if (PatchSuffix != RHSPatchSuffix) {
+ // Sort empty suffixes higher.
+ if (RHSPatchSuffix.empty())
+ return true;
+ if (PatchSuffix.empty())
+ return false;
+
+ // Provide a lexicographic sort to make this a total ordering.
+ return PatchSuffix < RHSPatchSuffix;
+ }
+
+ // The versions are equal.
+ return false;
+}
+
+static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain);
+ if (A)
+ return A->getValue();
+ return GCC_INSTALL_PREFIX;
+}
+
+/// \brief Initialize a GCCInstallationDetector from the driver.
+///
+/// This performs all of the autodetection and sets up the various paths.
+/// Once constructed, a GCCInstallationDetector is essentially immutable.
+///
+/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
+/// should instead pull the target out of the driver. This is currently
+/// necessary because the driver doesn't store the final version of the target
+/// triple.
+void
+Generic_GCC::GCCInstallationDetector::init(
+ const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
+ llvm::Triple BiarchVariantTriple =
+ TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
+ : TargetTriple.get32BitArchVariant();
+ // The library directories which may contain GCC installations.
+ SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
+ // The compatible GCC triples for this particular architecture.
+ SmallVector<StringRef, 10> CandidateTripleAliases;
+ 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(),
+ D.PrefixDirs.end());
+
+ StringRef GCCToolchainDir = getGCCToolchainDir(Args);
+ if (GCCToolchainDir != "") {
+ if (GCCToolchainDir.back() == '/')
+ GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
+
+ Prefixes.push_back(GCCToolchainDir);
+ } else {
+ // 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
+ // installation available. GCC installs are ranked by version number.
+ Version = GCCVersion::Parse("0.0.0");
+ for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
+ if (!llvm::sys::fs::exists(Prefixes[i]))
+ continue;
+ for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
+ const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
+ if (!llvm::sys::fs::exists(LibDir))
+ continue;
+ for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k)
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
+ CandidateTripleAliases[k]);
+ }
+ 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 = CandidateBiarchTripleAliases.size(); k < ke;
+ ++k)
+ ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
+ CandidateBiarchTripleAliases[k],
+ /*NeedsBiarchSuffix=*/ true);
+ }
+ }
+}
+
+void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
+ for (const auto &InstallPath : CandidateGCCInstallPaths)
+ OS << "Found candidate GCC installation: " << InstallPath << "\n";
+
+ if (!GCCInstallPath.empty())
+ OS << "Selected GCC installation: " << GCCInstallPath << "\n";
+
+ for (const auto &Multilib : Multilibs)
+ OS << "Candidate multilib: " << Multilib << "\n";
+
+ if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
+ OS << "Selected multilib: " << SelectedMultilib << "\n";
+}
+
+bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
+ if (BiarchSibling.hasValue()) {
+ M = BiarchSibling.getValue();
+ return true;
+ }
+ return false;
+}
+
+/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
+ const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
+ SmallVectorImpl<StringRef> &LibDirs,
+ SmallVectorImpl<StringRef> &TripleAliases,
+ 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[] = { "/lib64", "/lib" };
+ static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu",
+ "aarch64-linux-gnu",
+ "aarch64-linux-android",
+ "aarch64-redhat-linux" };
+ static const char *const AArch64beLibDirs[] = { "/lib" };
+ static const char *const AArch64beTriples[] = { "aarch64_be-none-linux-gnu",
+ "aarch64_be-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 ARMebLibDirs[] = { "/lib" };
+ static const char *const ARMebTriples[] = { "armeb-linux-gnueabi",
+ "armeb-linux-androideabi" };
+ static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf",
+ "armebv7hl-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-android", "x86_64-unknown-linux"
+ };
+ static const char *const X32LibDirs[] = { "/libx32" };
+ 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-montavista-linux", "i686-linux-android", "i586-linux-gnu"
+ };
+
+ static const char *const MIPSLibDirs[] = { "/lib" };
+ static const char *const MIPSTriples[] = { "mips-linux-gnu",
+ "mips-mti-linux-gnu",
+ "mips-img-linux-gnu" };
+ static const char *const MIPSELLibDirs[] = { "/lib" };
+ static const char *const MIPSELTriples[] = { "mipsel-linux-gnu",
+ "mipsel-linux-android",
+ "mips-img-linux-gnu" };
+
+ static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
+ static const char *const MIPS64Triples[] = { "mips64-linux-gnu",
+ "mips-mti-linux-gnu",
+ "mips-img-linux-gnu",
+ "mips64-linux-gnuabi64" };
+ static const char *const MIPS64ELLibDirs[] = { "/lib64", "/lib" };
+ static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu",
+ "mips-mti-linux-gnu",
+ "mips-img-linux-gnu",
+ "mips64el-linux-android",
+ "mips64el-linux-gnuabi64" };
+
+ 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"
+ };
+ 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 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 SPARCv8LibDirs[] = { "/lib32", "/lib" };
+ static const char *const SPARCv8Triples[] = { "sparc-linux-gnu",
+ "sparcv8-linux-gnu" };
+ static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" };
+ static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu",
+ "sparcv9-linux-gnu" };
+
+ static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
+ static const char *const SystemZTriples[] = {
+ "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
+ "s390x-suse-linux", "s390x-redhat-linux"
+ };
+
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::arm64:
+ case llvm::Triple::aarch64:
+ 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::arm64_be:
+ case llvm::Triple::aarch64_be:
+ LibDirs.append(AArch64beLibDirs,
+ AArch64beLibDirs + llvm::array_lengthof(AArch64beLibDirs));
+ TripleAliases.append(AArch64beTriples,
+ AArch64beTriples + llvm::array_lengthof(AArch64beTriples));
+ BiarchLibDirs.append(AArch64beLibDirs,
+ AArch64beLibDirs + llvm::array_lengthof(AArch64beLibDirs));
+ BiarchTripleAliases.append(
+ AArch64beTriples, AArch64beTriples + llvm::array_lengthof(AArch64beTriples));
+ 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));
+ } else {
+ TripleAliases.append(ARMTriples,
+ ARMTriples + llvm::array_lengthof(ARMTriples));
+ }
+ break;
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ LibDirs.append(ARMebLibDirs, ARMebLibDirs + llvm::array_lengthof(ARMebLibDirs));
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ TripleAliases.append(ARMebHFTriples,
+ ARMebHFTriples + llvm::array_lengthof(ARMebHFTriples));
+ } else {
+ TripleAliases.append(ARMebTriples,
+ ARMebTriples + llvm::array_lengthof(ARMebTriples));
+ }
+ 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));
+ // x32 is always available when x86_64 is available, so adding it as secondary
+ // arch with x86_64 triples
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32) {
+ BiarchLibDirs.append(X32LibDirs,
+ X32LibDirs + llvm::array_lengthof(X32LibDirs));
+ BiarchTripleAliases.append(X86_64Triples,
+ X86_64Triples + llvm::array_lengthof(X86_64Triples));
+ } else {
+ 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));
+ 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));
+ 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));
+ 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));
+ 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));
+ TripleAliases.append(
+ 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));
+ 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));
+ 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::sparc:
+ LibDirs.append(SPARCv8LibDirs,
+ SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
+ TripleAliases.append(SPARCv8Triples,
+ SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
+ BiarchLibDirs.append(SPARCv9LibDirs,
+ SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
+ BiarchTripleAliases.append(
+ SPARCv9Triples, SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
+ break;
+ case llvm::Triple::sparcv9:
+ LibDirs.append(SPARCv9LibDirs,
+ SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
+ TripleAliases.append(SPARCv9Triples,
+ SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
+ BiarchLibDirs.append(SPARCv8LibDirs,
+ SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
+ BiarchTripleAliases.append(
+ SPARCv8Triples, SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
+ break;
+ case llvm::Triple::systemz:
+ LibDirs.append(SystemZLibDirs,
+ SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
+ TripleAliases.append(SystemZTriples,
+ SystemZTriples + llvm::array_lengthof(SystemZTriples));
+ break;
+
+ default:
+ // By default, just rely on the standard lib directories and the original
+ // triple.
+ break;
+ }
+
+ // Always append the drivers target triple to the end, in case it doesn't
+ // match any of our aliases.
+ TripleAliases.push_back(TargetTriple.str());
+
+ // Also include the multiarch variant if it's different.
+ if (TargetTriple.str() != BiarchTriple.str())
+ BiarchTripleAliases.push_back(BiarchTriple.str());
+}
+
+namespace {
+// Filter to remove Multilibs that don't exist as a suffix to Path
+class FilterNonExistent : public MultilibSet::FilterCallback {
+ std::string Base;
+public:
+ FilterNonExistent(std::string Base) : Base(Base) {}
+ bool operator()(const Multilib &M) const override {
+ return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o");
+ }
+};
+} // end anonymous namespace
+
+static void addMultilibFlag(bool Enabled, const char *const Flag,
+ std::vector<std::string> &Flags) {
+ if (Enabled)
+ Flags.push_back(std::string("+") + Flag);
+ else
+ Flags.push_back(std::string("-") + Flag);
+}
+
+static bool isMipsArch(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
+ Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
+}
+
+static bool isMips32(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel;
+}
+
+static bool isMips64(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
+}
+
+static bool isMipsEL(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
+}
+
+static bool isMips16(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mips16,
+ options::OPT_mno_mips16);
+ return A && A->getOption().matches(options::OPT_mips16);
+}
+
+static bool isMicroMips(const ArgList &Args) {
+ Arg *A = Args.getLastArg(options::OPT_mmicromips,
+ options::OPT_mno_micromips);
+ return A && A->getOption().matches(options::OPT_mmicromips);
+}
+
+struct DetectedMultilibs {
+ /// The set of multilibs that the detected installation supports.
+ MultilibSet Multilibs;
+
+ /// The primary multilib appropriate for the given flags.
+ Multilib SelectedMultilib;
+
+ /// On Biarch systems, this corresponds to the default multilib when
+ /// targeting the non-default multilib. Otherwise, it is empty.
+ llvm::Optional<Multilib> BiarchSibling;
+};
+
+static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path,
+ const llvm::opt::ArgList &Args,
+ DetectedMultilibs &Result) {
+ // 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'
+
+ FilterNonExistent NonExistent(Path);
+
+ // Check for FSF toolchain multilibs
+ MultilibSet FSFMipsMultilibs;
+ {
+ Multilib MArchMips32 = Multilib()
+ .gccSuffix("/mips32")
+ .osSuffix("/mips32")
+ .includeSuffix("/mips32")
+ .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32");
+
+ Multilib MArchMicroMips = Multilib()
+ .gccSuffix("/micromips")
+ .osSuffix("/micromips")
+ .includeSuffix("/micromips")
+ .flag("+m32").flag("-m64").flag("+mmicromips");
+
+ Multilib MArchMips64r2 = Multilib()
+ .gccSuffix("/mips64r2")
+ .osSuffix("/mips64r2")
+ .includeSuffix("/mips64r2")
+ .flag("-m32").flag("+m64").flag("+march=mips64r2");
+
+ Multilib MArchMips64 = Multilib()
+ .gccSuffix("/mips64")
+ .osSuffix("/mips64")
+ .includeSuffix("/mips64")
+ .flag("-m32").flag("+m64").flag("-march=mips64r2");
+
+ Multilib MArchDefault = Multilib()
+ .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32r2");
+
+ Multilib Mips16 = Multilib()
+ .gccSuffix("/mips16")
+ .osSuffix("/mips16")
+ .includeSuffix("/mips16")
+ .flag("+mips16");
+
+ Multilib MAbi64 = Multilib()
+ .gccSuffix("/64")
+ .osSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+
+ Multilib BigEndian = Multilib()
+ .flag("+EB").flag("-EL");
+
+ Multilib LittleEndian = Multilib()
+ .gccSuffix("/el")
+ .osSuffix("/el")
+ .includeSuffix("/el")
+ .flag("+EL").flag("-EB");
+
+ Multilib SoftFloat = Multilib()
+ .gccSuffix("/sof")
+ .osSuffix("/sof")
+ .includeSuffix("/sof")
+ .flag("+msoft-float");
+
+ Multilib Nan2008 = Multilib()
+ .gccSuffix("/nan2008")
+ .osSuffix("/nan2008")
+ .includeSuffix("/nan2008")
+ .flag("+mnan=2008");
+
+ FSFMipsMultilibs = MultilibSet()
+ .Either(MArchMips32, MArchMicroMips,
+ MArchMips64r2, MArchMips64, MArchDefault)
+ .Maybe(Mips16)
+ .FilterOut("/mips64/mips16")
+ .FilterOut("/mips64r2/mips16")
+ .FilterOut("/micromips/mips16")
+ .Maybe(MAbi64)
+ .FilterOut("/micromips/64")
+ .FilterOut("/mips32/64")
+ .FilterOut("^/64")
+ .FilterOut("/mips16/64")
+ .Either(BigEndian, LittleEndian)
+ .Maybe(SoftFloat)
+ .Maybe(Nan2008)
+ .FilterOut(".*sof/nan2008")
+ .FilterOut(NonExistent);
+ }
+
+ // Check for Code Sourcery toolchain multilibs
+ MultilibSet CSMipsMultilibs;
+ {
+ Multilib MArchMips16 = Multilib()
+ .gccSuffix("/mips16")
+ .osSuffix("/mips16")
+ .includeSuffix("/mips16")
+ .flag("+m32").flag("+mips16");
+
+ Multilib MArchMicroMips = Multilib()
+ .gccSuffix("/micromips")
+ .osSuffix("/micromips")
+ .includeSuffix("/micromips")
+ .flag("+m32").flag("+mmicromips");
+
+ Multilib MArchDefault = Multilib()
+ .flag("-mips16").flag("-mmicromips");
+
+ Multilib SoftFloat = Multilib()
+ .gccSuffix("/soft-float")
+ .osSuffix("/soft-float")
+ .includeSuffix("/soft-float")
+ .flag("+msoft-float");
+
+ Multilib Nan2008 = Multilib()
+ .gccSuffix("/nan2008")
+ .osSuffix("/nan2008")
+ .includeSuffix("/nan2008")
+ .flag("+mnan=2008");
+
+ Multilib DefaultFloat = Multilib()
+ .flag("-msoft-float").flag("-mnan=2008");
+
+ Multilib BigEndian = Multilib()
+ .flag("+EB").flag("-EL");
+
+ Multilib LittleEndian = Multilib()
+ .gccSuffix("/el")
+ .osSuffix("/el")
+ .includeSuffix("/el")
+ .flag("+EL").flag("-EB");
+
+ // Note that this one's osSuffix is ""
+ Multilib MAbi64 = Multilib()
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+
+ CSMipsMultilibs = MultilibSet()
+ .Either(MArchMips16, MArchMicroMips, MArchDefault)
+ .Either(SoftFloat, Nan2008, DefaultFloat)
+ .FilterOut("/micromips/nan2008")
+ .FilterOut("/mips16/nan2008")
+ .Either(BigEndian, LittleEndian)
+ .Maybe(MAbi64)
+ .FilterOut("/mips16.*/64")
+ .FilterOut("/micromips.*/64")
+ .FilterOut(NonExistent);
+ }
+
+ MultilibSet AndroidMipsMultilibs = MultilibSet()
+ .Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
+ .FilterOut(NonExistent);
+
+ MultilibSet DebianMipsMultilibs;
+ {
+ Multilib MAbiN32 = Multilib()
+ .gccSuffix("/n32")
+ .includeSuffix("/n32")
+ .flag("+mabi=n32");
+
+ Multilib M64 = Multilib()
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+m64").flag("-m32").flag("-mabi=n32");
+
+ Multilib M32 = Multilib()
+ .flag("-m64").flag("+m32").flag("-mabi=n32");
+
+ DebianMipsMultilibs = MultilibSet()
+ .Either(M32, M64, MAbiN32)
+ .FilterOut(NonExistent);
+ }
+
+ MultilibSet ImgMultilibs;
+ {
+ Multilib Mips64r6 = Multilib()
+ .gccSuffix("/mips64r6")
+ .osSuffix("/mips64r6")
+ .includeSuffix("/mips64r6")
+ .flag("+m64").flag("-m32");
+
+ Multilib LittleEndian = Multilib()
+ .gccSuffix("/el")
+ .osSuffix("/el")
+ .includeSuffix("/el")
+ .flag("+EL").flag("-EB");
+
+ Multilib MAbi64 = Multilib()
+ .gccSuffix("/64")
+ .osSuffix("/64")
+ .includeSuffix("/64")
+ .flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+
+ ImgMultilibs = MultilibSet()
+ .Maybe(Mips64r6)
+ .Maybe(MAbi64)
+ .Maybe(LittleEndian)
+ .FilterOut(NonExistent);
+ }
+
+ StringRef CPUName;
+ StringRef ABIName;
+ tools::mips::getMipsCPUAndABI(Args, TargetTriple, CPUName, ABIName);
+
+ llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
+
+ Multilib::flags_list Flags;
+ addMultilibFlag(isMips32(TargetArch), "m32", Flags);
+ addMultilibFlag(isMips64(TargetArch), "m64", Flags);
+ addMultilibFlag(isMips16(Args), "mips16", Flags);
+ addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
+ addMultilibFlag(CPUName == "mips32r2", "march=mips32r2", Flags);
+ addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
+ addMultilibFlag(CPUName == "mips64r2" || CPUName == "octeon",
+ "march=mips64r2", Flags);
+ addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
+ addMultilibFlag(tools::mips::isNaN2008(Args, TargetTriple), "mnan=2008",
+ Flags);
+ addMultilibFlag(ABIName == "n32", "mabi=n32", Flags);
+ addMultilibFlag(ABIName == "n64", "mabi=n64", Flags);
+ addMultilibFlag(isSoftFloatABI(Args), "msoft-float", Flags);
+ addMultilibFlag(!isSoftFloatABI(Args), "mhard-float", Flags);
+ addMultilibFlag(isMipsEL(TargetArch), "EL", Flags);
+ addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags);
+
+ if (TargetTriple.getEnvironment() == llvm::Triple::Android) {
+ // Select Android toolchain. It's the only choice in that case.
+ if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
+ Result.Multilibs = AndroidMipsMultilibs;
+ return true;
+ }
+ return false;
+ }
+
+ if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies &&
+ TargetTriple.getOS() == llvm::Triple::Linux &&
+ TargetTriple.getEnvironment() == llvm::Triple::GNU) {
+ // Select mips-img-linux-gnu toolchain.
+ if (ImgMultilibs.select(Flags, Result.SelectedMultilib)) {
+ Result.Multilibs = ImgMultilibs;
+ return true;
+ }
+ return false;
+ }
+
+ // Sort candidates. Toolchain that best meets the directories goes first.
+ // Then select the first toolchains matches command line flags.
+ MultilibSet *candidates[] = { &DebianMipsMultilibs, &FSFMipsMultilibs,
+ &CSMipsMultilibs };
+ std::sort(
+ std::begin(candidates), std::end(candidates),
+ [](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); });
+ for (const auto &candidate : candidates) {
+ if (candidate->select(Flags, Result.SelectedMultilib)) {
+ if (candidate == &DebianMipsMultilibs)
+ Result.BiarchSibling = Multilib();
+ Result.Multilibs = *candidate;
+ return true;
+ }
+ }
+
+ {
+ // Fallback to the regular toolchain-tree structure.
+ Multilib Default;
+ Result.Multilibs.push_back(Default);
+ Result.Multilibs.FilterOut(NonExistent);
+
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) {
+ Result.BiarchSibling = Multilib();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool findBiarchMultilibs(const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ bool NeedsBiarchSuffix,
+ DetectedMultilibs &Result) {
+
+ // 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 biarch triple alias, we look for
+ // crtbegin.o without the subdirectory.
+
+ Multilib Default;
+ Multilib Alt64 = Multilib()
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("-m32").flag("+m64").flag("-mx32");
+ Multilib Alt32 = Multilib()
+ .gccSuffix("/32")
+ .includeSuffix("/32")
+ .flag("+m32").flag("-m64").flag("-mx32");
+ Multilib Altx32 = Multilib()
+ .gccSuffix("/x32")
+ .includeSuffix("/x32")
+ .flag("-m32").flag("-m64").flag("+mx32");
+
+ FilterNonExistent NonExistent(Path);
+
+ // Determine default multilib from: 32, 64, x32
+ // Also handle cases such as 64 on 32, 32 on 64, etc.
+ enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;
+ const bool IsX32 = TargetTriple.getEnvironment() == llvm::Triple::GNUX32;
+ if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
+ Want = WANT64;
+ else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
+ Want = WANT64;
+ else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64))
+ Want = WANT32;
+ else {
+ if (TargetTriple.isArch32Bit())
+ Want = NeedsBiarchSuffix ? WANT64 : WANT32;
+ else if (IsX32)
+ Want = NeedsBiarchSuffix ? WANT64 : WANTX32;
+ else
+ Want = NeedsBiarchSuffix ? WANT32 : WANT64;
+ }
+
+ if (Want == WANT32)
+ Default.flag("+m32").flag("-m64").flag("-mx32");
+ else if (Want == WANT64)
+ Default.flag("-m32").flag("+m64").flag("-mx32");
+ else if (Want == WANTX32)
+ Default.flag("-m32").flag("-m64").flag("+mx32");
+ else
+ return false;
+
+ Result.Multilibs.push_back(Default);
+ Result.Multilibs.push_back(Alt64);
+ Result.Multilibs.push_back(Alt32);
+ Result.Multilibs.push_back(Altx32);
+
+ Result.Multilibs.FilterOut(NonExistent);
+
+ Multilib::flags_list Flags;
+ addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "m64", Flags);
+ addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags);
+ addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "mx32", Flags);
+
+ if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
+ return false;
+
+ if (Result.SelectedMultilib == Alt64 ||
+ Result.SelectedMultilib == Alt32 ||
+ Result.SelectedMultilib == Altx32)
+ Result.BiarchSibling = Default;
+
+ return true;
+}
+
+void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
+ const llvm::Triple &TargetTriple, const ArgList &Args,
+ const std::string &LibDir, StringRef CandidateTriple,
+ bool NeedsBiarchSuffix) {
+ llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
+ // 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
+ // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
+ "/" + CandidateTriple.str(),
+
+ // Ubuntu has a strange mis-matched pair of triples that this happens to
+ // match.
+ // FIXME: It may be worthwhile to generalize this and look for a second
+ // triple.
+ "/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));
+ for (unsigned i = 0; i < NumLibSuffixes; ++i) {
+ StringRef LibSuffix = LibSuffixes[i];
+ std::error_code EC;
+ for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
+ 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;
+
+ DetectedMultilibs Detected;
+
+ // Debian mips multilibs behave more like the rest of the biarch ones,
+ // so handle them there
+ if (isMipsArch(TargetArch)) {
+ if (!findMIPSMultilibs(TargetTriple, LI->path(), Args, Detected))
+ continue;
+ } else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args,
+ NeedsBiarchSuffix, Detected)) {
+ continue;
+ }
+
+ Multilibs = Detected.Multilibs;
+ SelectedMultilib = Detected.SelectedMultilib;
+ BiarchSibling = Detected.BiarchSibling;
+ Version = CandidateVersion;
+ GCCTriple.setTriple(CandidateTriple);
+ // FIXME: We hack together the directory name here instead of
+ // using LI to ensure stable path separators across Windows and
+ // Linux.
+ GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str();
+ GCCParentLibPath = GCCInstallPath + InstallSuffixes[i];
+ IsValid = true;
+ }
+ }
+}
+
+Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args), GCCInstallation() {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+Generic_GCC::~Generic_GCC() {
+}
+
+Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::PreprocessJobClass:
+ if (!Preprocess)
+ Preprocess.reset(new tools::gcc::Preprocess(*this));
+ return Preprocess.get();
+ case Action::CompileJobClass:
+ if (!Compile)
+ Compile.reset(new tools::gcc::Compile(*this));
+ return Compile.get();
+ default:
+ return ToolChain::getTool(AC);
+ }
+}
+
+Tool *Generic_GCC::buildAssembler() const {
+ return new tools::gnutools::Assemble(*this);
+}
+
+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;
+}
+
+bool Generic_GCC::isPICDefault() const {
+ return false;
+}
+
+bool Generic_GCC::isPIEDefault() const {
+ return false;
+}
+
+bool Generic_GCC::isPICDefaultForced() const {
+ return false;
+}
+
+bool Generic_GCC::IsIntegratedAssemblerDefault() const {
+ return getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be ||
+ getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::armeb ||
+ getTriple().getArch() == llvm::Triple::thumb ||
+ getTriple().getArch() == llvm::Triple::thumbeb;
+}
+
+void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
+ bool UseInitArrayDefault =
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be ||
+ (getTriple().getOS() == llvm::Triple::Linux &&
+ (!V.isOlderThan(4, 7, 0) ||
+ getTriple().getEnvironment() == llvm::Triple::Android));
+
+ if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array,
+ UseInitArrayDefault))
+ CC1Args.push_back("-fuse-init-array");
+}
+
+/// Hexagon Toolchain
+
+std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir) {
+
+ // Locate the rest of the toolchain ...
+ if (strlen(GCC_INSTALL_PREFIX))
+ return std::string(GCC_INSTALL_PREFIX);
+
+ std::string InstallRelDir = InstalledDir + "/../../gnu";
+ if (llvm::sys::fs::exists(InstallRelDir))
+ return InstallRelDir;
+
+ std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/../gnu";
+ if (llvm::sys::fs::exists(PrefixRelDir))
+ return PrefixRelDir;
+
+ return InstallRelDir;
+}
+
+static void GetHexagonLibraryPaths(
+ const ArgList &Args,
+ const std::string Ver,
+ const std::string MarchString,
+ const std::string &InstalledDir,
+ ToolChain::path_list *LibPaths)
+{
+ bool buildingLib = Args.hasArg(options::OPT_shared);
+
+ //----------------------------------------------------------------------------
+ // -L Args
+ //----------------------------------------------------------------------------
+ for (arg_iterator
+ it = Args.filtered_begin(options::OPT_L),
+ ie = Args.filtered_end();
+ it != ie;
+ ++it) {
+ for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
+ LibPaths->push_back((*it)->getValue(i));
+ }
+
+ //----------------------------------------------------------------------------
+ // Other standard paths
+ //----------------------------------------------------------------------------
+ const std::string MarchSuffix = "/" + MarchString;
+ const std::string G0Suffix = "/G0";
+ const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
+ const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir) + "/";
+
+ // lib/gcc/hexagon/...
+ std::string LibGCCHexagonDir = RootDir + "lib/gcc/hexagon/";
+ if (buildingLib) {
+ LibPaths->push_back(LibGCCHexagonDir + Ver + MarchG0Suffix);
+ LibPaths->push_back(LibGCCHexagonDir + Ver + G0Suffix);
+ }
+ LibPaths->push_back(LibGCCHexagonDir + Ver + MarchSuffix);
+ LibPaths->push_back(LibGCCHexagonDir + Ver);
+
+ // lib/gcc/...
+ LibPaths->push_back(RootDir + "lib/gcc");
+
+ // hexagon/lib/...
+ std::string HexagonLibDir = RootDir + "hexagon/lib";
+ if (buildingLib) {
+ LibPaths->push_back(HexagonLibDir + MarchG0Suffix);
+ LibPaths->push_back(HexagonLibDir + G0Suffix);
+ }
+ LibPaths->push_back(HexagonLibDir + MarchSuffix);
+ LibPaths->push_back(HexagonLibDir);
+}
+
+Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Linux(D, Triple, Args) {
+ const std::string InstalledDir(getDriver().getInstalledDir());
+ const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir);
+
+ // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
+ // program paths
+ const std::string BinDir(GnuDir + "/bin");
+ if (llvm::sys::fs::exists(BinDir))
+ getProgramPaths().push_back(BinDir);
+
+ // Determine version of GCC libraries and headers to use.
+ const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon");
+ std::error_code ec;
+ GCCVersion MaxVersion= GCCVersion::Parse("0.0.0");
+ for (llvm::sys::fs::directory_iterator di(HexagonDir, ec), de;
+ !ec && di != de; di = di.increment(ec)) {
+ GCCVersion cv = GCCVersion::Parse(llvm::sys::path::filename(di->path()));
+ if (MaxVersion < cv)
+ MaxVersion = cv;
+ }
+ GCCLibAndIncVersion = MaxVersion;
+
+ ToolChain::path_list *LibPaths= &getFilePaths();
+
+ // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
+ // 'elf' OS type, so the Linux paths are not appropriate. When we actually
+ // support 'linux' we'll need to fix this up
+ LibPaths->clear();
+
+ GetHexagonLibraryPaths(
+ Args,
+ GetGCCLibAndIncVersion(),
+ GetTargetCPU(Args),
+ InstalledDir,
+ LibPaths);
+}
+
+Hexagon_TC::~Hexagon_TC() {
+}
+
+Tool *Hexagon_TC::buildAssembler() const {
+ return new tools::hexagon::Assemble(*this);
+}
+
+Tool *Hexagon_TC::buildLinker() const {
+ return new tools::hexagon::Link(*this);
+}
+
+void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ std::string Ver(GetGCCLibAndIncVersion());
+ std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir);
+ std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver);
+ addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include-fixed");
+ addExternCSystemInclude(DriverArgs, CC1Args, GnuDir + "/hexagon/include");
+}
+
+void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ const Driver &D = getDriver();
+ std::string Ver(GetGCCLibAndIncVersion());
+ SmallString<128> IncludeDir(Hexagon_TC::GetGnuDir(D.InstalledDir));
+
+ llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
+ llvm::sys::path::append(IncludeDir, Ver);
+ addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
+}
+
+ToolChain::CXXStdlibType
+Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const {
+ Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
+ if (!A)
+ return ToolChain::CST_Libstdcxx;
+
+ StringRef Value = A->getValue();
+ if (Value != "libstdc++") {
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libstdcxx;
+}
+
+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;
+ }
+
+ // FIXME: should probably be an error.
+ return 4;
+}
+
+StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
+{
+ 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";
+ }
+}
+// End Hexagon
+
+/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
+/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
+/// Currently does not support anything else but compilation.
+
+TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ // Path mangling to find libexec
+ std::string Path(getDriver().Dir);
+
+ Path += "/../libexec";
+ getProgramPaths().push_back(Path);
+}
+
+TCEToolChain::~TCEToolChain() {
+}
+
+bool TCEToolChain::IsMathErrnoDefault() const {
+ return true;
+}
+
+bool TCEToolChain::isPICDefault() const {
+ return false;
+}
+
+bool TCEToolChain::isPIEDefault() const {
+ return false;
+}
+
+bool TCEToolChain::isPICDefaultForced() const {
+ return false;
+}
+
+/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
+
+OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+}
+
+Tool *OpenBSD::buildAssembler() const {
+ return new tools::openbsd::Assemble(*this);
+}
+
+Tool *OpenBSD::buildLinker() const {
+ return new tools::openbsd::Link(*this);
+}
+
+/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
+
+Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+}
+
+Tool *Bitrig::buildAssembler() const {
+ return new tools::bitrig::Assemble(*this);
+}
+
+Tool *Bitrig::buildLinker() const {
+ return new tools::bitrig::Link(*this);
+}
+
+ToolChain::CXXStdlibType
+Bitrig::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+ return ToolChain::CST_Libcxx;
+}
+
+void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/v1");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++");
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/backward");
+
+ StringRef Triple = getTriple().str();
+ if (Triple.startswith("amd64"))
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" +
+ Triple.substr(5));
+ else
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/stdc++/" +
+ Triple);
+ break;
+ }
+}
+
+void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lpthread");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+}
+
+/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
+
+FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
+ // back to '/usr/lib' if it doesn't exist.
+ if ((Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::ppc) &&
+ llvm::sys::fs::exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
+ getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
+ else
+ getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+}
+
+ToolChain::CXXStdlibType
+FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+ if (getTriple().getOSMajorVersion() >= 10)
+ return ToolChain::CST_Libcxx;
+ return ToolChain::CST_Libstdcxx;
+}
+
+void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/v1");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/4.2");
+ 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::GNUEABIHF:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::EABI:
+ return false;
+
+ default:
+ return (getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::thumb);
+ }
+}
+
+bool FreeBSD::HasNativeLLVMSupport() const {
+ return true;
+}
+
+bool FreeBSD::isPIEDefault() const {
+ return getSanitizerArgs().hasZeroBaseShadow();
+}
+
+/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
+
+NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ if (getDriver().UseStdLib) {
+ // When targeting a 32-bit platform, try the special directory used on
+ // 64-bit hosts, and only fall back to the main library directory if that
+ // doesn't work.
+ // FIXME: It'd be nicer to test if this directory exists, but I'm not sure
+ // what all logic is needed to emulate the '=' prefix here.
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ getFilePaths().push_back("=/usr/lib/i386");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::EABI:
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
+ getFilePaths().push_back("=/usr/lib/eabi");
+ break;
+ default:
+ getFilePaths().push_back("=/usr/lib/oabi");
+ break;
+ }
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ if (tools::mips::hasMipsAbiArg(Args, "o32"))
+ getFilePaths().push_back("=/usr/lib/o32");
+ else if (tools::mips::hasMipsAbiArg(Args, "64"))
+ getFilePaths().push_back("=/usr/lib/64");
+ break;
+ case llvm::Triple::sparc:
+ getFilePaths().push_back("=/usr/lib/sparc");
+ break;
+ default:
+ break;
+ }
+
+ getFilePaths().push_back("=/usr/lib");
+ }
+}
+
+Tool *NetBSD::buildAssembler() const {
+ return new tools::netbsd::Assemble(*this);
+}
+
+Tool *NetBSD::buildLinker() const {
+ return new tools::netbsd::Link(*this);
+}
+
+ToolChain::CXXStdlibType
+NetBSD::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ unsigned Major, Minor, Micro;
+ getTriple().getOSVersion(Major, Minor, Micro);
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
+ switch (getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return ToolChain::CST_Libcxx;
+ default:
+ break;
+ }
+ }
+ return ToolChain::CST_Libstdcxx;
+}
+
+void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/");
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/g++");
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/g++/backward");
+ break;
+ }
+}
+
+/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
+
+Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+}
+
+Tool *Minix::buildAssembler() const {
+ return new tools::minix::Assemble(*this);
+}
+
+Tool *Minix::buildLinker() const {
+ return new tools::minix::Link(*this);
+}
+
+/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
+
+AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {
+
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back("/usr/sfw/lib");
+ getFilePaths().push_back("/opt/gcc4/lib");
+ getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
+
+}
+
+Tool *AuroraUX::buildAssembler() const {
+ return new tools::auroraux::Assemble(*this);
+}
+
+Tool *AuroraUX::buildLinker() const {
+ return new tools::auroraux::Link(*this);
+}
+
+/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
+
+Solaris::Solaris(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {
+
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+}
+
+Tool *Solaris::buildAssembler() const {
+ return new tools::solaris::Assemble(*this);
+}
+
+Tool *Solaris::buildLinker() const {
+ return new tools::solaris::Link(*this);
+}
+
+/// Distribution (very bare-bones at the moment).
+
+enum Distro {
+ ArchLinux,
+ DebianLenny,
+ DebianSqueeze,
+ DebianWheezy,
+ DebianJessie,
+ Exherbo,
+ RHEL4,
+ RHEL5,
+ RHEL6,
+ Fedora,
+ OpenSUSE,
+ UbuntuHardy,
+ UbuntuIntrepid,
+ UbuntuJaunty,
+ UbuntuKarmic,
+ UbuntuLucid,
+ UbuntuMaverick,
+ UbuntuNatty,
+ UbuntuOneiric,
+ UbuntuPrecise,
+ UbuntuQuantal,
+ UbuntuRaring,
+ UbuntuSaucy,
+ UbuntuTrusty,
+ UnknownDistro
+};
+
+static bool IsRedhat(enum Distro Distro) {
+ return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6);
+}
+
+static bool IsOpenSUSE(enum Distro Distro) {
+ return Distro == OpenSUSE;
+}
+
+static bool IsDebian(enum Distro Distro) {
+ return Distro >= DebianLenny && Distro <= DebianJessie;
+}
+
+static bool IsUbuntu(enum Distro Distro) {
+ return Distro >= UbuntuHardy && Distro <= UbuntuTrusty;
+}
+
+static Distro DetectDistro(llvm::Triple::ArchType Arch) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ llvm::MemoryBuffer::getFile("/etc/lsb-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ SmallVector<StringRef, 8> Lines;
+ Data.split(Lines, "\n");
+ Distro Version = UnknownDistro;
+ for (unsigned i = 0, s = Lines.size(); i != s; ++i)
+ if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME="))
+ Version = llvm::StringSwitch<Distro>(Lines[i].substr(17))
+ .Case("hardy", UbuntuHardy)
+ .Case("intrepid", UbuntuIntrepid)
+ .Case("jaunty", UbuntuJaunty)
+ .Case("karmic", UbuntuKarmic)
+ .Case("lucid", UbuntuLucid)
+ .Case("maverick", UbuntuMaverick)
+ .Case("natty", UbuntuNatty)
+ .Case("oneiric", UbuntuOneiric)
+ .Case("precise", UbuntuPrecise)
+ .Case("quantal", UbuntuQuantal)
+ .Case("raring", UbuntuRaring)
+ .Case("saucy", UbuntuSaucy)
+ .Case("trusty", UbuntuTrusty)
+ .Default(UnknownDistro);
+ return Version;
+ }
+
+ File = llvm::MemoryBuffer::getFile("/etc/redhat-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("Fedora release"))
+ return Fedora;
+ if (Data.startswith("Red Hat Enterprise Linux") ||
+ Data.startswith("CentOS")) {
+ if (Data.find("release 6") != StringRef::npos)
+ return RHEL6;
+ else if (Data.find("release 5") != StringRef::npos)
+ return RHEL5;
+ else if (Data.find("release 4") != StringRef::npos)
+ return RHEL4;
+ }
+ return UnknownDistro;
+ }
+
+ File = llvm::MemoryBuffer::getFile("/etc/debian_version");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ if (Data[0] == '5')
+ return DebianLenny;
+ else if (Data.startswith("squeeze/sid") || Data[0] == '6')
+ return DebianSqueeze;
+ else if (Data.startswith("wheezy/sid") || Data[0] == '7')
+ return DebianWheezy;
+ else if (Data.startswith("jessie/sid") || Data[0] == '8')
+ return DebianJessie;
+ return UnknownDistro;
+ }
+
+ if (llvm::sys::fs::exists("/etc/SuSE-release"))
+ return OpenSUSE;
+
+ if (llvm::sys::fs::exists("/etc/exherbo-release"))
+ return Exherbo;
+
+ if (llvm::sys::fs::exists("/etc/arch-release"))
+ return ArchLinux;
+
+ return UnknownDistro;
+}
+
+/// \brief Get our best guess at the multiarch triple for a target.
+///
+/// Debian-based systems are starting to use a multiarch setup where they use
+/// a target-triple directory in the library and header search paths.
+/// Unfortunately, this triple does not align with the vanilla target triple,
+/// so we provide a rough mapping here.
+static std::string getMultiarchTriple(const llvm::Triple &TargetTriple,
+ StringRef SysRoot) {
+ // For most architectures, just use whatever we have rather than trying to be
+ // clever.
+ switch (TargetTriple.getArch()) {
+ default:
+ return TargetTriple.str();
+
+ // We use the existence of '/lib/<triple>' as a directory to detect some
+ // common linux triples that don't quite match the Clang triple for both
+ // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+ // regardless of what the actual target triple is.
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf"))
+ return "arm-linux-gnueabihf";
+ } else {
+ if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi"))
+ return "arm-linux-gnueabi";
+ }
+ return TargetTriple.str();
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
+ return "armeb-linux-gnueabihf";
+ } else {
+ if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi"))
+ return "armeb-linux-gnueabi";
+ }
+ return TargetTriple.str();
+ case llvm::Triple::x86:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu"))
+ return "i386-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::x86_64:
+ // We don't want this for x32, otherwise it will match x86_64 libs
+ if (TargetTriple.getEnvironment() != llvm::Triple::GNUX32 &&
+ llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu"))
+ return "x86_64-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::arm64:
+ case llvm::Triple::aarch64:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
+ return "aarch64-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::arm64_be:
+ case llvm::Triple::aarch64_be:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
+ return "aarch64_be-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::mips:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu"))
+ return "mips-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::mipsel:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu"))
+ return "mipsel-linux-gnu";
+ return TargetTriple.str();
+ case llvm::Triple::mips64:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnu"))
+ return "mips64-linux-gnu";
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
+ return "mips64-linux-gnuabi64";
+ return TargetTriple.str();
+ case llvm::Triple::mips64el:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnu"))
+ return "mips64el-linux-gnu";
+ if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
+ return "mips64el-linux-gnuabi64";
+ return TargetTriple.str();
+ case llvm::Triple::ppc:
+ if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
+ return "powerpc-linux-gnuspe";
+ if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu"))
+ return "powerpc-linux-gnu";
+ return TargetTriple.str();
+ 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();
+ }
+}
+
+static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
+ if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
+}
+
+static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
+ 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 (tools::mips::hasMipsAbiArg(Args, "n32"))
+ return "lib32";
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+ }
+
+ // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, 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' library 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 oslibdir 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";
+
+ if (Triple.getArch() == llvm::Triple::x86_64 &&
+ Triple.getEnvironment() == llvm::Triple::GNUX32)
+ return "libx32";
+
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+}
+
+Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ GCCInstallation.init(D, Triple, Args);
+ Multilibs = GCCInstallation.getMultilibs();
+ llvm::Triple::ArchType Arch = Triple.getArch();
+ 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());
+
+ Linker = GetLinkerPath();
+
+ Distro Distro = DetectDistro(Arch);
+
+ if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("relro");
+ }
+
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
+ ExtraOpts.push_back("-X");
+
+ const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android;
+ const bool IsMips = isMipsArch(Arch);
+
+ if (IsMips && !SysRoot.empty())
+ ExtraOpts.push_back("--sysroot=" + SysRoot);
+
+ // Do not use 'gnu' hash style for Mips targets because .gnu.hash
+ // and the MIPS ABI require .dynsym to be sorted in different ways.
+ // .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
+ // ABI requires a mapping between the GOT and the symbol table.
+ // Android loader does not support .gnu.hash.
+ if (!IsMips && !IsAndroid) {
+ if (IsRedhat(Distro) || IsOpenSUSE(Distro) ||
+ (IsUbuntu(Distro) && Distro >= UbuntuMaverick))
+ ExtraOpts.push_back("--hash-style=gnu");
+
+ if (IsDebian(Distro) || IsOpenSUSE(Distro) || Distro == UbuntuLucid ||
+ Distro == UbuntuJaunty || Distro == UbuntuKarmic)
+ ExtraOpts.push_back("--hash-style=both");
+ }
+
+ if (IsRedhat(Distro))
+ ExtraOpts.push_back("--no-add-needed");
+
+ if (Distro == DebianSqueeze || Distro == DebianWheezy ||
+ Distro == DebianJessie || IsOpenSUSE(Distro) ||
+ (IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) ||
+ (IsUbuntu(Distro) && Distro >= UbuntuKarmic))
+ ExtraOpts.push_back("--build-id");
+
+ if (IsOpenSUSE(Distro))
+ ExtraOpts.push_back("--enable-new-dtags");
+
+ // The selection of paths to try here is designed to match the patterns which
+ // the GCC driver itself uses, as this is part of the GCC-compatible driver.
+ // This was determined by running GCC in a fake filesystem, creating all
+ // possible permutations of these directories, and seeing which ones it added
+ // to the link paths.
+ path_list &Paths = getFilePaths();
+
+ const std::string OSLibDir = getOSLibDir(Triple, Args);
+ const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot);
+
+ // Add the multilib suffixed paths where they are available.
+ if (GCCInstallation.isValid()) {
+ const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+ const std::string &LibPath = GCCInstallation.getParentLibPath();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+
+ // Sourcery CodeBench MIPS toolchain holds some libraries under
+ // a biarch-like suffix of the GCC installation.
+ addPathIfExists((GCCInstallation.getInstallPath() +
+ Multilib.gccSuffix()),
+ 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 targeting 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/../" + OSLibDir +
+ Multilib.osSuffix(),
+ 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.
+ // It is important to *not* use these paths when the GCC installation is
+ // 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. 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 + "/" + MultiarchTriple, Paths);
+ addPathIfExists(LibPath + "/../" + OSLibDir, Paths);
+ }
+ }
+
+ // Similar to the logic for GCC above, if we currently running Clang inside
+ // of the requested system root, add its parent library paths to
+ // those searched.
+ // FIXME: It's not clear whether we should use the driver's installed
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot)) {
+ addPathIfExists(D.Dir + "/../lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D.Dir + "/../" + OSLibDir, Paths);
+ }
+
+ addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths);
+ addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+
+ // Try walking via the GCC triple path in case of biarch or multiarch GCC
+ // installations with strange symlinks.
+ if (GCCInstallation.isValid()) {
+ addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+ "/../../" + OSLibDir, Paths);
+
+ // Add the 'other' biarch variant path
+ Multilib BiarchSibling;
+ if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
+ addPathIfExists(GCCInstallation.getInstallPath() +
+ BiarchSibling.gccSuffix(), Paths);
+ }
+
+ // See comments above on the multilib variant for details of why this is
+ // included even from outside the sysroot.
+ const std::string &LibPath = GCCInstallation.getParentLibPath();
+ const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ addPathIfExists(LibPath + "/../" + GCCTriple.str() +
+ "/lib" + Multilib.osSuffix(), 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);
+ }
+
+ // Similar to the logic for GCC above, if we are currently running Clang
+ // inside of the requested system root, add its parent library path to those
+ // searched.
+ // FIXME: It's not clear whether we should use the driver's installed
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot))
+ addPathIfExists(D.Dir + "/../lib", Paths);
+
+ addPathIfExists(SysRoot + "/lib", Paths);
+ addPathIfExists(SysRoot + "/usr/lib", Paths);
+}
+
+bool Linux::HasNativeLLVMSupport() const {
+ return true;
+}
+
+Tool *Linux::buildLinker() const {
+ return new tools::gnutools::Link(*this);
+}
+
+Tool *Linux::buildAssembler() const {
+ return new tools::gnutools::Assemble(*this);
+}
+
+std::string Linux::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ if (!GCCInstallation.isValid() || !isMipsArch(getTriple().getArch()))
+ return std::string();
+
+ // 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 Multilib &Multilib = GCCInstallation.getMultilib();
+
+ std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" +
+ Multilib.osSuffix()).str();
+
+ if (llvm::sys::fs::exists(Path))
+ return Path;
+
+ Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str();
+
+ if (llvm::sys::fs::exists(Path))
+ return Path;
+
+ return std::string();
+}
+
+void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+ addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix = llvm::sys::path::is_absolute(dir) ? SysRoot : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+
+ // Lacking those, try to detect the correct set of system includes for the
+ // target triple.
+
+ // Sourcery CodeBench and modern FSF Mips toolchains put extern C
+ // system includes under three additional directories.
+ if (GCCInstallation.isValid() && isMipsArch(getTriple().getArch())) {
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args, GCCInstallation.getInstallPath() + "/include");
+
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() + "/../../../../" +
+ GCCInstallation.getTriple().str() + "/libc/usr/include");
+
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() + "/../../../../sysroot/usr/include");
+ }
+
+ // Implement generic Debian multiarch support.
+ const StringRef X86_64MultiarchIncludeDirs[] = {
+ "/usr/include/x86_64-linux-gnu",
+
+ // 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"
+ };
+ const StringRef X86MultiarchIncludeDirs[] = {
+ "/usr/include/i386-linux-gnu",
+
+ // 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/i486-linux-gnu"
+ };
+ const StringRef AArch64MultiarchIncludeDirs[] = {
+ "/usr/include/aarch64-linux-gnu"
+ };
+ const StringRef ARMMultiarchIncludeDirs[] = {
+ "/usr/include/arm-linux-gnueabi"
+ };
+ const StringRef ARMHFMultiarchIncludeDirs[] = {
+ "/usr/include/arm-linux-gnueabihf"
+ };
+ const StringRef MIPSMultiarchIncludeDirs[] = {
+ "/usr/include/mips-linux-gnu"
+ };
+ const StringRef MIPSELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsel-linux-gnu"
+ };
+ const StringRef MIPS64MultiarchIncludeDirs[] = {
+ "/usr/include/mips64-linux-gnu",
+ "/usr/include/mips64-linux-gnuabi64"
+ };
+ const StringRef MIPS64ELMultiarchIncludeDirs[] = {
+ "/usr/include/mips64el-linux-gnu",
+ "/usr/include/mips64el-linux-gnuabi64"
+ };
+ const StringRef PPCMultiarchIncludeDirs[] = {
+ "/usr/include/powerpc-linux-gnu"
+ };
+ const StringRef PPC64MultiarchIncludeDirs[] = {
+ "/usr/include/powerpc64-linux-gnu"
+ };
+ const StringRef PPC64LEMultiarchIncludeDirs[] = {
+ "/usr/include/powerpc64le-linux-gnu"
+ };
+ ArrayRef<StringRef> MultiarchIncludeDirs;
+ if (getTriple().getArch() == llvm::Triple::x86_64) {
+ MultiarchIncludeDirs = X86_64MultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::x86) {
+ MultiarchIncludeDirs = X86MultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getTriple().getArch() == llvm::Triple::arm64 ||
+ getTriple().getArch() == llvm::Triple::arm64_be) {
+ MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::arm) {
+ if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::mips) {
+ MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::mipsel) {
+ MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::mips64) {
+ MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::mips64el) {
+ MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::ppc) {
+ MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::ppc64) {
+ MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
+ } else if (getTriple().getArch() == llvm::Triple::ppc64le) {
+ MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs;
+ }
+ for (StringRef Dir : MultiarchIncludeDirs) {
+ if (llvm::sys::fs::exists(SysRoot + Dir)) {
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
+ break;
+ }
+ }
+
+ if (getTriple().getOS() == llvm::Triple::RTEMS)
+ return;
+
+ // Add an include of '/include' directly. This isn't provided by default by
+ // system GCCs, but is often used with cross-compiling GCCs, and harmless to
+ // add even when Clang is acting as-if it were a system compiler.
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+}
+
+/// \brief Helper to add the variant paths of a libstdc++ installation.
+/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
+ StringRef GCCTriple,
+ StringRef GCCMultiarchTriple,
+ StringRef TargetMultiarchTriple,
+ Twine IncludeSuffix,
+ const ArgList &DriverArgs,
+ ArgStringList &CC1Args) {
+ if (!llvm::sys::fs::exists(Base + Suffix))
+ return false;
+
+ addSystemInclude(DriverArgs, CC1Args, Base + Suffix);
+
+ // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If
+ // that path exists or we have neither a GCC nor target multiarch triple, use
+ // this vanilla search path.
+ if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
+ llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + Suffix + "/" + GCCTriple + IncludeSuffix);
+ } else {
+ // Otherwise try to use multiarch naming schemes which have normalized the
+ // triples and put the triple before the suffix.
+ //
+ // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
+ // the target triple, so we support that here.
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + "/" + TargetMultiarchTriple + Suffix);
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
+ return true;
+}
+
+void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ // Check if libc++ has been enabled and provide its include paths if so.
+ if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
+ const std::string LibCXXIncludePathCandidates[] = {
+ // The primary location is within the Clang installation.
+ // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
+ // newer ABI versions.
+ getDriver().Dir + "/../include/c++/v1",
+
+ // We also check the system as for a long time this is the only place Clang looked.
+ // FIXME: We should really remove this. It doesn't make any sense.
+ getDriver().SysRoot + "/usr/include/c++/v1"
+ };
+ for (const auto &IncludePath : LibCXXIncludePathCandidates) {
+ if (!llvm::sys::fs::exists(IncludePath))
+ continue;
+ // Add the first candidate that exists.
+ addSystemInclude(DriverArgs, CC1Args, IncludePath);
+ break;
+ }
+ return;
+ }
+
+ // We need a detected GCC installation on Linux to provide libstdc++'s
+ // headers. We handled the libc++ case above.
+ if (!GCCInstallation.isValid())
+ return;
+
+ // By default, look for the C++ headers in an include directory adjacent to
+ // the lib directory of the GCC installation. Note that this is expect to be
+ // equivalent to '/usr/include/c++/X.Y' in almost all cases.
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef InstallDir = GCCInstallation.getInstallPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ const std::string GCCMultiarchTriple =
+ getMultiarchTriple(GCCInstallation.getTriple(), getDriver().SysRoot);
+ const std::string TargetMultiarchTriple =
+ getMultiarchTriple(getTriple(), getDriver().SysRoot);
+ const GCCVersion &Version = GCCInstallation.getVersion();
+
+ // The primary search for libstdc++ supports multiarch variants.
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+ "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple,
+ TargetMultiarchTriple,
+ Multilib.includeSuffix(), DriverArgs, CC1Args))
+ return;
+
+ // Otherwise, fall back on a bunch of options which don't use multiarch
+ // layouts for simplicity.
+ const std::string LibStdCXXIncludePathCandidates[] = {
+ // Gentoo is weird and places its headers inside the GCC install, so if the
+ // 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.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 (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
+ if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
+ /*GCCMultiarchTriple*/ "",
+ /*TargetMultiarchTriple*/ "",
+ Multilib.includeSuffix(), DriverArgs, CC1Args))
+ break;
+ }
+}
+
+bool Linux::isPIEDefault() const {
+ return getSanitizerArgs().hasZeroBaseShadow();
+}
+
+/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
+
+DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ // Path mangling to find libexec
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
+ getFilePaths().push_back(getDriver().Dir + "/../lib");
+ getFilePaths().push_back("/usr/lib");
+ if (llvm::sys::fs::exists("/usr/lib/gcc47"))
+ getFilePaths().push_back("/usr/lib/gcc47");
+ else
+ getFilePaths().push_back("/usr/lib/gcc44");
+}
+
+Tool *DragonFly::buildAssembler() const {
+ return new tools::dragonfly::Assemble(*this);
+}
+
+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
new file mode 100644
index 0000000..b5df866
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h
@@ -0,0 +1,782 @@
+//===--- ToolChains.h - ToolChain Implementations ---------------*- 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_TOOLCHAINS_H_
+#define CLANG_LIB_DRIVER_TOOLCHAINS_H_
+
+#include "Tools.h"
+#include "clang/Basic/VersionTuple.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Multilib.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include <set>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+/// Generic_GCC - A tool chain using the 'gcc' command to perform
+/// all subcommands; this relies on gcc translating the majority of
+/// command line options.
+class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
+protected:
+ /// \brief Struct to store and manipulate GCC versions.
+ ///
+ /// We rely on assumptions about the form and structure of GCC version
+ /// numbers: they consist of at most three '.'-separated components, and each
+ /// component is a non-negative integer except for the last component. For
+ /// the last component we are very flexible in order to tolerate release
+ /// candidates or 'x' wildcards.
+ ///
+ /// Note that the ordering established among GCCVersions is based on the
+ /// preferred version string to use. For example we prefer versions without
+ /// a hard-coded patch number to those with a hard coded patch number.
+ ///
+ /// Currently this doesn't provide any logic for textual suffixes to patches
+ /// in the way that (for example) Debian's version format does. If that ever
+ /// becomes necessary, it can be added.
+ struct GCCVersion {
+ /// \brief The unparsed text of the version.
+ std::string Text;
+
+ /// \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 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); }
+ };
+
+ /// \brief This is a class to find a viable GCC installation for Clang to
+ /// use.
+ ///
+ /// This class tries to find a GCC installation on the system, and report
+ /// 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;
+ llvm::Triple GCCTriple;
+
+ // FIXME: These might be better as path objects.
+ std::string GCCInstallPath;
+ std::string GCCParentLibPath;
+
+ /// The primary multilib appropriate for the given flags.
+ Multilib SelectedMultilib;
+ /// On Biarch systems, this corresponds to the default multilib when
+ /// targeting the non-default multilib. Otherwise, it is empty.
+ llvm::Optional<Multilib> BiarchSibling;
+
+ 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;
+
+ /// The set of multilibs that the detected installation supports.
+ MultilibSet Multilibs;
+
+ public:
+ GCCInstallationDetector() : IsValid(false) {}
+ void init(const Driver &D, const llvm::Triple &TargetTriple,
+ const llvm::opt::ArgList &Args);
+
+ /// \brief Check whether we detected a valid GCC install.
+ bool isValid() const { return IsValid; }
+
+ /// \brief Get the GCC triple for the detected install.
+ const llvm::Triple &getTriple() const { return GCCTriple; }
+
+ /// \brief Get the detected GCC installation path.
+ StringRef getInstallPath() const { return GCCInstallPath; }
+
+ /// \brief Get the detected GCC parent lib path.
+ StringRef getParentLibPath() const { return GCCParentLibPath; }
+
+ /// \brief Get the detected Multilib
+ const Multilib &getMultilib() const { return SelectedMultilib; }
+
+ /// \brief Get the whole MultilibSet
+ const MultilibSet &getMultilibs() const { return Multilibs; }
+
+ /// Get the biarch sibling multilib (if it exists).
+ /// \return true iff such a sibling exists
+ bool getBiarchSibling(Multilib &M) const;
+
+ /// \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 &BiarchTriple,
+ SmallVectorImpl<StringRef> &LibDirs,
+ SmallVectorImpl<StringRef> &TripleAliases,
+ SmallVectorImpl<StringRef> &BiarchLibDirs,
+ SmallVectorImpl<StringRef> &BiarchTripleAliases);
+
+ void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
+ const llvm::opt::ArgList &Args,
+ const std::string &LibDir,
+ StringRef CandidateTriple,
+ bool NeedsBiarchSuffix = false);
+ };
+
+ GCCInstallationDetector GCCInstallation;
+
+public:
+ Generic_GCC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~Generic_GCC();
+
+ void printVerboseInfo(raw_ostream &OS) const override;
+
+ bool IsUnwindTablesDefault() const override;
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+ bool IsIntegratedAssemblerDefault() const override;
+
+protected:
+ Tool *getTool(Action::ActionClass AC) const override;
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+ /// \name ToolChain Implementation Helper Functions
+ /// @{
+
+ /// \brief Check whether the target triple's architecture is 64-bits.
+ bool isTarget64Bit() const { return getTriple().isArch64Bit(); }
+
+ /// \brief Check whether the target triple's architecture is 32-bits.
+ bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
+
+ /// @}
+
+private:
+ mutable std::unique_ptr<tools::gcc::Preprocess> Preprocess;
+ mutable std::unique_ptr<tools::gcc::Compile> Compile;
+};
+
+class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+ Tool *getTool(Action::ActionClass AC) const override;
+private:
+ mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
+ mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
+ mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
+
+public:
+ MachO(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~MachO();
+
+ /// @name MachO specific toolchain API
+ /// {
+
+ /// Get the "MachO" arch name for a particular compiler invocation. For
+ /// example, Apple treats different ARM variations as distinct architectures.
+ StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
+
+
+ /// Add the linker arguments to link the ARC runtime library.
+ virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {}
+
+ /// Add the linker arguments to link the compiler runtime library.
+ virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ virtual void
+ addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {}
+
+ virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {}
+
+ /// On some iOS platforms, kernel and kernel modules were built statically. Is
+ /// this such a target?
+ virtual bool isKernelStatic() const {
+ return false;
+ }
+
+ /// Is the target either iOS or an iOS simulator?
+ bool isTargetIOSBased() const {
+ return false;
+ }
+
+ void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ StringRef DarwinStaticLib,
+ bool AlwaysLink = false,
+ bool IsEmbedded = false) const;
+
+ /// }
+ /// @name ToolChain Implementation
+ /// {
+
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+
+ types::ID LookupTypeForExtension(const char *Ext) const override;
+
+ bool HasNativeLLVMSupport() const override;
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const override;
+
+ bool IsBlocksDefault() const override {
+ // Always allow blocks on Apple; users interested in versioning are
+ // expected to use /usr/include/Blocks.h.
+ return true;
+ }
+ bool IsIntegratedAssemblerDefault() const override {
+ // Default integrated assembler to on for Apple's MachO targets.
+ return true;
+ }
+
+ bool IsMathErrnoDefault() const override {
+ return false;
+ }
+
+ bool IsEncodeExtendedBlockSignatureDefault() const override {
+ return true;
+ }
+
+ bool IsObjCNonFragileABIDefault() const override {
+ // Non-fragile ABI is default for everything but i386.
+ return getTriple().getArch() != llvm::Triple::x86;
+ }
+
+ bool UseObjCMixedDispatch() const override {
+ return true;
+ }
+
+ bool IsUnwindTablesDefault() const override;
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+
+ bool SupportsProfiling() const override;
+
+ bool SupportsObjCGC() const override {
+ return false;
+ }
+
+ bool UseDwarfDebugFlags() const override;
+
+ bool UseSjLjExceptions() const override {
+ return false;
+ }
+
+ /// }
+};
+
+ /// Darwin - The base Darwin tool chain.
+class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
+public:
+ /// The host version.
+ unsigned DarwinVersion[3];
+
+ /// Whether the information on the target has been initialized.
+ //
+ // FIXME: This should be eliminated. What we want to do is make this part of
+ // the "default target for arguments" selection process, once we get out of
+ // the argument translation business.
+ mutable bool TargetInitialized;
+
+ enum DarwinPlatformKind {
+ MacOS,
+ IPhoneOS,
+ IPhoneOSSimulator
+ };
+
+ mutable DarwinPlatformKind TargetPlatform;
+
+ /// The OS version we are targeting.
+ mutable VersionTuple TargetVersion;
+
+private:
+ /// The default macosx-version-min of this tool chain; empty until
+ /// initialized.
+ std::string MacosxVersionMin;
+
+ /// The default ios-version-min of this tool chain; empty until
+ /// initialized.
+ std::string iOSVersionMin;
+
+private:
+ void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
+
+public:
+ Darwin(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~Darwin();
+
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+
+ /// @name Apple Specific Toolchain Implementation
+ /// {
+
+ void
+ addMinVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ void
+ addStartObjectFileArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ bool isKernelStatic() const override {
+ return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0) ||
+ getTriple().getArch() == llvm::Triple::arm64;
+ }
+
+protected:
+ /// }
+ /// @name Darwin specific Toolchain functions
+ /// {
+
+ // FIXME: Eliminate these ...Target functions and derive separate tool chains
+ // for these targets and put version in constructor.
+ void setTarget(DarwinPlatformKind Platform, unsigned Major, unsigned Minor,
+ unsigned Micro) const {
+ // FIXME: For now, allow reinitialization as long as values don't
+ // change. This will go away when we move away from argument translation.
+ if (TargetInitialized && TargetPlatform == Platform &&
+ TargetVersion == VersionTuple(Major, Minor, Micro))
+ return;
+
+ assert(!TargetInitialized && "Target already initialized!");
+ TargetInitialized = true;
+ TargetPlatform = Platform;
+ TargetVersion = VersionTuple(Major, Minor, Micro);
+ }
+
+ bool isTargetIPhoneOS() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == IPhoneOS;
+ }
+
+ bool isTargetIOSSimulator() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == IPhoneOSSimulator;
+ }
+
+ bool isTargetIOSBased() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return isTargetIPhoneOS() || isTargetIOSSimulator();
+ }
+
+ bool isTargetMacOS() const {
+ return TargetPlatform == MacOS;
+ }
+
+ bool isTargetInitialized() const { return TargetInitialized; }
+
+ VersionTuple getTargetVersion() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetVersion;
+ }
+
+ bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
+ return TargetVersion < VersionTuple(V0, V1, V2);
+ }
+
+ bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
+ assert(isTargetMacOS() && "Unexpected call for non OS X target!");
+ return TargetVersion < VersionTuple(V0, V1, V2);
+ }
+
+public:
+ /// }
+ /// @name ToolChain Implementation
+ /// {
+
+ // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
+ // most development is done against SDKs, so compiling for a different
+ // architecture should not get any special treatment.
+ bool isCrossCompiling() const override { return false; }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const override;
+
+ ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
+ bool hasBlocksRuntime() const override;
+
+ bool UseObjCMixedDispatch() const override {
+ // This is only used with the non-fragile ABI and non-legacy dispatch.
+
+ // Mixed dispatch is used everywhere except OS X before 10.6.
+ return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
+ }
+
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ // Stack protectors default to on for user code on 10.5,
+ // and for everything in 10.6 and beyond
+ if (isTargetIOSBased())
+ return 1;
+ else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
+ return 1;
+ else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
+ return 1;
+
+ return 0;
+ }
+
+ bool SupportsObjCGC() const override;
+
+ void CheckObjCARC() const override;
+
+ bool UseSjLjExceptions() const override;
+};
+
+/// DarwinClang - The Darwin toolchain used by Clang.
+class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
+public:
+ DarwinClang(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ /// @name Apple ToolChain Implementation
+ /// {
+
+ void
+ AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ void
+ AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ void
+ AddCCKextLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
+
+ void
+ AddLinkARCArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ /// }
+};
+
+class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC {
+ virtual void anchor();
+public:
+ Generic_ELF(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {}
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC {
+public:
+ AuroraUX(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC {
+public:
+ Solaris(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsIntegratedAssemblerDefault() const override { return true; }
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+};
+
+
+class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
+public:
+ OpenBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+ bool isPIEDefault() const override { return true; }
+
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return 2;
+ }
+
+ virtual bool IsIntegratedAssemblerDefault() const override {
+ if (getTriple().getArch() == llvm::Triple::ppc ||
+ getTriple().getArch() == llvm::Triple::sparc ||
+ getTriple().getArch() == llvm::Triple::sparcv9)
+ return true;
+ return Generic_ELF::IsIntegratedAssemblerDefault();
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF {
+public:
+ Bitrig(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return 1;
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
+public:
+ FreeBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ bool HasNativeLLVMSupport() const override;
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ bool IsIntegratedAssemblerDefault() const override {
+ if (getTriple().getArch() == llvm::Triple::ppc ||
+ getTriple().getArch() == llvm::Triple::ppc64)
+ return true;
+ return Generic_ELF::IsIntegratedAssemblerDefault();
+ }
+
+ bool UseSjLjExceptions() const override;
+ bool isPIEDefault() const override;
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF {
+public:
+ NetBSD(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ bool IsUnwindTablesDefault() const override {
+ return true;
+ }
+ bool IsIntegratedAssemblerDefault() const override {
+ if (getTriple().getArch() == llvm::Triple::ppc)
+ return true;
+ return Generic_ELF::IsIntegratedAssemblerDefault();
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
+public:
+ Minix(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF {
+public:
+ DragonFly(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsMathErrnoDefault() const override { return false; }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
+public:
+ Linux(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool HasNativeLLVMSupport() const override;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ bool isPIEDefault() const override;
+
+ std::string Linker;
+ std::vector<std::string> ExtraOpts;
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+private:
+ static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
+ StringRef GCCTriple,
+ StringRef GCCMultiarchTriple,
+ StringRef TargetMultiarchTriple,
+ Twine IncludeSuffix,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args);
+
+ std::string computeSysRoot() const;
+};
+
+class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux {
+protected:
+ GCCVersion GCCLibAndIncVersion;
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+public:
+ Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~Hexagon_TC();
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
+
+ static std::string GetGnuDir(const std::string &InstalledDir);
+
+ 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 llvm::opt::ArgList &Args);
+ ~TCEToolChain();
+
+ bool IsMathErrnoDefault() const override;
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
+public:
+ Windows(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool IsIntegratedAssemblerDefault() const override;
+ bool IsUnwindTablesDefault() const override;
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+ Tool *buildLinker() const override;
+ Tool *buildAssembler() const override;
+};
+
+
+class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain {
+public:
+ XCore(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+public:
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+ bool SupportsProfiling() const override;
+ bool hasBlocksRuntime() const override;
+ void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
new file mode 100644
index 0000000..89db52e
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -0,0 +1,8013 @@
+//===--- Tools.cpp - Tools Implementations --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "InputInfo.h"
+#include "ToolChains.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Version.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Util.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/Compression.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/Process.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static void addAssemblerKPIC(const ArgList &Args, ArgStringList &CmdArgs) {
+ 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)
+ return;
+ if (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");
+ }
+}
+
+/// 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) && !Args.hasArg(options::OPT__SLASH_P) &&
+ !Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << A->getBaseArg().getAsString(Args)
+ << (D.IsCLMode() ? "/E, /P or /EP" : "-E");
+ }
+ }
+}
+
+/// CheckCodeGenerationOptions - Perform some validation of code generation
+/// arguments that is shared with gcc.
+static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
+ // In gcc, only ARM checks this, but it seems reasonable to check universally.
+ if (Args.hasArg(options::OPT_static))
+ if (const Arg *A = Args.getLastArg(options::OPT_dynamic,
+ options::OPT_mdynamic_no_pic))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-static";
+}
+
+// Quote target names for inclusion in GNU Make dependency files.
+// Only the characters '$', '#', ' ', '\t' are quoted.
+static void QuoteTarget(StringRef Target,
+ SmallVectorImpl<char> &Res) {
+ for (unsigned i = 0, e = Target.size(); i != e; ++i) {
+ switch (Target[i]) {
+ case ' ':
+ case '\t':
+ // Escape the preceding backslashes
+ for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
+ Res.push_back('\\');
+
+ // Escape the space/tab
+ Res.push_back('\\');
+ break;
+ case '$':
+ Res.push_back('$');
+ break;
+ case '#':
+ Res.push_back('\\');
+ break;
+ default:
+ break;
+ }
+
+ Res.push_back(Target[i]);
+ }
+}
+
+static void addDirectoryList(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *ArgName,
+ const char *EnvVar) {
+ const char *DirList = ::getenv(EnvVar);
+ bool CombinedArg = false;
+
+ if (!DirList)
+ return; // Nothing to do.
+
+ StringRef Name(ArgName);
+ if (Name.equals("-I") || Name.equals("-L"))
+ CombinedArg = true;
+
+ StringRef Dirs(DirList);
+ if (Dirs.empty()) // Empty string should not add '.'.
+ return;
+
+ StringRef::size_type Delim;
+ while ((Delim = Dirs.find(llvm::sys::EnvPathSeparator)) != StringRef::npos) {
+ if (Delim == 0) { // Leading colon.
+ if (CombinedArg) {
+ CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
+ } else {
+ CmdArgs.push_back(ArgName);
+ CmdArgs.push_back(".");
+ }
+ } else {
+ if (CombinedArg) {
+ CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs.substr(0, Delim)));
+ } else {
+ CmdArgs.push_back(ArgName);
+ CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim)));
+ }
+ }
+ Dirs = Dirs.substr(Delim + 1);
+ }
+
+ if (Dirs.empty()) { // Trailing colon.
+ if (CombinedArg) {
+ CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + "."));
+ } else {
+ CmdArgs.push_back(ArgName);
+ CmdArgs.push_back(".");
+ }
+ } else { // Add the last path.
+ if (CombinedArg) {
+ CmdArgs.push_back(Args.MakeArgString(std::string(ArgName) + Dirs));
+ } else {
+ CmdArgs.push_back(ArgName);
+ CmdArgs.push_back(Args.MakeArgString(Dirs));
+ }
+ }
+}
+
+static void AddLinkerInputs(const ToolChain &TC,
+ const InputInfoList &Inputs, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+
+ // Add extra linker input arguments which are not treated as inputs
+ // (constructed via -Xarch_).
+ Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
+
+ for (const auto &II : Inputs) {
+ if (!TC.HasNativeLLVMSupport()) {
+ // Don't try to pass LLVM inputs unless we have native support.
+ if (II.getType() == types::TY_LLVM_IR ||
+ II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC ||
+ II.getType() == types::TY_LTO_BC)
+ D.Diag(diag::err_drv_no_linker_llvm_support)
+ << TC.getTripleString();
+ }
+
+ // Add filenames immediately.
+ if (II.isFilename()) {
+ CmdArgs.push_back(II.getFilename());
+ continue;
+ }
+
+ // Otherwise, this is a linker input argument.
+ const Arg &A = II.getInputArg();
+
+ // Handle reserved library options.
+ if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx))
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
+ TC.AddCCKextLibArgs(Args, CmdArgs);
+ else if (A.getOption().matches(options::OPT_z)) {
+ // Pass -z prefix for gcc linker compatibility.
+ A.claim();
+ A.render(Args, CmdArgs);
+ } else {
+ A.renderAsInput(Args, CmdArgs);
+ }
+ }
+
+ // LIBRARY_PATH - included following the user specified library paths.
+ // and only supported on native toolchains.
+ if (!TC.isCrossCompiling())
+ addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
+}
+
+/// \brief Determine whether Objective-C automated reference counting is
+/// enabled.
+static bool isObjCAutoRefCount(const ArgList &Args) {
+ return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
+}
+
+/// \brief Determine whether we are linking the ObjC runtime.
+static bool isObjCRuntimeLinked(const ArgList &Args) {
+ if (isObjCAutoRefCount(Args)) {
+ Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
+ return true;
+ }
+ return Args.hasArg(options::OPT_fobjc_link_runtime);
+}
+
+static bool forwardToGCC(const Option &O) {
+ // 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);
+}
+
+void Clang::AddPreprocessingOptions(Compilation &C,
+ const JobAction &JA,
+ const Driver &D,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs) const {
+ Arg *A;
+
+ CheckPreprocessingOptions(D, Args);
+
+ Args.AddLastArg(CmdArgs, options::OPT_C);
+ Args.AddLastArg(CmdArgs, options::OPT_CC);
+
+ // Handle dependency file generation.
+ if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
+ (A = Args.getLastArg(options::OPT_MD)) ||
+ (A = Args.getLastArg(options::OPT_MMD))) {
+ // Determine the output location.
+ const char *DepFile;
+ if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
+ DepFile = MF->getValue();
+ C.addFailureResultFile(DepFile, &JA);
+ } else if (Output.getType() == types::TY_Dependencies) {
+ DepFile = Output.getFilename();
+ } else if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MM)) {
+ DepFile = "-";
+ } else {
+ DepFile = getDependencyFileName(Args, Inputs);
+ C.addFailureResultFile(DepFile, &JA);
+ }
+ CmdArgs.push_back("-dependency-file");
+ CmdArgs.push_back(DepFile);
+
+ // Add a default target if one wasn't specified.
+ if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
+ const char *DepTarget;
+
+ // If user provided -o, that is the dependency target, except
+ // when we are only generating a dependency file.
+ Arg *OutputOpt = Args.getLastArg(options::OPT_o);
+ if (OutputOpt && Output.getType() != types::TY_Dependencies) {
+ DepTarget = OutputOpt->getValue();
+ } else {
+ // Otherwise derive from the base input.
+ //
+ // FIXME: This should use the computed output file location.
+ SmallString<128> P(Inputs[0].getBaseInput());
+ llvm::sys::path::replace_extension(P, "o");
+ DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
+ }
+
+ CmdArgs.push_back("-MT");
+ SmallString<128> Quoted;
+ QuoteTarget(DepTarget, Quoted);
+ CmdArgs.push_back(Args.MakeArgString(Quoted));
+ }
+
+ if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MD))
+ CmdArgs.push_back("-sys-header-deps");
+
+ if (isa<PrecompileJobAction>(JA))
+ CmdArgs.push_back("-module-file-deps");
+ }
+
+ if (Args.hasArg(options::OPT_MG)) {
+ if (!A || A->getOption().matches(options::OPT_MD) ||
+ A->getOption().matches(options::OPT_MMD))
+ D.Diag(diag::err_drv_mg_requires_m_or_mm);
+ CmdArgs.push_back("-MG");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_MP);
+
+ // Convert all -MQ <target> args to -MT <quoted target>
+ for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
+ options::OPT_MQ),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = *it;
+ A->claim();
+
+ if (A->getOption().matches(options::OPT_MQ)) {
+ CmdArgs.push_back("-MT");
+ SmallString<128> Quoted;
+ QuoteTarget(A->getValue(), Quoted);
+ CmdArgs.push_back(Args.MakeArgString(Quoted));
+
+ // -MT flag - no change
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ // Add -i* options, and automatically translate to
+ // -include-pch/-include-pth for transparent PCH support. It's
+ // wonky, but we include looking for .gch so we can support seamless
+ // replacement into a build system already set up to be generating
+ // .gch files.
+ bool RenderedImplicitInclude = false;
+ for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ const Arg *A = it;
+
+ if (A->getOption().matches(options::OPT_include)) {
+ bool IsFirstImplicitInclude = !RenderedImplicitInclude;
+ RenderedImplicitInclude = true;
+
+ // Use PCH if the user requested it.
+ bool UsePCH = D.CCCUsePCH;
+
+ bool FoundPTH = false;
+ bool FoundPCH = false;
+ 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) {
+ llvm::sys::path::replace_extension(P, "pch");
+ if (llvm::sys::fs::exists(P.str()))
+ FoundPCH = true;
+ }
+
+ if (!FoundPCH) {
+ llvm::sys::path::replace_extension(P, "pth");
+ if (llvm::sys::fs::exists(P.str()))
+ FoundPTH = true;
+ }
+
+ if (!FoundPCH && !FoundPTH) {
+ llvm::sys::path::replace_extension(P, "gch");
+ if (llvm::sys::fs::exists(P.str())) {
+ FoundPCH = UsePCH;
+ FoundPTH = !UsePCH;
+ }
+ }
+
+ if (FoundPCH || FoundPTH) {
+ if (IsFirstImplicitInclude) {
+ A->claim();
+ if (UsePCH)
+ CmdArgs.push_back("-include-pch");
+ else
+ CmdArgs.push_back("-include-pth");
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ continue;
+ } else {
+ // Ignore the PCH if not first on command line and emit warning.
+ D.Diag(diag::warn_drv_pch_not_first_include)
+ << P.str() << A->getAsString(Args);
+ }
+ }
+ }
+
+ // Not translated, render as usual.
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+ Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F,
+ options::OPT_index_header_map);
+
+ // Add -Wp, and -Xassembler if using the preprocessor.
+
+ // FIXME: There is a very unfortunate problem here, some troubled
+ // souls abuse -Wp, to pass preprocessor options in gcc syntax. To
+ // really support that we would have to parse and then translate
+ // those options. :(
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
+ options::OPT_Xpreprocessor);
+
+ // -I- is a deprecated GCC feature, reject it.
+ if (Arg *A = Args.getLastArg(options::OPT_I_))
+ D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
+
+ // If we have a --sysroot, and don't have an explicit -isysroot flag, add an
+ // -isysroot to the CC1 invocation.
+ StringRef sysroot = C.getSysRoot();
+ if (sysroot != "") {
+ if (!Args.hasArg(options::OPT_isysroot)) {
+ CmdArgs.push_back("-isysroot");
+ CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
+ }
+ }
+
+ // Parse additional include paths from environment variables.
+ // FIXME: We should probably sink the logic for handling these from the
+ // frontend into the driver. It will allow deleting 4 otherwise unused flags.
+ // CPATH - included following the user specified includes (but prior to
+ // builtin and standard includes).
+ addDirectoryList(Args, CmdArgs, "-I", "CPATH");
+ // C_INCLUDE_PATH - system includes enabled when compiling C.
+ addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH");
+ // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
+ addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH");
+ // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
+ addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH");
+ // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
+ addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");
+
+ // Add C++ include arguments, if needed.
+ if (types::isCXX(Inputs[0].getType()))
+ getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+
+ // Add system include arguments.
+ getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
+}
+
+// FIXME: Move to target hook.
+static bool isSignedCharDefault(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return true;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ if (Triple.isOSDarwin() || Triple.isOSWindows())
+ return true;
+ return false;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ if (Triple.isOSDarwin())
+ 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 -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 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.
+ Features.push_back("-vfp2");
+ Features.push_back("-vfp3");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp") {
+ Features.push_back("+vfp2");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") {
+ Features.push_back("+vfp3");
+ Features.push_back("+d16");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp3" || FPU == "vfpv3") {
+ Features.push_back("+vfp3");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") {
+ Features.push_back("+vfp4");
+ Features.push_back("+d16");
+ Features.push_back("-neon");
+ } else if (FPU == "vfp4" || FPU == "vfpv4") {
+ Features.push_back("+vfp4");
+ Features.push_back("-neon");
+ } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") {
+ Features.push_back("+vfp4");
+ Features.push_back("+d16");
+ Features.push_back("+fp-only-sp");
+ 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") {
+ 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);
+}
+
+// Select the float ABI as determined by -msoft-float, -mhard-float, and
+// -mfloat-abi=.
+StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ else {
+ FloatABI = A->getValue();
+ if (FloatABI != "soft" && FloatABI != "softfp" && FloatABI != "hard") {
+ D.Diag(diag::err_drv_invalid_mfloat_abi)
+ << A->getAsString(Args);
+ FloatABI = "soft";
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ switch (Triple.getOS()) {
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS: {
+ // Darwin defaults to "softfp" for v6 and v7.
+ //
+ // FIXME: Factor out an ARM class so we can cache the arch somewhere.
+ std::string ArchName =
+ arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
+ if (StringRef(ArchName).startswith("v6") ||
+ StringRef(ArchName).startswith("v7"))
+ FloatABI = "softfp";
+ else
+ FloatABI = "soft";
+ break;
+ }
+
+ // FIXME: this is invalid for WindowsCE
+ case llvm::Triple::Win32:
+ FloatABI = "hard";
+ break;
+
+ case llvm::Triple::FreeBSD:
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ FloatABI = "hard";
+ break;
+ default:
+ // FreeBSD defaults to soft float
+ FloatABI = "soft";
+ break;
+ }
+ break;
+
+ default:
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ FloatABI = "hard";
+ break;
+ case llvm::Triple::GNUEABI:
+ FloatABI = "softfp";
+ break;
+ case llvm::Triple::EABIHF:
+ FloatABI = "hard";
+ break;
+ case llvm::Triple::EABI:
+ // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
+ FloatABI = "softfp";
+ break;
+ case llvm::Triple::Android: {
+ std::string ArchName =
+ arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple));
+ if (StringRef(ArchName).startswith("v7"))
+ FloatABI = "softfp";
+ else
+ FloatABI = "soft";
+ break;
+ }
+ default:
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ !Triple.isOSBinFormatMachO())
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ break;
+ }
+ }
+ }
+
+ return FloatABI;
+}
+
+static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features,
+ bool ForAS) {
+ StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
+ if (!ForAS) {
+ // 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. We should probably pass this a new
+ // -target-option, which is handled by the -cc1/-cc1as invocation.
+ //
+ // FIXME2: For consistency, it would be ideal if we set up the target
+ // machine state the same when using the frontend or the assembler. We don't
+ // currently do that for the assembler, we pass the options directly to the
+ // backend and never even instantiate the frontend TargetInfo. If we did,
+ // and used its handleTargetFeatures hook, then we could ensure the
+ // assembler and the frontend behave the same.
+
+ // 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");
+ // Also need to explicitly disable features which imply NEON.
+ Features.push_back("-crypto");
+ }
+
+ // 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,
+ bool KernelOrKext) const {
+ const Driver &D = getToolChain().getDriver();
+ // Get the effective triple, which takes into account the deployment target.
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple Triple(TripleStr);
+ std::string CPUName = arm::getARMTargetCPU(Args, Triple);
+
+ // Select the ABI to use.
+ //
+ // FIXME: Support -meabi.
+ const char *ABIName = nullptr;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ ABIName = A->getValue();
+ } else if (Triple.isOSBinFormatMachO()) {
+ // The backend is hardwired to assume AAPCS for M-class processors, ensure
+ // the frontend matches that.
+ if (Triple.getEnvironment() == llvm::Triple::EABI ||
+ (Triple.getOS() == llvm::Triple::UnknownOS &&
+ Triple.getObjectFormat() == llvm::Triple::MachO) ||
+ StringRef(CPUName).startswith("cortex-m")) {
+ ABIName = "aapcs";
+ } else {
+ ABIName = "apcs-gnu";
+ }
+ } else if (Triple.isOSWindows()) {
+ // FIXME: this is invalid for WindowsCE
+ ABIName = "aapcs";
+ } else {
+ // Select the default based on the platform.
+ switch(Triple.getEnvironment()) {
+ case llvm::Triple::Android:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
+ ABIName = "aapcs-linux";
+ break;
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::EABI:
+ ABIName = "aapcs";
+ break;
+ default:
+ ABIName = "apcs-gnu";
+ }
+ }
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ // Determine floating point ABI from the options & target defaults.
+ StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple);
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ } else if (FloatABI == "softfp") {
+ // Floating point operations are hard, but argument passing is soft.
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ } else {
+ // Floating point operations and argument passing are hard.
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
+ // Kernel code has more strict alignment requirements.
+ if (KernelOrKext) {
+ if (!Triple.isiOS() || Triple.isOSVersionLT(6)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-long-calls");
+ }
+
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-strict-align");
+
+ // The kext linker doesn't know how to deal with movw/movt.
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-use-movt=0");
+ }
+
+ // Setting -mno-global-merge disables the codegen global merge pass. Setting
+ // -mglobal-merge has no effect as the pass is enabled by default.
+ if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
+ options::OPT_mno_global_merge)) {
+ if (A->getOption().matches(options::OPT_mno_global_merge))
+ CmdArgs.push_back("-mno-global-merge");
+ }
+
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float,
+ true))
+ CmdArgs.push_back("-no-implicit-float");
+
+ // 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");
+ }
+}
+
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
+/// targeting.
+static std::string getAArch64TargetCPU(const ArgList &Args) {
+ Arg *A;
+ std::string CPU;
+ // If we have -mtune or -mcpu, use that.
+ if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
+ CPU = A->getValue();
+ } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
+ StringRef Mcpu = A->getValue();
+ CPU = Mcpu.split("+").first;
+ }
+
+ // Handle CPU name is 'native'.
+ if (CPU == "native")
+ return llvm::sys::getHostCPUName();
+ else if (CPU.size())
+ return CPU;
+
+ // Make sure we pick "cyclone" if -arch is used.
+ // FIXME: Should this be picked by checking the target triple instead?
+ if (Args.getLastArg(options::OPT_arch))
+ return "cyclone";
+
+ return "generic";
+}
+
+void Clang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ llvm::Triple Triple(TripleStr);
+
+ if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float, true))
+ CmdArgs.push_back("-no-implicit-float");
+
+ const char *ABIName = nullptr;
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ ABIName = A->getValue();
+ else if (Triple.isOSDarwin())
+ ABIName = "darwinpcs";
+ else
+ ABIName = "aapcs";
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+
+ if (Args.hasArg(options::OPT_mstrict_align)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-aarch64-strict-align");
+ }
+
+ // Setting -mno-global-merge disables the codegen global merge pass. Setting
+ // -mglobal-merge has no effect as the pass is enabled by default.
+ if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
+ options::OPT_mno_global_merge)) {
+ if (A->getOption().matches(options::OPT_mno_global_merge))
+ CmdArgs.push_back("-mno-global-merge");
+ }
+}
+
+// Get CPU and ABI names. They are not independent
+// so we have to calculate them together.
+void mips::getMipsCPUAndABI(const ArgList &Args,
+ const llvm::Triple &Triple,
+ StringRef &CPUName,
+ StringRef &ABIName) {
+ const char *DefMips32CPU = "mips32r2";
+ const char *DefMips64CPU = "mips64r2";
+
+ // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
+ // default for mips64(el)?-img-linux-gnu.
+ if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
+ Triple.getEnvironment() == llvm::Triple::GNU) {
+ DefMips32CPU = "mips32r6";
+ DefMips64CPU = "mips64r6";
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
+ options::OPT_mcpu_EQ))
+ CPUName = A->getValue();
+
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ ABIName = A->getValue();
+ // Convert a GNU style Mips ABI name to the name
+ // accepted by LLVM Mips backend.
+ ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
+ .Case("32", "o32")
+ .Case("64", "n64")
+ .Default(ABIName);
+ }
+
+ // Setup default CPU and ABI names.
+ if (CPUName.empty() && ABIName.empty()) {
+ switch (Triple.getArch()) {
+ default:
+ llvm_unreachable("Unexpected triple arch name");
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ CPUName = DefMips32CPU;
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ CPUName = DefMips64CPU;
+ break;
+ }
+ }
+
+ if (ABIName.empty()) {
+ // Deduce ABI name from the target triple.
+ if (Triple.getArch() == llvm::Triple::mips ||
+ Triple.getArch() == llvm::Triple::mipsel)
+ ABIName = "o32";
+ else
+ ABIName = "n64";
+ }
+
+ if (CPUName.empty()) {
+ // Deduce CPU name from ABI name.
+ CPUName = llvm::StringSwitch<const char *>(ABIName)
+ .Cases("o32", "eabi", DefMips32CPU)
+ .Cases("n32", "n64", DefMips64CPU)
+ .Default("");
+ }
+}
+
+// Convert ABI name to the GNU tools acceptable variant.
+static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
+ return llvm::StringSwitch<llvm::StringRef>(ABI)
+ .Case("o32", "32")
+ .Case("n64", "64")
+ .Default(ABI);
+}
+
+// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
+// and -mfloat-abi=.
+static StringRef getMipsFloatABI(const Driver &D, const ArgList &Args) {
+ StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ else {
+ FloatABI = A->getValue();
+ if (FloatABI != "soft" && FloatABI != "hard") {
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+ FloatABI = "hard";
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ // Assume "hard", because it's a default value used by gcc.
+ // When we start to recognize specific target MIPS processors,
+ // we will be able to select the default more correctly.
+ FloatABI = "hard";
+ }
+
+ return FloatABI;
+}
+
+static void AddTargetFeature(const ArgList &Args,
+ std::vector<const char *> &Features,
+ OptSpecifier OnOpt, OptSpecifier OffOpt,
+ StringRef FeatureName) {
+ if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
+ if (A->getOption().matches(OnOpt))
+ Features.push_back(Args.MakeArgString("+" + FeatureName));
+ else
+ Features.push_back(Args.MakeArgString("-" + FeatureName));
+ }
+}
+
+static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ ABIName = getGnuCompatibleMipsABIName(ABIName);
+
+ // Always override the backend's default ABI.
+ std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
+ .Case("32", "+o32")
+ .Case("n32", "+n32")
+ .Case("64", "+n64")
+ .Case("eabi", "+eabi")
+ .Default(("+" + ABIName).str());
+ Features.push_back("-o32");
+ Features.push_back("-n64");
+ Features.push_back(Args.MakeArgString(ABIFeature));
+
+ StringRef FloatABI = getMipsFloatABI(D, Args);
+ if (FloatABI == "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.
+ Features.push_back("+soft-float");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+ StringRef Val = StringRef(A->getValue());
+ if (Val == "2008")
+ Features.push_back("+nan2008");
+ else if (Val == "legacy")
+ Features.push_back("-nan2008");
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+
+ 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");
+
+ // Add the last -mfp32/-mfpxx/-mfp64 or if none are given and the ABI is O32
+ // pass -mfpxx
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
+ options::OPT_mfp64)) {
+ if (A->getOption().matches(options::OPT_mfp32))
+ Features.push_back(Args.MakeArgString("-fp64"));
+ else if (A->getOption().matches(options::OPT_mfpxx)) {
+ Features.push_back(Args.MakeArgString("+fpxx"));
+ Features.push_back(Args.MakeArgString("+nooddspreg"));
+ } else
+ Features.push_back(Args.MakeArgString("+fp64"));
+ } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
+ Features.push_back(Args.MakeArgString("+fpxx"));
+ Features.push_back(Args.MakeArgString("+nooddspreg"));
+ }
+
+ AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
+ options::OPT_modd_spreg, "nooddspreg");
+}
+
+void Clang::AddMIPSTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ StringRef CPUName;
+ StringRef ABIName;
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName.data());
+
+ StringRef FloatABI = getMipsFloatABI(D, Args);
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
+ }
+ else {
+ // Floating point operations and argument passing are hard.
+ assert(FloatABI == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
+ if (A->getOption().matches(options::OPT_mxgot)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mxgot");
+ }
+ }
+
+ 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");
+ CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v));
+ A->claim();
+ }
+}
+
+/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
+static std::string getPPCTargetCPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPUName = A->getValue();
+
+ if (CPUName == "native") {
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ else
+ return "";
+ }
+
+ return llvm::StringSwitch<const char *>(CPUName)
+ .Case("common", "generic")
+ .Case("440", "440")
+ .Case("440fp", "440")
+ .Case("450", "450")
+ .Case("601", "601")
+ .Case("602", "602")
+ .Case("603", "603")
+ .Case("603e", "603e")
+ .Case("603ev", "603ev")
+ .Case("604", "604")
+ .Case("604e", "604e")
+ .Case("620", "620")
+ .Case("630", "pwr3")
+ .Case("G3", "g3")
+ .Case("7400", "7400")
+ .Case("G4", "g4")
+ .Case("7450", "7450")
+ .Case("G4+", "g4+")
+ .Case("750", "750")
+ .Case("970", "970")
+ .Case("G5", "g5")
+ .Case("a2", "a2")
+ .Case("a2q", "a2q")
+ .Case("e500mc", "e500mc")
+ .Case("e5500", "e5500")
+ .Case("power3", "pwr3")
+ .Case("power4", "pwr4")
+ .Case("power5", "pwr5")
+ .Case("power5x", "pwr5x")
+ .Case("power6", "pwr6")
+ .Case("power6x", "pwr6x")
+ .Case("power7", "pwr7")
+ .Case("power8", "pwr8")
+ .Case("pwr3", "pwr3")
+ .Case("pwr4", "pwr4")
+ .Case("pwr5", "pwr5")
+ .Case("pwr5x", "pwr5x")
+ .Case("pwr6", "pwr6")
+ .Case("pwr6x", "pwr6x")
+ .Case("pwr7", "pwr7")
+ .Case("pwr8", "pwr8")
+ .Case("powerpc", "ppc")
+ .Case("powerpc64", "ppc64")
+ .Case("powerpc64le", "ppc64le")
+ .Default("");
+ }
+
+ return "";
+}
+
+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();
+
+ // 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);
+
+ // 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";
+
+ 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)) {
+ const char *GPUName = A->getValue();
+ return llvm::StringSwitch<const char *>(GPUName)
+ .Cases("rv630", "rv635", "r600")
+ .Cases("rv610", "rv620", "rs780", "rs880")
+ .Case("rv740", "rv770")
+ .Case("palm", "cedar")
+ .Cases("sumo", "sumo2", "sumo")
+ .Case("hemlock", "cypress")
+ .Case("aruba", "cayman")
+ .Default(GPUName);
+ }
+ return "";
+}
+
+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();
+
+ // Select the float ABI as determined by -msoft-float and -mhard-float.
+ StringRef FloatABI;
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mhard_float)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ // Assume "soft", but warn the user we are guessing.
+ FloatABI = "soft";
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+ }
+
+ if (FloatABI == "soft") {
+ // Floating point operations and argument passing are soft.
+ //
+ // FIXME: This changes CPP defines, we need -target-soft-float.
+ CmdArgs.push_back("-msoft-float");
+ } 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 (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.
+ //
+ // FIXME: We should also incorporate the detected target features for use
+ // with -native.
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (!CPU.empty() && CPU != "generic")
+ return Args.MakeArgString(CPU);
+ }
+
+ // Select the default CPU if none was given (or detection failed).
+
+ if (Triple.getArch() != llvm::Triple::x86_64 &&
+ Triple.getArch() != llvm::Triple::x86)
+ return nullptr; // This routine is only handling x86 targets.
+
+ bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
+
+ // FIXME: Need target hooks.
+ if (Triple.isOSDarwin()) {
+ if (Triple.getArchName() == "x86_64h")
+ return "core-avx2";
+ return Is64Bit ? "core2" : "yonah";
+ }
+
+ // On Android use targets compatible with gcc
+ if (Triple.getEnvironment() == llvm::Triple::Android)
+ return Is64Bit ? "x86-64" : "i686";
+
+ // Everything else goes to x86-64 in 64-bit mode.
+ if (Is64Bit)
+ return "x86-64";
+
+ switch (Triple.getOS()) {
+ case llvm::Triple::FreeBSD:
+ case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
+ return "i486";
+ case llvm::Triple::Haiku:
+ return "i586";
+ case llvm::Triple::Bitrig:
+ return "i686";
+ default:
+ // Fallback to p4.
+ return "pentium4";
+ }
+}
+
+static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
+ switch(T.getArch()) {
+ default:
+ return "";
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ return getAArch64TargetCPU(Args);
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ return arm::getARMTargetCPU(Args, T);
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::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:
+ case llvm::Triple::sparcv9:
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_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 AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // 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.
+ 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));
+}
+
+static void getX86TargetFeatures(const Driver & D,
+ 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");
+ }
+
+ // Add features to comply with gcc on Android
+ if (Triple.getEnvironment() == llvm::Triple::Android) {
+ if (Triple.getArch() == llvm::Triple::x86_64) {
+ Features.push_back("+sse4.2");
+ Features.push_back("+popcnt");
+ } else
+ Features.push_back("+ssse3");
+ }
+
+ // Set features according to the -arch flag on MSVC
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+ StringRef Arch = A->getValue();
+ bool ArchUsed = false;
+ // First, look for flags that are shared in x86 and x86-64.
+ if (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::x86) {
+ if (Arch == "AVX" || Arch == "AVX2") {
+ ArchUsed = true;
+ Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+ }
+ }
+ // Then, look for x86-specific flags.
+ if (Triple.getArch() == llvm::Triple::x86) {
+ if (Arch == "IA32") {
+ ArchUsed = true;
+ } else if (Arch == "SSE" || Arch == "SSE2") {
+ ArchUsed = true;
+ Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+ }
+ }
+ if (!ArchUsed)
+ D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
+ }
+
+ // 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,
+ ArgStringList &CmdArgs) const {
+ if (!Args.hasFlag(options::OPT_mred_zone,
+ options::OPT_mno_red_zone,
+ true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ // Default to avoid implicit floating-point for kernel/kext code, but allow
+ // that to be overridden with -mno-soft-float.
+ bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext));
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
+ options::OPT_mno_soft_float,
+ options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float)) {
+ const Option &O = A->getOption();
+ NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
+ O.matches(options::OPT_msoft_float));
+ }
+ if (NoImplicitFloat)
+ CmdArgs.push_back("-no-implicit-float");
+
+ if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "intel" || Value == "att") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
+ } else {
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+}
+
+static inline bool HasPICArg(const ArgList &Args) {
+ return Args.hasArg(options::OPT_fPIC)
+ || Args.hasArg(options::OPT_fpic);
+}
+
+static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) {
+ return Args.getLastArg(options::OPT_G,
+ options::OPT_G_EQ,
+ options::OPT_msmall_data_threshold_EQ);
+}
+
+static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) {
+ std::string value;
+ if (HasPICArg(Args))
+ value = "0";
+ else if (Arg *A = GetLastSmallDataThresholdArg(Args)) {
+ value = A->getValue();
+ A->claim();
+ }
+ return value;
+}
+
+void Clang::AddHexagonTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-fno-signed-char");
+ CmdArgs.push_back("-mqdsp6-compat");
+ CmdArgs.push_back("-Wreturn-type");
+
+ std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
+ if (!SmallDataThreshold.empty()) {
+ CmdArgs.push_back ("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString(
+ "-hexagon-small-data-threshold=" + SmallDataThreshold));
+ }
+
+ if (!Args.hasArg(options::OPT_fno_short_enums))
+ CmdArgs.push_back("-fshort-enums");
+ if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
+ CmdArgs.push_back ("-mllvm");
+ CmdArgs.push_back ("-enable-hexagon-ieee-rnd-near");
+ }
+ CmdArgs.push_back ("-mllvm");
+ CmdArgs.push_back ("-machine-sink-split=0");
+}
+
+// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
+static bool DecodeAArch64Features(const Driver &D, const StringRef &text,
+ std::vector<const char *> &Features) {
+ SmallVector<StringRef, 8> Split;
+ text.split(Split, StringRef("+"), -1, false);
+
+ for (unsigned I = 0, E = Split.size(); I != E; ++I) {
+ const char *result = llvm::StringSwitch<const char *>(Split[I])
+ .Case("fp", "+fp-armv8")
+ .Case("simd", "+neon")
+ .Case("crc", "+crc")
+ .Case("crypto", "+crypto")
+ .Case("nofp", "-fp-armv8")
+ .Case("nosimd", "-neon")
+ .Case("nocrc", "-crc")
+ .Case("nocrypto", "-crypto")
+ .Default(nullptr);
+ if (result)
+ Features.push_back(result);
+ else if (Split[I] == "neon" || Split[I] == "noneon")
+ D.Diag(diag::err_drv_no_neon_modifier);
+ else
+ return false;
+ }
+ return true;
+}
+
+// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
+// decode CPU and feature.
+static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
+ std::vector<const char *> &Features) {
+ std::pair<StringRef, StringRef> Split = Mcpu.split("+");
+ CPU = Split.first;
+ if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
+ Features.push_back("+neon");
+ Features.push_back("+crc");
+ Features.push_back("+crypto");
+ } else if (CPU == "generic") {
+ Features.push_back("+neon");
+ } else {
+ return false;
+ }
+
+ if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ std::pair<StringRef, StringRef> Split = March.split("+");
+ if (Split.first != "armv8-a")
+ return false;
+
+ if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef CPU;
+ if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
+ return false;
+
+ return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ // Handle CPU name is 'native'.
+ if (Mtune == "native")
+ Mtune = llvm::sys::getHostCPUName();
+ if (Mtune == "cyclone") {
+ Features.push_back("+zcm");
+ Features.push_back("+zcz");
+ }
+ return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+ const ArgList &Args,
+ std::vector<const char *> &Features) {
+ StringRef CPU;
+ std::vector<const char *> DecodedFeature;
+ if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
+ return false;
+
+ return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
+}
+
+static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<const char *> &Features) {
+ Arg *A;
+ bool success = true;
+ // Enable NEON by default.
+ Features.push_back("+neon");
+ if ((A = Args.getLastArg(options::OPT_march_EQ)))
+ success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
+ else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
+ success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+
+ if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
+ success =
+ getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
+ else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
+ success =
+ getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+
+ if (!success)
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
+ if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
+ Features.push_back("-fp-armv8");
+ Features.push_back("-crypto");
+ 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");
+ }
+}
+
+static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ bool ForAS) {
+ 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, Triple, Args, Features);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ getARMTargetFeatures(D, Triple, Args, Features, ForAS);
+ 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:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ getAArch64TargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ getX86TargetFeatures(D, 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) {
+ // We use the zero-cost exception tables for Objective-C if the non-fragile
+ // ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
+ // later.
+ if (runtime.isNonFragile())
+ return true;
+
+ if (!Triple.isMacOSX())
+ return false;
+
+ return (!Triple.isMacOSXVersionLT(10,5) &&
+ (Triple.getArch() == llvm::Triple::x86_64 ||
+ Triple.getArch() == llvm::Triple::arm));
+}
+
+namespace {
+ struct ExceptionSettings {
+ bool ExceptionsEnabled;
+ bool ShouldUseExceptionTables;
+ ExceptionSettings() : ExceptionsEnabled(false),
+ ShouldUseExceptionTables(false) {}
+ };
+} // end anonymous namespace.
+
+// exceptionSettings() exists to share the logic between -cc1 and linker
+// invocations.
+static ExceptionSettings exceptionSettings(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ ExceptionSettings ES;
+
+ // Are exceptions enabled by default?
+ ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);
+
+ // This keeps track of whether exceptions were explicitly turned on or off.
+ bool DidHaveExplicitExceptionFlag = false;
+
+ if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
+ options::OPT_fno_exceptions)) {
+ if (A->getOption().matches(options::OPT_fexceptions))
+ ES.ExceptionsEnabled = true;
+ else
+ ES.ExceptionsEnabled = false;
+
+ DidHaveExplicitExceptionFlag = true;
+ }
+
+ // Exception tables and cleanups can be enabled with -fexceptions even if the
+ // language itself doesn't support exceptions.
+ if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
+ ES.ShouldUseExceptionTables = true;
+
+ return ES;
+}
+
+/// addExceptionArgs - Adds exception related arguments to the driver command
+/// arguments. There's a master flag, -fexceptions and also language specific
+/// flags to enable/disable C++ and Objective-C exceptions.
+/// This makes it possible to for example disable C++ exceptions but enable
+/// Objective-C exceptions.
+static void addExceptionArgs(const ArgList &Args, types::ID InputType,
+ const llvm::Triple &Triple,
+ bool KernelOrKext,
+ const ObjCRuntime &objcRuntime,
+ ArgStringList &CmdArgs) {
+ if (KernelOrKext) {
+ // -mkernel and -fapple-kext imply no exceptions, so claim exception related
+ // arguments now to avoid warnings about unused arguments.
+ Args.ClaimAllArgs(options::OPT_fexceptions);
+ Args.ClaimAllArgs(options::OPT_fno_exceptions);
+ Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
+ Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
+ Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
+ Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
+ return;
+ }
+
+ // Gather the exception settings from the command line arguments.
+ ExceptionSettings ES = exceptionSettings(Args, Triple);
+
+ // Obj-C exceptions are enabled by default, regardless of -fexceptions. This
+ // is not necessarily sensible, but follows GCC.
+ if (types::isObjC(InputType) &&
+ Args.hasFlag(options::OPT_fobjc_exceptions,
+ options::OPT_fno_objc_exceptions,
+ true)) {
+ CmdArgs.push_back("-fobjc-exceptions");
+
+ ES.ShouldUseExceptionTables |=
+ shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
+ }
+
+ if (types::isCXX(InputType)) {
+ bool CXXExceptionsEnabled = ES.ExceptionsEnabled;
+
+ if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
+ options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions,
+ options::OPT_fno_exceptions)) {
+ if (A->getOption().matches(options::OPT_fcxx_exceptions))
+ CXXExceptionsEnabled = true;
+ else if (A->getOption().matches(options::OPT_fno_cxx_exceptions))
+ CXXExceptionsEnabled = false;
+ }
+
+ if (CXXExceptionsEnabled) {
+ CmdArgs.push_back("-fcxx-exceptions");
+
+ ES.ShouldUseExceptionTables = true;
+ }
+ }
+
+ if (ES.ShouldUseExceptionTables)
+ CmdArgs.push_back("-fexceptions");
+}
+
+static bool ShouldDisableAutolink(const ArgList &Args,
+ const ToolChain &TC) {
+ bool Default = true;
+ if (TC.getTriple().isOSDarwin()) {
+ // The native darwin assembler doesn't support the linker_option directives,
+ // so we disable them if we think the .s file will be passed to it.
+ Default = TC.useIntegratedAs();
+ }
+ return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
+ Default);
+}
+
+static bool ShouldDisableDwarfDirectory(const ArgList &Args,
+ const ToolChain &TC) {
+ bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm,
+ options::OPT_fno_dwarf_directory_asm,
+ TC.useIntegratedAs());
+ return !UseDwarfDirectory;
+}
+
+/// \brief Check whether the given input tree contains any compilation actions.
+static bool ContainsCompileAction(const Action *A) {
+ if (isa<CompileJobAction>(A))
+ return true;
+
+ for (const auto &Act : *A)
+ if (ContainsCompileAction(Act))
+ return true;
+
+ return false;
+}
+
+/// \brief Check if -relax-all should be passed to the internal assembler.
+/// This is done by default when compiling non-assembler source with -O0.
+static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
+ bool RelaxDefault = true;
+
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ RelaxDefault = A->getOption().matches(options::OPT_O0);
+
+ if (RelaxDefault) {
+ RelaxDefault = false;
+ for (const auto &Act : C.getActions()) {
+ if (ContainsCompileAction(Act)) {
+ RelaxDefault = true;
+ break;
+ }
+ }
+ }
+
+ return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
+ RelaxDefault);
+}
+
+static void CollectArgsForIntegratedAssembler(Compilation &C,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const Driver &D) {
+ if (UseRelaxAll(C, Args))
+ CmdArgs.push_back("-mrelax-all");
+
+ // 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;
+
+ // When using an integrated assembler, translate -Wa, and -Xassembler
+ // options.
+ bool CompressDebugSections = false;
+ 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 (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 == "-compress-debug-sections" ||
+ Value == "--compress-debug-sections") {
+ CompressDebugSections = true;
+ } else if (Value == "-nocompress-debug-sections" ||
+ Value == "--nocompress-debug-sections") {
+ CompressDebugSections = false;
+ } 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 if (Value.startswith("-gdwarf-")) {
+ CmdArgs.push_back(Value.data());
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+ }
+ if (CompressDebugSections) {
+ if (llvm::zlib::isAvailable())
+ CmdArgs.push_back("-compress-debug-sections");
+ else
+ D.Diag(diag::warn_debug_compression_unavailable);
+ }
+}
+
+// Until ARM libraries are build separately, we have them all in one library
+static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
+ if (TC.getArch() == llvm::Triple::arm ||
+ TC.getArch() == llvm::Triple::armeb)
+ return "arm";
+ else
+ return TC.getArchName();
+}
+
+static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
+ // The runtimes are located in the OS-specific resource directory.
+ SmallString<128> Res(TC.getDriver().ResourceDir);
+ const llvm::Triple &Triple = TC.getTriple();
+ // TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
+ StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
+ "freebsd" : TC.getOS();
+ llvm::sys::path::append(Res, "lib", OSLibName);
+ return Res;
+}
+
+// This adds the static libclang_rt.builtins-arch.a directly to the command line
+// FIXME: Make sure we can also emit shared objects if they're requested
+// and available, check for possible errors, etc.
+static void addClangRTLinux(
+ const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+ SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
+ getArchNameForCompilerRTLib(TC) +
+ ".a");
+
+ CmdArgs.push_back(Args.MakeArgString(LibClangRT));
+ CmdArgs.push_back("-lgcc_s");
+ if (TC.getDriver().CCCIsCXX())
+ CmdArgs.push_back("-lgcc_eh");
+}
+
+static void addProfileRT(
+ 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_fprofile_instr_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)))
+ return;
+
+ // -fprofile-instr-generate requires position-independent code to build with
+ // shared objects. Link against the right archive.
+ const char *Lib = "libclang_rt.profile-";
+ if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
+ Args.hasArg(options::OPT_shared))
+ Lib = "libclang_rt.profile-pic-";
+
+ SmallString<128> LibProfile = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibProfile,
+ Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a");
+
+ CmdArgs.push_back(Args.MakeArgString(LibProfile));
+}
+
+static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
+ const StringRef Sanitizer,
+ bool Shared) {
+ // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
+ // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
+ const char *EnvSuffix =
+ TC.getTriple().getEnvironment() == llvm::Triple::Android ? "-android" : "";
+ SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(LibSanitizer,
+ Twine("libclang_rt.") + Sanitizer + "-" +
+ getArchNameForCompilerRTLib(TC) + EnvSuffix +
+ (Shared ? ".so" : ".a"));
+ return LibSanitizer;
+}
+
+static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const StringRef Sanitizer,
+ bool BeforeLibStdCXX,
+ bool ExportSymbols = true,
+ bool LinkDeps = true) {
+ SmallString<128> LibSanitizer =
+ getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
+
+ // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
+ // etc.) so that the linker picks custom versions of the global 'operator
+ // new' and 'operator delete' symbols. We take the extreme (but simple)
+ // strategy of inserting it at the front of the link command. It also
+ // needs to be forced to end up in the executable, so wrap it in
+ // whole-archive.
+ SmallVector<const char *, 3> LibSanitizerArgs;
+ LibSanitizerArgs.push_back("-whole-archive");
+ LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
+ LibSanitizerArgs.push_back("-no-whole-archive");
+
+ CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
+ LibSanitizerArgs.begin(), LibSanitizerArgs.end());
+
+ if (LinkDeps) {
+ // Link sanitizer dependencies explicitly
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lrt");
+ CmdArgs.push_back("-lm");
+ // There's no libdl on FreeBSD.
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-ldl");
+ }
+
+ // If possible, use a dynamic symbols file to export the symbols from the
+ // runtime library. If we can't do so, use -export-dynamic instead to export
+ // all symbols from the binary.
+ if (ExportSymbols) {
+ if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
+ CmdArgs.push_back(
+ Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+ else
+ CmdArgs.push_back("-export-dynamic");
+ }
+}
+
+/// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
+/// This needs to be called before we add the C run-time (malloc, etc).
+static void addAsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool Shared, bool IsCXX) {
+ if (Shared) {
+ // Link dynamic runtime if necessary.
+ SmallString<128> LibSanitizer =
+ getSanitizerRTLibName(TC, "asan", Shared);
+ CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
+ }
+
+ // Do not link static runtime to DSOs or if compiling for Android.
+ if (Args.hasArg(options::OPT_shared) ||
+ (TC.getTriple().getEnvironment() == llvm::Triple::Android))
+ return;
+
+ if (Shared) {
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
+ /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
+ /*LinkDeps*/ false);
+ } else {
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
+ if (IsCXX)
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
+ }
+}
+
+/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
+/// This needs to be called before we add the C run-time (malloc, etc).
+static void addTsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlags(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 addMsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlags(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 addLsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
+}
+
+/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
+/// (Linux).
+static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool IsCXX,
+ bool HasOtherSanitizerRt) {
+ // Do not link runtime into shared libraries.
+ 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)
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);
+
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true);
+
+ // Only include the bits of the runtime which need a C++ ABI library if
+ // we're linking in C++ mode.
+ if (IsCXX)
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true);
+}
+
+static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasArg(options::OPT_shared))
+ addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
+}
+
+// Should be called before we add C++ ABI library.
+static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ const Driver &D = TC.getDriver();
+ if (Sanitize.needsUbsanRt())
+ addUbsanRT(TC, Args, CmdArgs, D.CCCIsCXX(),
+ Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
+ Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
+ if (Sanitize.needsAsanRt())
+ addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(), D.CCCIsCXX());
+ if (Sanitize.needsTsanRt())
+ addTsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsMsanRt())
+ addMsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsLsanRt())
+ addLsanRT(TC, Args, CmdArgs);
+ if (Sanitize.needsDfsanRt())
+ addDfsanRT(TC, Args, CmdArgs);
+}
+
+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);
+
+ return shouldUseFramePointerForTarget(Args, Triple);
+}
+
+static bool shouldUseLeafFramePointer(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
+ options::OPT_momit_leaf_frame_pointer))
+ return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+
+ return shouldUseFramePointerForTarget(Args, Triple);
+}
+
+/// Add a CC1 option to specify the debug compilation directory.
+static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
+ SmallString<128> cwd;
+ if (!llvm::sys::fs::current_path(cwd)) {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Args.MakeArgString(cwd));
+ }
+}
+
+static const char *SplitDebugName(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ Arg *FinalOutput = Args.getLastArg(options::OPT_o);
+ if (FinalOutput && Args.hasArg(options::OPT_c)) {
+ SmallString<128> T(FinalOutput->getValue());
+ llvm::sys::path::replace_extension(T, "dwo");
+ return Args.MakeArgString(T);
+ } else {
+ // Use the compilation dir.
+ SmallString<128> T(
+ Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
+ SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput()));
+ llvm::sys::path::replace_extension(F, "dwo");
+ T += F;
+ return Args.MakeArgString(F);
+ }
+}
+
+static void SplitDebugInfo(const ToolChain &TC, Compilation &C,
+ const Tool &T, const JobAction &JA,
+ const ArgList &Args, const InputInfo &Output,
+ const char *OutFile) {
+ ArgStringList ExtractArgs;
+ ExtractArgs.push_back("--extract-dwo");
+
+ ArgStringList StripArgs;
+ StripArgs.push_back("--strip-dwo");
+
+ // Grabbing the output of the earlier compile step.
+ StripArgs.push_back(Output.getFilename());
+ ExtractArgs.push_back(Output.getFilename());
+ ExtractArgs.push_back(OutFile);
+
+ const char *Exec =
+ Args.MakeArgString(TC.GetProgramPath("objcopy"));
+
+ // First extract the dwo sections.
+ C.addCommand(new Command(JA, T, Exec, ExtractArgs));
+
+ // Then remove them from the original .o file.
+ C.addCommand(new Command(JA, T, Exec, StripArgs));
+}
+
+/// \brief Vectorize at all optimization levels greater than 1 except for -Oz.
+/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
+static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
+ 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, unless it's the slp vectorizer.
+ if (S == "z")
+ return isSlpVec;
+
+ unsigned OptLevel = 0;
+ if (S.getAsInteger(10, OptLevel))
+ return false;
+
+ return OptLevel > 1;
+ }
+
+ return false;
+}
+
+/// Add -x lang to \p CmdArgs for \p Input.
+static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
+ ArgStringList &CmdArgs) {
+ // When using -verify-pch, we don't want to provide the type
+ // 'precompiled-header' if it was inferred from the file extension
+ if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
+ return;
+
+ CmdArgs.push_back("-x");
+ if (Args.hasArg(options::OPT_rewrite_objc))
+ CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
+ else
+ CmdArgs.push_back(types::getTypeName(Input.getType()));
+}
+
+static std::string getMSCompatibilityVersion(const char *VersionStr) {
+ unsigned Version;
+ if (StringRef(VersionStr).getAsInteger(10, Version))
+ return "0";
+
+ if (Version < 100)
+ return llvm::utostr_32(Version) + ".0";
+
+ if (Version < 10000)
+ return llvm::utostr_32(Version / 100) + "." +
+ llvm::utostr_32(Version % 100);
+
+ unsigned Build = 0, Factor = 1;
+ for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10)
+ Build = Build + (Version % 10) * Factor;
+ return llvm::utostr_32(Version / 100) + "." +
+ llvm::utostr_32(Version % 100) + "." +
+ llvm::utostr_32(Build);
+}
+
+void Clang::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ bool KernelOrKext = Args.hasArg(options::OPT_mkernel,
+ options::OPT_fapple_kext);
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ bool IsWindowsGNU = getToolChain().getTriple().isWindowsGNUEnvironment();
+ bool IsWindowsCygnus =
+ getToolChain().getTriple().isWindowsCygwinEnvironment();
+ bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
+
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+
+ // Invoke ourselves in -cc1 mode.
+ //
+ // FIXME: Implement custom jobs for internal actions.
+ CmdArgs.push_back("-cc1");
+
+ // Add the "effective" target triple.
+ CmdArgs.push_back("-triple");
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ const llvm::Triple TT(TripleStr);
+ if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ unsigned Offset = TT.getArch() == llvm::Triple::arm ? 4 : 6;
+ unsigned Version;
+ TT.getArchName().substr(Offset).getAsInteger(10, Version);
+ if (Version < 7)
+ D.Diag(diag::err_target_unsupported_arch) << TT.getArchName()
+ << TripleStr;
+ }
+
+ // Push all default warning arguments that are specific to
+ // the given target. These come before user provided warning options
+ // are provided.
+ getToolChain().addClangWarningOptions(CmdArgs);
+
+ // Select the appropriate action.
+ RewriteKind rewriteKind = RK_None;
+
+ if (isa<AnalyzeJobAction>(JA)) {
+ assert(JA.getType() == types::TY_Plist && "Invalid output type.");
+ CmdArgs.push_back("-analyze");
+ } else if (isa<MigrateJobAction>(JA)) {
+ CmdArgs.push_back("-migrate");
+ } else if (isa<PreprocessJobAction>(JA)) {
+ if (Output.getType() == types::TY_Dependencies)
+ CmdArgs.push_back("-Eonly");
+ else {
+ CmdArgs.push_back("-E");
+ if (Args.hasArg(options::OPT_rewrite_objc) &&
+ !Args.hasArg(options::OPT_g_Group))
+ CmdArgs.push_back("-P");
+ }
+ } else if (isa<AssembleJobAction>(JA)) {
+ CmdArgs.push_back("-emit-obj");
+
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
+
+ // Also ignore explicit -force_cpusubtype_ALL option.
+ (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
+ } else if (isa<PrecompileJobAction>(JA)) {
+ // Use PCH if the user requested it.
+ bool UsePCH = D.CCCUsePCH;
+
+ if (JA.getType() == types::TY_Nothing)
+ CmdArgs.push_back("-fsyntax-only");
+ else if (UsePCH)
+ CmdArgs.push_back("-emit-pch");
+ else
+ CmdArgs.push_back("-emit-pth");
+ } else if (isa<VerifyPCHJobAction>(JA)) {
+ CmdArgs.push_back("-verify-pch");
+ } else {
+ assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
+
+ if (JA.getType() == types::TY_Nothing) {
+ CmdArgs.push_back("-fsyntax-only");
+ } else if (JA.getType() == types::TY_LLVM_IR ||
+ JA.getType() == types::TY_LTO_IR) {
+ CmdArgs.push_back("-emit-llvm");
+ } else if (JA.getType() == types::TY_LLVM_BC ||
+ JA.getType() == types::TY_LTO_BC) {
+ CmdArgs.push_back("-emit-llvm-bc");
+ } else if (JA.getType() == types::TY_PP_Asm) {
+ CmdArgs.push_back("-S");
+ } else if (JA.getType() == types::TY_AST) {
+ CmdArgs.push_back("-emit-pch");
+ } else if (JA.getType() == types::TY_ModuleFile) {
+ CmdArgs.push_back("-module-file-info");
+ } else if (JA.getType() == types::TY_RewrittenObjC) {
+ CmdArgs.push_back("-rewrite-objc");
+ rewriteKind = RK_NonFragile;
+ } else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
+ CmdArgs.push_back("-rewrite-objc");
+ rewriteKind = RK_Fragile;
+ } else {
+ assert(JA.getType() == types::TY_PP_Asm &&
+ "Unexpected output type!");
+ }
+ }
+
+ // We normally speed up the clang process a bit by skipping destructors at
+ // exit, but when we're generating diagnostics we can rely on some of the
+ // cleanup.
+ if (!C.isForDiagnostics())
+ CmdArgs.push_back("-disable-free");
+
+ // Disable the verification pass in -asserts builds.
+#ifdef NDEBUG
+ CmdArgs.push_back("-disable-llvm-verifier");
+#endif
+
+ // Set the main file name, so that debug info works even with
+ // -save-temps.
+ CmdArgs.push_back("-main-file-name");
+ CmdArgs.push_back(getBaseInputName(Args, Inputs));
+
+ // Some flags which affect the language (via preprocessor
+ // defines).
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-static-define");
+
+ if (isa<AnalyzeJobAction>(JA)) {
+ // Enable region store model by default.
+ CmdArgs.push_back("-analyzer-store=region");
+
+ // Treat blocks as analysis entry points.
+ CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
+
+ CmdArgs.push_back("-analyzer-eagerly-assume");
+
+ // Add default argument set.
+ if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
+ CmdArgs.push_back("-analyzer-checker=core");
+
+ if (!IsWindowsMSVC)
+ CmdArgs.push_back("-analyzer-checker=unix");
+
+ if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
+ CmdArgs.push_back("-analyzer-checker=osx");
+
+ CmdArgs.push_back("-analyzer-checker=deadcode");
+
+ if (types::isCXX(Inputs[0].getType()))
+ CmdArgs.push_back("-analyzer-checker=cplusplus");
+
+ // Enable the following experimental checkers for testing.
+ CmdArgs.push_back(
+ "-analyzer-checker=security.insecureAPI.UncheckedReturn");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
+ }
+
+ // Set the output format. The default is plist, for (lame) historical
+ // reasons.
+ CmdArgs.push_back("-analyzer-output");
+ if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
+ CmdArgs.push_back(A->getValue());
+ else
+ CmdArgs.push_back("plist");
+
+ // Disable the presentation of standard compiler warnings when
+ // using --analyze. We only want to show static analyzer diagnostics
+ // or frontend errors.
+ CmdArgs.push_back("-w");
+
+ // Add -Xanalyzer arguments when running as analyzer.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
+ }
+
+ CheckCodeGenerationOptions(D, Args);
+
+ bool PIE = getToolChain().isPIEDefault();
+ bool PIC = PIE || getToolChain().isPICDefault();
+ bool IsPICLevelTwo = PIC;
+
+ // Android-specific defaults for PIC/PIE
+ if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) {
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm64:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ PIC = true; // "-fpic"
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ PIC = true; // "-fPIC"
+ IsPICLevelTwo = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // OpenBSD-specific defaults for PIE
+ if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) {
+ switch (getToolChain().getTriple().getArch()) {
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::sparc:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ IsPICLevelTwo = false; // "-fpie"
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::sparcv9:
+ IsPICLevelTwo = true; // "-fPIE"
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // For the PIC and PIE flag options, this logic is different from the
+ // legacy logic in very old versions of GCC, as that logic was just
+ // a bug no one had ever fixed. This logic is both more rational and
+ // consistent with GCC's new logic now that the bugs are fixed. The last
+ // argument relating to either PIC or PIE wins, and no other argument is
+ // used. If the last argument is any flavor of the '-fno-...' arguments,
+ // both PIC and PIE are disabled. Any PIE option implicitly enables PIC
+ // at the same level.
+ Arg *LastPICArg =Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie);
+ // Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
+ // is forced, then neither PIC nor PIE flags will have no effect.
+ if (!getToolChain().isPICDefaultForced()) {
+ if (LastPICArg) {
+ Option O = LastPICArg->getOption();
+ if (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie)) {
+ PIE = O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie);
+ PIC = PIE || O.matches(options::OPT_fPIC) ||
+ O.matches(options::OPT_fpic);
+ IsPICLevelTwo = O.matches(options::OPT_fPIE) ||
+ O.matches(options::OPT_fPIC);
+ } else {
+ PIE = PIC = false;
+ }
+ }
+ }
+
+ // 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).
+ if (PIC && getToolChain().getTriple().isOSDarwin())
+ IsPICLevelTwo |= getToolChain().isPICDefault();
+
+ // Note that these flags are trump-cards. Regardless of the order w.r.t. the
+ // PIC or PIE options above, if these show up, PIC is disabled.
+ llvm::Triple Triple(TripleStr);
+ if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
+ Triple.getArch() == llvm::Triple::arm64 ||
+ Triple.getArch() == llvm::Triple::aarch64))
+ PIC = PIE = false;
+ if (Args.hasArg(options::OPT_static))
+ PIC = PIE = false;
+
+ if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
+ // This is a very special mode. It trumps the other modes, almost no one
+ // uses it, and it isn't even valid on any OS but Darwin.
+ if (!getToolChain().getTriple().isOSDarwin())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << getToolChain().getTriple().str();
+
+ // FIXME: Warn when this flag trumps some other PIC or PIE flag.
+
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back("dynamic-no-pic");
+
+ // Only a forced PIC mode can cause the actual compile to have PIC defines
+ // etc., no flags are sufficient. This behavior was selected to closely
+ // match that of llvm-gcc and Apple GCC before that.
+ if (getToolChain().isPICDefault() && getToolChain().isPICDefaultForced()) {
+ CmdArgs.push_back("-pic-level");
+ CmdArgs.push_back("2");
+ }
+ } else {
+ // Currently, LLVM only knows about PIC vs. static; the PIE differences are
+ // handled in Clang's IRGen by the -pie-level flag.
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back(PIC ? "pic" : "static");
+
+ if (PIC) {
+ CmdArgs.push_back("-pic-level");
+ CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
+ if (PIE) {
+ CmdArgs.push_back("-pie-level");
+ CmdArgs.push_back(IsPICLevelTwo ? "2" : "1");
+ }
+ }
+ }
+
+ if (!Args.hasFlag(options::OPT_fmerge_all_constants,
+ options::OPT_fno_merge_all_constants))
+ CmdArgs.push_back("-fno-merge-all-constants");
+
+ // LLVM Code Generator Options.
+
+ if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
+ StringRef v = A->getValue();
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
+ A->claim();
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
+ CmdArgs.push_back("-mregparm");
+ 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");
+
+ if (shouldUseFramePointer(Args, getToolChain().getTriple()))
+ CmdArgs.push_back("-mdisable-fp-elim");
+ if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
+ options::OPT_fno_zero_initialized_in_bss))
+ CmdArgs.push_back("-mno-zero-initialized-in-bss");
+
+ bool OFastEnabled = isOptimizationLevelFast(Args);
+ // If -Ofast is the optimization level, then -fstrict-aliasing should be
+ // enabled. This alias option is being used to simplify the hasFlag logic.
+ OptSpecifier StrictAliasingAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_fstrict_aliasing;
+ // We turn strict aliasing off by default if we're in CL mode, since MSVC
+ // doesn't do any TBAA.
+ bool TBAAOnByDefault = !getToolChain().getDriver().IsCLMode();
+ if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
+ options::OPT_fno_strict_aliasing, TBAAOnByDefault))
+ CmdArgs.push_back("-relaxed-aliasing");
+ 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");
+ if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls))
+ CmdArgs.push_back("-mdisable-tail-calls");
+
+ // Handle segmented stacks.
+ if (Args.hasArg(options::OPT_fsplit_stack))
+ CmdArgs.push_back("-split-stacks");
+
+ // If -Ofast is the optimization level, then -ffast-math should be enabled.
+ // This alias option is being used to simplify the getLastArg logic.
+ OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
+ options::OPT_ffast_math;
+
+ // Handle various floating point optimization flags, mapping them to the
+ // appropriate LLVM code generation flags. The pattern for all of these is to
+ // default off the codegen optimizations, and if any flag enables them and no
+ // flag disables them after the flag enabling them, enable the codegen
+ // optimization. This is complicated by several "umbrella" flags.
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only,
+ options::OPT_fhonor_infinities,
+ options::OPT_fno_honor_infinities))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_finite_math_only &&
+ A->getOption().getID() != options::OPT_fhonor_infinities)
+ CmdArgs.push_back("-menable-no-infs");
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only,
+ options::OPT_fhonor_nans,
+ options::OPT_fno_honor_nans))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_finite_math_only &&
+ A->getOption().getID() != options::OPT_fhonor_nans)
+ CmdArgs.push_back("-menable-no-nans");
+
+ // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
+ bool MathErrno = getToolChain().IsMathErrnoDefault();
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ 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");
+
+ // There are several flags which require disabling very specific
+ // optimizations. Any of these being disabled forces us to turn off the
+ // entire set of LLVM optimizations, so collect them through all the flag
+ // madness.
+ bool AssociativeMath = false;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fassociative_math,
+ options::OPT_fno_associative_math))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fno_associative_math)
+ AssociativeMath = true;
+ bool ReciprocalMath = false;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_freciprocal_math,
+ options::OPT_fno_reciprocal_math))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fno_reciprocal_math)
+ ReciprocalMath = true;
+ bool SignedZeros = true;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fsigned_zeros,
+ options::OPT_fno_signed_zeros))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_fsigned_zeros)
+ SignedZeros = false;
+ bool TrappingMath = true;
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_ftrapping_math,
+ options::OPT_fno_trapping_math))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations &&
+ A->getOption().getID() != options::OPT_ftrapping_math)
+ TrappingMath = false;
+ if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
+ !TrappingMath)
+ CmdArgs.push_back("-menable-unsafe-fp-math");
+
+
+ // Validate and pass through -fp-contract option.
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_ffp_contract)) {
+ if (A->getOption().getID() == options::OPT_ffp_contract) {
+ StringRef Val = A->getValue();
+ if (Val == "fast" || Val == "on" || Val == "off") {
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val));
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ }
+ } else if (A->getOption().matches(options::OPT_ffast_math) ||
+ (OFastEnabled && A->getOption().matches(options::OPT_Ofast))) {
+ // If fast-math is set then set the fp-contract mode to fast.
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ }
+ }
+
+ // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
+ // and if we find them, tell the frontend to provide the appropriate
+ // preprocessor macros. This is distinct from enabling any optimizations as
+ // these options induce language changes which must survive serialization
+ // and deserialization, etc.
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math))
+ if (!A->getOption().matches(options::OPT_fno_fast_math))
+ CmdArgs.push_back("-ffast-math");
+ if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only,
+ options::OPT_fno_fast_math))
+ if (A->getOption().matches(options::OPT_ffinite_math_only))
+ CmdArgs.push_back("-ffinite-math-only");
+
+ // Decide whether to use verbose asm. Verbose assembly is the default on
+ // toolchains which have the integrated assembler on by default.
+ bool IsIntegratedAssemblerDefault =
+ getToolChain().IsIntegratedAssemblerDefault();
+ if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
+ IsIntegratedAssemblerDefault) ||
+ Args.hasArg(options::OPT_dA))
+ CmdArgs.push_back("-masm-verbose");
+
+ if (!Args.hasFlag(options::OPT_fintegrated_as, options::OPT_fno_integrated_as,
+ IsIntegratedAssemblerDefault))
+ CmdArgs.push_back("-no-integrated-as");
+
+ if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
+ CmdArgs.push_back("-mdebug-pass");
+ CmdArgs.push_back("Structure");
+ }
+ if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
+ CmdArgs.push_back("-mdebug-pass");
+ CmdArgs.push_back("Arguments");
+ }
+
+ // Enable -mconstructor-aliases except on darwin, where we have to
+ // work around a linker bug; see <rdar://problem/7651567>.
+ if (!getToolChain().getTriple().isOSDarwin())
+ CmdArgs.push_back("-mconstructor-aliases");
+
+ // Darwin's kernel doesn't support guard variables; just die if we
+ // try to use them.
+ if (KernelOrKext && getToolChain().getTriple().isOSDarwin())
+ CmdArgs.push_back("-fforbid-guard-variables");
+
+ if (Args.hasArg(options::OPT_mms_bitfields)) {
+ CmdArgs.push_back("-mms-bitfields");
+ }
+
+ // This is a coarse approximation of what llvm-gcc actually does, both
+ // -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
+ // complicated ways.
+ bool AsynchronousUnwindTables =
+ Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ (getToolChain().IsUnwindTablesDefault() ||
+ getToolChain().getSanitizerArgs().needsUnwindTables()) &&
+ !KernelOrKext);
+ if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
+ AsynchronousUnwindTables))
+ CmdArgs.push_back("-munwind-tables");
+
+ getToolChain().addClangTargetOptions(Args, CmdArgs);
+
+ if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+ CmdArgs.push_back("-mlimit-float-precision");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ // FIXME: Handle -mtune=.
+ (void) Args.hasArg(options::OPT_mtune_EQ);
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ CmdArgs.push_back("-mcode-model");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ // 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, false);
+
+ // Add target specific flags.
+ switch(getToolChain().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ AddARMTargetArgs(Args, CmdArgs, KernelOrKext);
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm64:
+ case llvm::Triple::arm64_be:
+ AddAArch64TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ AddSparcTargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::hexagon:
+ AddHexagonTargetArgs(Args, CmdArgs);
+ 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)) {
+ CmdArgs.push_back("-target-linker-version");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (!shouldUseLeafFramePointer(Args, getToolChain().getTriple()))
+ CmdArgs.push_back("-momit-leaf-frame-pointer");
+
+ // Explicitly error on some things we know we don't support and can't just
+ // ignore.
+ types::ID InputType = Inputs[0].getType();
+ if (!Args.hasArg(options::OPT_fallow_unsupported)) {
+ Arg *Unsupported;
+ if (types::isCXX(InputType) &&
+ getToolChain().getTriple().isOSDarwin() &&
+ 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)
+ << Unsupported->getOption().getName();
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_v);
+ Args.AddLastArg(CmdArgs, options::OPT_H);
+ if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
+ CmdArgs.push_back("-header-include-file");
+ CmdArgs.push_back(D.CCPrintHeadersFilename ?
+ D.CCPrintHeadersFilename : "-");
+ }
+ Args.AddLastArg(CmdArgs, options::OPT_P);
+ Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
+
+ if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
+ CmdArgs.push_back("-diagnostic-log-file");
+ CmdArgs.push_back(D.CCLogDiagnosticsFilename ?
+ D.CCLogDiagnosticsFilename : "-");
+ }
+
+ // Use the last option from "-g" group. "-gline-tables-only" and "-gdwarf-x"
+ // are preserved, all other debug options are substituted with "-g".
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ if (A->getOption().matches(options::OPT_gline_tables_only)) {
+ // FIXME: we should support specifying dwarf version with
+ // -gline-tables-only.
+ CmdArgs.push_back("-gline-tables-only");
+ // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
+ Triple.getOS() == llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-gdwarf-2");
+ } 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)) {
+ // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD.
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD ||
+ Triple.getOS() == llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-gdwarf-2");
+ else
+ CmdArgs.push_back("-g");
+ }
+ }
+
+ // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
+ Args.ClaimAllArgs(options::OPT_g_flags_Group);
+ if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
+ /*Default*/ true))
+ 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().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");
+ }
+
+ // -gdwarf-aranges turns on the emission of the aranges section in the
+ // backend.
+ if (Args.hasArg(options::OPT_gdwarf_aranges)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-arange-section");
+ }
+
+ if (Args.hasFlag(options::OPT_fdebug_types_section,
+ options::OPT_fno_debug_types_section, false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-generate-type-units");
+ }
+
+ if (Args.hasFlag(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections, false)) {
+ CmdArgs.push_back("-ffunction-sections");
+ }
+
+ if (Args.hasFlag(options::OPT_fdata_sections,
+ options::OPT_fno_data_sections, false)) {
+ CmdArgs.push_back("-fdata-sections");
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
+
+ if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
+ (Args.hasArg(options::OPT_fprofile_instr_use) ||
+ Args.hasArg(options::OPT_fprofile_instr_use_EQ)))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fprofile-instr-generate" << "-fprofile-instr-use";
+
+ Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ))
+ A->render(Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_fprofile_instr_use))
+ CmdArgs.push_back("-fprofile-instr-use=pgo-data");
+
+ if (Args.hasArg(options::OPT_ftest_coverage) ||
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-femit-coverage-notes");
+ if (Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-femit-coverage-data");
+
+ if (C.getArgs().hasArg(options::OPT_c) ||
+ C.getArgs().hasArg(options::OPT_S)) {
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-coverage-file");
+ SmallString<128> CoverageFilename(Output.getFilename());
+ if (llvm::sys::path::is_relative(CoverageFilename.str())) {
+ 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));
+ }
+ }
+
+ // Pass options for controlling the default header search paths.
+ if (Args.hasArg(options::OPT_nostdinc)) {
+ CmdArgs.push_back("-nostdsysteminc");
+ CmdArgs.push_back("-nobuiltininc");
+ } else {
+ if (Args.hasArg(options::OPT_nostdlibinc))
+ CmdArgs.push_back("-nostdsysteminc");
+ Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
+ Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
+ }
+
+ // Pass the path to compiler resource files.
+ CmdArgs.push_back("-resource-dir");
+ CmdArgs.push_back(D.ResourceDir.c_str());
+
+ Args.AddLastArg(CmdArgs, options::OPT_working_directory);
+
+ bool ARCMTEnabled = false;
+ 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)) {
+ ARCMTEnabled = true;
+ switch (A->getOption().getID()) {
+ default:
+ llvm_unreachable("missed a case");
+ case options::OPT_ccc_arcmt_check:
+ CmdArgs.push_back("-arcmt-check");
+ break;
+ case options::OPT_ccc_arcmt_modify:
+ CmdArgs.push_back("-arcmt-modify");
+ break;
+ case options::OPT_ccc_arcmt_migrate:
+ CmdArgs.push_back("-arcmt-migrate");
+ CmdArgs.push_back("-mt-migrate-directory");
+ CmdArgs.push_back(A->getValue());
+
+ Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
+ Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
+ 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)) {
+ if (ARCMTEnabled) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-ccc-arcmt-migrate";
+ }
+ CmdArgs.push_back("-mt-migrate-directory");
+ CmdArgs.push_back(A->getValue());
+
+ if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
+ 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_migrate_designated_init);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
+ }
+
+ // Add preprocessing options like -I, -D, etc. if we are using the
+ // preprocessor.
+ //
+ // FIXME: Support -fpreprocessed
+ if (types::getPreprocessedType(InputType) != types::TY_INVALID)
+ AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);
+
+ // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
+ // that "The compiler can only warn and ignore the option if not recognized".
+ // When building with ccache, it will pass -D options to clang even on
+ // preprocessed inputs and configure concludes that -fPIC is not supported.
+ Args.ClaimAllArgs(options::OPT_D);
+
+ // 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)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ // Warn about ignored options to clang.
+ for (arg_iterator it = Args.filtered_begin(
+ options::OPT_clang_ignored_gcc_optimization_f_Group),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
+ }
+
+ // Don't warn about unused -flto. This can happen when we're preprocessing or
+ // precompiling.
+ Args.ClaimAllArgs(options::OPT_flto);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+ if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
+ CmdArgs.push_back("-pedantic");
+ Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+
+ // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
+ // (-ansi is equivalent to -std=c89 or -std=c++98).
+ //
+ // If a std is supplied, only add -trigraphs if it follows the
+ // option.
+ if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
+ if (Std->getOption().matches(options::OPT_ansi))
+ if (types::isCXX(InputType))
+ CmdArgs.push_back("-std=c++98");
+ else
+ CmdArgs.push_back("-std=c89");
+ else
+ Std->render(Args, CmdArgs);
+
+ if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
+ options::OPT_trigraphs))
+ if (A != Std)
+ A->render(Args, CmdArgs);
+ } else {
+ // Honor -std-default.
+ //
+ // FIXME: Clang doesn't correctly handle -std= when the input language
+ // doesn't match. For the time being just ignore this for C++ inputs;
+ // eventually we want to do all the standard defaulting here instead of
+ // splitting it between the driver and clang -cc1.
+ if (!types::isCXX(InputType))
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ,
+ "-std=", /*Joined=*/true);
+ else if (IsWindowsMSVC)
+ CmdArgs.push_back("-std=c++11");
+
+ Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
+ }
+
+ // 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)) {
+ // FIXME: This should behave just like a warning flag, and thus should also
+ // respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
+ Arg *WriteStrings =
+ Args.getLastArg(options::OPT_Wwrite_strings,
+ options::OPT_Wno_write_strings, options::OPT_w);
+ if (WriteStrings &&
+ WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
+ CmdArgs.push_back("-fconst-strings");
+ }
+
+ // GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
+ // during C++ compilation, which it is by default. GCC keeps this define even
+ // in the presence of '-w', match this behavior bug-for-bug.
+ if (types::isCXX(InputType) &&
+ Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated,
+ true)) {
+ CmdArgs.push_back("-fdeprecated-macro");
+ }
+
+ // Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
+ if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
+ if (Asm->getOption().matches(options::OPT_fasm))
+ CmdArgs.push_back("-fgnu-keywords");
+ else
+ CmdArgs.push_back("-fno-gnu-keywords");
+ }
+
+ if (ShouldDisableDwarfDirectory(Args, getToolChain()))
+ CmdArgs.push_back("-fno-dwarf-directory-asm");
+
+ if (ShouldDisableAutolink(Args, getToolChain()))
+ CmdArgs.push_back("-fno-autolink");
+
+ // Add in -fdebug-compilation-dir if necessary.
+ addDebugCompDirArg(Args, CmdArgs);
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
+ options::OPT_ftemplate_depth_EQ)) {
+ CmdArgs.push_back("-ftemplate-depth");
+ 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());
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
+ options::OPT_Wlarge_by_value_copy_def)) {
+ if (A->getNumValues()) {
+ StringRef bytes = A->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
+ } else
+ CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
+ }
+
+
+ if (Args.hasArg(options::OPT_relocatable_pch))
+ CmdArgs.push_back("-relocatable-pch");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
+ CmdArgs.push_back("-fconstant-string-class");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
+ CmdArgs.push_back("-ftabstop");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ CmdArgs.push_back("-ferror-limit");
+ if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
+ CmdArgs.push_back(A->getValue());
+ else
+ CmdArgs.push_back("19");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
+ CmdArgs.push_back("-fmacro-backtrace-limit");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
+ CmdArgs.push_back("-ftemplate-backtrace-limit");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
+ CmdArgs.push_back("-fconstexpr-backtrace-limit");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ // Pass -fmessage-length=.
+ CmdArgs.push_back("-fmessage-length");
+ if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
+ CmdArgs.push_back(A->getValue());
+ } else {
+ // If -fmessage-length=N was not specified, determine whether this is a
+ // terminal and, if so, implicitly define -fmessage-length appropriately.
+ unsigned N = llvm::sys::Process::StandardErrColumns();
+ CmdArgs.push_back(Args.MakeArgString(Twine(N)));
+ }
+
+ // -fvisibility= and -fvisibility-ms-compat are of a piece.
+ if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back(A->getValue());
+ } else {
+ assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
+ CmdArgs.push_back("-fvisibility");
+ CmdArgs.push_back("hidden");
+ CmdArgs.push_back("-ftype-visibility");
+ CmdArgs.push_back("default");
+ }
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+
+ Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
+
+ // -fhosted is default.
+ if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
+ KernelOrKext)
+ CmdArgs.push_back("-ffreestanding");
+
+ // Forward -f (flag) options which we can pass directly.
+ Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
+ Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
+ Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
+ Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
+ Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
+ // 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);
+
+ const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
+ Sanitize.addArgs(Args, CmdArgs);
+
+ if (!Args.hasFlag(options::OPT_fsanitize_recover,
+ options::OPT_fno_sanitize_recover,
+ true))
+ CmdArgs.push_back("-fno-sanitize-recover");
+
+ if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
+ options::OPT_fno_sanitize_undefined_trap_on_error, false))
+ CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
+
+ // Report an error for -faltivec on anything other than PowerPC.
+ if (const Arg *A = Args.getLastArg(options::OPT_faltivec))
+ 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/ppc64le";
+
+ if (getToolChain().SupportsProfiling())
+ Args.AddLastArg(CmdArgs, options::OPT_pg);
+
+ // -flax-vector-conversions is default.
+ if (!Args.hasFlag(options::OPT_flax_vector_conversions,
+ options::OPT_fno_lax_vector_conversions))
+ CmdArgs.push_back("-fno-lax-vector-conversions");
+
+ if (Args.getLastArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-fapple-kext");
+
+ Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
+ Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
+ Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
+ CmdArgs.push_back("-ftrapv-handler");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);
+
+ // -fno-strict-overflow implies -fwrapv if it isn't disabled, but
+ // -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
+ if (Arg *A = Args.getLastArg(options::OPT_fwrapv,
+ options::OPT_fno_wrapv)) {
+ if (A->getOption().matches(options::OPT_fwrapv))
+ CmdArgs.push_back("-fwrapv");
+ } else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
+ options::OPT_fno_strict_overflow)) {
+ 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,
+ options::OPT_fno_unroll_loops);
+
+ Args.AddLastArg(CmdArgs, options::OPT_pthread);
+
+
+ // -stack-protector=0 is default.
+ unsigned StackProtectorLevel = 0;
+ if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+ options::OPT_fstack_protector_all,
+ options::OPT_fstack_protector_strong,
+ options::OPT_fstack_protector)) {
+ if (A->getOption().matches(options::OPT_fstack_protector)) {
+ StackProtectorLevel = std::max<unsigned>(LangOptions::SSPOn,
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext));
+ } else if (A->getOption().matches(options::OPT_fstack_protector_strong))
+ StackProtectorLevel = LangOptions::SSPStrong;
+ else if (A->getOption().matches(options::OPT_fstack_protector_all))
+ StackProtectorLevel = LangOptions::SSPReq;
+ } else {
+ StackProtectorLevel =
+ getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
+ }
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector");
+ CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
+ }
+
+ // --param ssp-buffer-size=
+ for (arg_iterator it = Args.filtered_begin(options::OPT__param),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ StringRef Str((*it)->getValue());
+ if (Str.startswith("ssp-buffer-size=")) {
+ if (StackProtectorLevel) {
+ CmdArgs.push_back("-stack-protector-buffer-size");
+ // FIXME: Verify the argument is a valid integer.
+ CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
+ }
+ (*it)->claim();
+ }
+ }
+
+ // Translate -mstackrealign
+ if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
+ false)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-force-align-stack");
+ }
+ if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign,
+ false)) {
+ CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
+ }
+
+ if (Args.hasArg(options::OPT_mstack_alignment)) {
+ StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
+ CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
+ }
+ // -mkernel implies -mstrict-align; don't add the redundant option.
+ 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");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-strict-align");
+ else
+ CmdArgs.push_back("-arm-strict-align");
+ } else {
+ CmdArgs.push_back("-backend-option");
+ if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("-aarch64-no-strict-align");
+ else
+ 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");
+ }
+ } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb)) {
+ // Windows on ARM expects restricted IT blocks
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-restrict-it");
+ }
+
+ if (TT.getArch() == llvm::Triple::arm ||
+ TT.getArch() == llvm::Triple::thumb) {
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mlong_calls)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-long-calls");
+ }
+ }
+ }
+
+ // 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))
+ CmdArgs.push_back("-fapple-kext");
+ if (!Args.hasArg(options::OPT_fbuiltin))
+ CmdArgs.push_back("-fno-builtin");
+ Args.ClaimAllArgs(options::OPT_fno_builtin);
+ }
+ // -fbuiltin is default.
+ else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
+ CmdArgs.push_back("-fno-builtin");
+
+ if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new))
+ CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+ // -fblocks=0 is default.
+ if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
+ getToolChain().IsBlocksDefault()) ||
+ (Args.hasArg(options::OPT_fgnu_runtime) &&
+ Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
+ !Args.hasArg(options::OPT_fno_blocks))) {
+ CmdArgs.push_back("-fblocks");
+
+ if (!Args.hasArg(options::OPT_fgnu_runtime) &&
+ !getToolChain().hasBlocksRuntime())
+ CmdArgs.push_back("-fblocks-runtime-optional");
+ }
+
+ // -fmodules enables modules (off by default). However, for C++/Objective-C++,
+ // users must also pass -fcxx-modules. The latter flag will disappear once the
+ // modules implementation is solid for C++/Objective-C++ programs as well.
+ bool HaveModules = false;
+ if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
+ bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
+ options::OPT_fno_cxx_modules,
+ false);
+ if (AllowedInCXX || !types::isCXX(InputType)) {
+ CmdArgs.push_back("-fmodules");
+ HaveModules = true;
+ }
+ }
+
+ // -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");
+ }
+
+ // -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
+ // all #included headers are part of modules.
+ if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
+ options::OPT_fno_modules_strict_decluse,
+ false)) {
+ CmdArgs.push_back("-fmodules-strict-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->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->render(Args, CmdArgs);
+
+ // -fmodule-cache-path specifies where our module files should be written.
+ SmallString<128> ModuleCachePath;
+ if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
+ ModuleCachePath = A->getValue();
+ if (HaveModules) {
+ if (C.isForDiagnostics()) {
+ // When generating crash reports, we want to emit the modules along with
+ // the reproduction sources, so we ignore any provided module path.
+ ModuleCachePath = Output.getFilename();
+ llvm::sys::path::replace_extension(ModuleCachePath, ".cache");
+ llvm::sys::path::append(ModuleCachePath, "modules");
+ } else if (ModuleCachePath.empty()) {
+ // No module path was provided: use the default.
+ llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
+ ModuleCachePath);
+ llvm::sys::path::append(ModuleCachePath, "org.llvm.clang");
+ llvm::sys::path::append(ModuleCachePath, "ModuleCache");
+ }
+ const char Arg[] = "-fmodules-cache-path=";
+ ModuleCachePath.insert(ModuleCachePath.begin(), Arg, Arg + strlen(Arg));
+ CmdArgs.push_back(Args.MakeArgString(ModuleCachePath));
+ }
+
+ // When building modules and generating crashdumps, we need to dump a module
+ // dependency VFS alongside the output.
+ if (HaveModules && C.isForDiagnostics()) {
+ SmallString<128> VFSDir(Output.getFilename());
+ llvm::sys::path::replace_extension(VFSDir, ".cache");
+ llvm::sys::path::append(VFSDir, "vfs");
+ CmdArgs.push_back("-module-dependency-dir");
+ CmdArgs.push_back(Args.MakeArgString(VFSDir));
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_fmodules_user_build_path))
+ if (HaveModules)
+ A->render(Args, CmdArgs);
+
+ // Pass through all -fmodules-ignore-macro arguments.
+ Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
+
+ Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
+
+ if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
+ if (!Args.getLastArg(options::OPT_fbuild_session_timestamp))
+ D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
+
+ Args.AddLastArg(CmdArgs,
+ options::OPT_fmodules_validate_once_per_build_session);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
+
+ // -faccess-control is default.
+ if (Args.hasFlag(options::OPT_fno_access_control,
+ options::OPT_faccess_control,
+ false))
+ CmdArgs.push_back("-fno-access-control");
+
+ // -felide-constructors is the default.
+ if (Args.hasFlag(options::OPT_fno_elide_constructors,
+ options::OPT_felide_constructors,
+ false))
+ CmdArgs.push_back("-fno-elide-constructors");
+
+ // -frtti is default.
+ if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
+ KernelOrKext) {
+ CmdArgs.push_back("-fno-rtti");
+
+ // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
+ if (Sanitize.sanitizesVptr()) {
+ std::string NoRttiArg =
+ Args.getLastArg(options::OPT_mkernel,
+ options::OPT_fapple_kext,
+ options::OPT_fno_rtti)->getAsString(Args);
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize=vptr" << NoRttiArg;
+ }
+ }
+
+ // -fshort-enums=0 is default for all architectures except Hexagon.
+ if (Args.hasFlag(options::OPT_fshort_enums,
+ options::OPT_fno_short_enums,
+ getToolChain().getArch() ==
+ llvm::Triple::hexagon))
+ CmdArgs.push_back("-fshort-enums");
+
+ // -fsigned-char is default.
+ if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char,
+ isSignedCharDefault(getToolChain().getTriple())))
+ CmdArgs.push_back("-fno-signed-char");
+
+ // -fthreadsafe-static is default.
+ if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
+ options::OPT_fno_threadsafe_statics))
+ 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,
+ !IsWindowsCygnus && !IsWindowsGNU &&
+ getToolChain().getArch() != llvm::Triple::hexagon &&
+ getToolChain().getArch() != llvm::Triple::xcore) ||
+ KernelOrKext)
+ CmdArgs.push_back("-fno-use-cxa-atexit");
+
+ // -fms-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ IsWindowsMSVC))
+ CmdArgs.push_back("-fms-extensions");
+
+ // -fms-compatibility=0 is default.
+ if (Args.hasFlag(options::OPT_fms_compatibility,
+ options::OPT_fno_ms_compatibility,
+ (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
+ options::OPT_fno_ms_extensions,
+ true))))
+ CmdArgs.push_back("-fms-compatibility");
+
+ // -fms-compatibility-version=17.00 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) ||
+ Args.hasArg(options::OPT_fms_compatibility_version)) {
+ const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
+ const Arg *MSCompatibilityVersion =
+ Args.getLastArg(options::OPT_fms_compatibility_version);
+
+ if (MSCVersion && MSCompatibilityVersion)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << MSCVersion->getAsString(Args)
+ << MSCompatibilityVersion->getAsString(Args);
+
+ std::string Ver;
+ if (MSCompatibilityVersion)
+ Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version);
+ else if (MSCVersion)
+ Ver = getMSCompatibilityVersion(MSCVersion->getValue());
+
+ if (Ver.empty())
+ CmdArgs.push_back("-fms-compatibility-version=17.00");
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
+ }
+
+ // -fno-borland-extensions is default.
+ if (Args.hasFlag(options::OPT_fborland_extensions,
+ options::OPT_fno_borland_extensions, false))
+ CmdArgs.push_back("-fborland-extensions");
+
+ // -fno-delayed-template-parsing is default, except for Windows where MSVC STL
+ // needs it.
+ if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
+ options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
+ CmdArgs.push_back("-fdelayed-template-parsing");
+
+ // -fgnu-keywords default varies depending on language; only pass if
+ // specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
+ options::OPT_fno_gnu_keywords))
+ A->render(Args, CmdArgs);
+
+ if (Args.hasFlag(options::OPT_fgnu89_inline,
+ options::OPT_fno_gnu89_inline,
+ false))
+ CmdArgs.push_back("-fgnu89-inline");
+
+ if (Args.hasArg(options::OPT_fno_inline))
+ CmdArgs.push_back("-fno-inline");
+
+ if (Args.hasArg(options::OPT_fno_inline_functions))
+ CmdArgs.push_back("-fno-inline-functions");
+
+ ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
+
+ // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
+ // legacy is the default. Except for deployment taget of 10.5,
+ // next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
+ // gets ignored silently.
+ if (objcRuntime.isNonFragile()) {
+ if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
+ options::OPT_fno_objc_legacy_dispatch,
+ objcRuntime.isLegacyDispatchDefaultForArch(
+ getToolChain().getArch()))) {
+ if (getToolChain().UseObjCMixedDispatch())
+ CmdArgs.push_back("-fobjc-dispatch-method=mixed");
+ else
+ CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
+ }
+ }
+
+ // 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");
+ }
+
+ // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
+ // NOTE: This logic is duplicated in ToolChains.cpp.
+ bool ARC = isObjCAutoRefCount(Args);
+ if (ARC) {
+ getToolChain().CheckObjCARC();
+
+ CmdArgs.push_back("-fobjc-arc");
+
+ // FIXME: It seems like this entire block, and several around it should be
+ // wrapped in isObjC, but for now we just use it here as this is where it
+ // was being used previously.
+ if (types::isCXX(InputType) && types::isObjC(InputType)) {
+ if (getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+ CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
+ else
+ CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
+ }
+
+ // Allow the user to enable full exceptions code emission.
+ // We define off for Objective-CC, on for Objective-C++.
+ if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
+ options::OPT_fno_objc_arc_exceptions,
+ /*default*/ types::isCXX(InputType)))
+ CmdArgs.push_back("-fobjc-arc-exceptions");
+ }
+
+ // -fobjc-infer-related-result-type is the default, except in the Objective-C
+ // rewriter.
+ if (rewriteKind != RK_None)
+ CmdArgs.push_back("-fno-objc-infer-related-result-type");
+
+ // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
+ // takes precedence.
+ const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
+ if (!GCArg)
+ GCArg = Args.getLastArg(options::OPT_fobjc_gc);
+ if (GCArg) {
+ if (ARC) {
+ D.Diag(diag::err_drv_objc_gc_arr)
+ << GCArg->getAsString(Args);
+ } else if (getToolChain().SupportsObjCGC()) {
+ GCArg->render(Args, CmdArgs);
+ } else {
+ // FIXME: We should move this to a hard error.
+ D.Diag(diag::warn_drv_objc_gc_unsupported)
+ << GCArg->getAsString(Args);
+ }
+ }
+
+ // Handle GCC-style exception args.
+ if (!C.getDriver().IsCLMode())
+ addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
+ objcRuntime, CmdArgs);
+
+ if (getToolChain().UseSjLjExceptions())
+ CmdArgs.push_back("-fsjlj-exceptions");
+
+ // C++ "sane" operator new.
+ if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new))
+ CmdArgs.push_back("-fno-assume-sane-operator-new");
+
+ // -fconstant-cfstrings is default, and may be subject to argument translation
+ // on Darwin.
+ if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
+ options::OPT_fno_constant_cfstrings) ||
+ !Args.hasFlag(options::OPT_mconstant_cfstrings,
+ options::OPT_mno_constant_cfstrings))
+ CmdArgs.push_back("-fno-constant-cfstrings");
+
+ // -fshort-wchar default varies depending on platform; only
+ // pass if specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
+ options::OPT_fno_short_wchar))
+ A->render(Args, CmdArgs);
+
+ // -fno-pascal-strings is default, only pass non-default.
+ if (Args.hasFlag(options::OPT_fpascal_strings,
+ options::OPT_fno_pascal_strings,
+ false))
+ CmdArgs.push_back("-fpascal-strings");
+
+ // Honor -fpack-struct= and -fpack-struct, if given. Note that
+ // -fno-pack-struct doesn't apply to -fpack-struct=.
+ if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
+ std::string PackStructStr = "-fpack-struct=";
+ PackStructStr += A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(PackStructStr));
+ } else if (Args.hasFlag(options::OPT_fpack_struct,
+ options::OPT_fno_pack_struct, false)) {
+ CmdArgs.push_back("-fpack-struct=1");
+ }
+
+ if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) {
+ if (!Args.hasArg(options::OPT_fcommon))
+ CmdArgs.push_back("-fno-common");
+ Args.ClaimAllArgs(options::OPT_fno_common);
+ }
+
+ // -fcommon is default, only pass non-default.
+ else if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common))
+ CmdArgs.push_back("-fno-common");
+
+ // -fsigned-bitfields is default, and clang doesn't yet support
+ // -funsigned-bitfields.
+ if (!Args.hasFlag(options::OPT_fsigned_bitfields,
+ options::OPT_funsigned_bitfields))
+ D.Diag(diag::warn_drv_clang_unsupported)
+ << Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
+
+ // -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
+ if (!Args.hasFlag(options::OPT_ffor_scope,
+ options::OPT_fno_for_scope))
+ D.Diag(diag::err_drv_clang_unsupported)
+ << Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
+
+ // -finput_charset=UTF-8 is default. Reject others
+ if (Arg *inputCharset = Args.getLastArg(
+ options::OPT_finput_charset_EQ)) {
+ StringRef value = inputCharset->getValue();
+ if (value != "UTF-8")
+ D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value;
+ }
+
+ // -fcaret-diagnostics is default.
+ if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
+ options::OPT_fno_caret_diagnostics, true))
+ CmdArgs.push_back("-fno-caret-diagnostics");
+
+ // -fdiagnostics-fixit-info is default, only pass non-default.
+ if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
+ options::OPT_fno_diagnostics_fixit_info))
+ CmdArgs.push_back("-fno-diagnostics-fixit-info");
+
+ // Enable -fdiagnostics-show-option by default.
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option))
+ CmdArgs.push_back("-fdiagnostics-show-option");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-show-category");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
+ CmdArgs.push_back("-fdiagnostics-format");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (Arg *A = Args.getLastArg(
+ options::OPT_fdiagnostics_show_note_include_stack,
+ options::OPT_fno_diagnostics_show_note_include_stack)) {
+ if (A->getOption().matches(
+ options::OPT_fdiagnostics_show_note_include_stack))
+ CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
+ else
+ CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
+ }
+
+ // Color diagnostics are the default, unless the terminal doesn't support
+ // them.
+ // Support both clang's -f[no-]color-diagnostics and gcc's
+ // -f[no-]diagnostics-colors[=never|always|auto].
+ enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto;
+ for (const auto &Arg : Args) {
+ const Option &O = Arg->getOption();
+ if (!O.matches(options::OPT_fcolor_diagnostics) &&
+ !O.matches(options::OPT_fdiagnostics_color) &&
+ !O.matches(options::OPT_fno_color_diagnostics) &&
+ !O.matches(options::OPT_fno_diagnostics_color) &&
+ !O.matches(options::OPT_fdiagnostics_color_EQ))
+ continue;
+
+ Arg->claim();
+ if (O.matches(options::OPT_fcolor_diagnostics) ||
+ O.matches(options::OPT_fdiagnostics_color)) {
+ ShowColors = Colors_On;
+ } else if (O.matches(options::OPT_fno_color_diagnostics) ||
+ O.matches(options::OPT_fno_diagnostics_color)) {
+ ShowColors = Colors_Off;
+ } else {
+ assert(O.matches(options::OPT_fdiagnostics_color_EQ));
+ StringRef value(Arg->getValue());
+ if (value == "always")
+ ShowColors = Colors_On;
+ else if (value == "never")
+ ShowColors = Colors_Off;
+ else if (value == "auto")
+ ShowColors = Colors_Auto;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << ("-fdiagnostics-color=" + value).str();
+ }
+ }
+ if (ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
+ CmdArgs.push_back("-fcolor-diagnostics");
+
+ if (Args.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");
+
+ if (!Args.hasFlag(options::OPT_fshow_column,
+ options::OPT_fno_show_column,
+ true))
+ CmdArgs.push_back("-fno-show-column");
+
+ if (!Args.hasFlag(options::OPT_fspell_checking,
+ options::OPT_fno_spell_checking))
+ CmdArgs.push_back("-fno-spell-checking");
+
+
+ // -fno-asm-blocks is default.
+ if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
+ false))
+ CmdArgs.push_back("-fasm-blocks");
+
+ // 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, false);
+ OptSpecifier VectorizeAliasOption = EnableVec ? options::OPT_O_Group :
+ options::OPT_fvectorize;
+ if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
+ options::OPT_fno_vectorize, EnableVec))
+ CmdArgs.push_back("-vectorize-loops");
+
+ // -fslp-vectorize is enabled based on the optimization level selected.
+ bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
+ OptSpecifier SLPVectAliasOption = EnableSLPVec ? options::OPT_O_Group :
+ options::OPT_fslp_vectorize;
+ if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
+ options::OPT_fno_slp_vectorize, EnableSLPVec))
+ 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("-vectorize-slp-aggressive");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
+ A->render(Args, CmdArgs);
+
+ // -fdollars-in-identifiers default varies depending on platform and
+ // language; only pass if specified.
+ if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
+ options::OPT_fno_dollars_in_identifiers)) {
+ if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
+ CmdArgs.push_back("-fdollars-in-identifiers");
+ else
+ CmdArgs.push_back("-fno-dollars-in-identifiers");
+ }
+
+ // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
+ // practical purposes.
+ if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
+ options::OPT_fno_unit_at_a_time)) {
+ if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
+ D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
+ }
+
+ if (Args.hasFlag(options::OPT_fapple_pragma_pack,
+ 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().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))
+ CmdArgs.push_back("-fno-builtin-strcpy");
+ }
+#endif
+
+ // Enable rewrite includes if the user's asked for it or if we're generating
+ // diagnostics.
+ // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
+ // nice to enable this when doing a crashdump for modules as well.
+ if (Args.hasFlag(options::OPT_frewrite_includes,
+ options::OPT_fno_rewrite_includes, false) ||
+ (C.isForDiagnostics() && !HaveModules))
+ CmdArgs.push_back("-frewrite-includes");
+
+ // Only allow -traditional or -traditional-cpp outside in preprocessing modes.
+ if (Arg *A = Args.getLastArg(options::OPT_traditional,
+ options::OPT_traditional_cpp)) {
+ if (isa<PreprocessJobAction>(JA))
+ CmdArgs.push_back("-traditional-cpp");
+ else
+ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_dM);
+ Args.AddLastArg(CmdArgs, options::OPT_dD);
+
+ // Handle serialized diagnostics.
+ if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
+ CmdArgs.push_back("-serialize-diagnostic-file");
+ CmdArgs.push_back(Args.MakeArgString(A->getValue()));
+ }
+
+ if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
+ CmdArgs.push_back("-fretain-comments-from-system-headers");
+
+ // Forward -fcomment-block-commands to -cc1.
+ Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
+ // Forward -fparse-all-comments to -cc1.
+ Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);
+
+ // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
+ // parser.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
+ for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+
+ // We translate this by hand to the -cc1 argument, since nightly test uses
+ // it and developers have been trained to spell it with -mllvm.
+ if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns")
+ CmdArgs.push_back("-disable-llvm-optzns");
+ else
+ (*it)->render(Args, CmdArgs);
+ }
+
+ if (Output.getType() == types::TY_Dependencies) {
+ // Handled with other dependency code.
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ for (const auto &II : Inputs) {
+ addDashXForInput(Args, II, CmdArgs);
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_undef);
+
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+
+ // Optionally embed the -cc1 level arguments into the debug info, for build
+ // analysis.
+ if (getToolChain().UseDwarfDebugFlags()) {
+ ArgStringList OriginalArgs;
+ for (const auto &Arg : Args)
+ Arg->render(Args, OriginalArgs);
+
+ SmallString<256> Flags;
+ Flags += Exec;
+ for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+ Flags += " ";
+ Flags += OriginalArgs[i];
+ }
+ CmdArgs.push_back("-dwarf-debug-flags");
+ CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+ }
+
+ // 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().isOSLinux() &&
+ (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
+ const char *SplitDwarfOut;
+ if (SplitDwarf) {
+ CmdArgs.push_back("-split-dwarf-file");
+ SplitDwarfOut = SplitDebugName(Args, Inputs);
+ CmdArgs.push_back(SplitDwarfOut);
+ }
+
+ // Finally add the compile command to the compilation.
+ if (Args.hasArg(options::OPT__SLASH_fallback) &&
+ Output.getType() == types::TY_Object &&
+ (InputType == types::TY_C || InputType == types::TY_CXX)) {
+ Command *CLCommand = getCLFallback()->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.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (SplitDwarf && !isa<CompileJobAction>(JA))
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);
+
+ if (Arg *A = Args.getLastArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fomit-frame-pointer" << A->getAsString(Args);
+
+ // Claim some arguments which clang supports automatically.
+
+ // -fpch-preprocess is used with gcc to add a special marker in the output to
+ // include the PCH file. Clang's PTH solution is completely transparent, so we
+ // do not need to deal with it at all.
+ Args.ClaimAllArgs(options::OPT_fpch_preprocess);
+
+ // Claim some arguments which clang doesn't support, but we don't
+ // care to warn the user about.
+ Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
+ Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
+
+ // Disable warnings for clang -E -emit-llvm foo.c
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+}
+
+/// Add options related to the Objective-C runtime/ABI.
+///
+/// Returns true if the runtime is non-fragile.
+ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
+ ArgStringList &cmdArgs,
+ RewriteKind rewriteKind) const {
+ // Look for the controlling runtime option.
+ Arg *runtimeArg = args.getLastArg(options::OPT_fnext_runtime,
+ options::OPT_fgnu_runtime,
+ options::OPT_fobjc_runtime_EQ);
+
+ // Just forward -fobjc-runtime= to the frontend. This supercedes
+ // options about fragility.
+ if (runtimeArg &&
+ runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
+ ObjCRuntime runtime;
+ StringRef value = runtimeArg->getValue();
+ if (runtime.tryParse(value)) {
+ getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
+ << value;
+ }
+
+ runtimeArg->render(args, cmdArgs);
+ return runtime;
+ }
+
+ // Otherwise, we'll need the ABI "version". Version numbers are
+ // slightly confusing for historical reasons:
+ // 1 - Traditional "fragile" ABI
+ // 2 - Non-fragile ABI, version 1
+ // 3 - Non-fragile ABI, version 2
+ unsigned objcABIVersion = 1;
+ // If -fobjc-abi-version= is present, use that to set the version.
+ if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
+ StringRef value = abiArg->getValue();
+ if (value == "1")
+ objcABIVersion = 1;
+ else if (value == "2")
+ objcABIVersion = 2;
+ else if (value == "3")
+ objcABIVersion = 3;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << value;
+ } else {
+ // Otherwise, determine if we are using the non-fragile ABI.
+ bool nonFragileABIIsDefault =
+ (rewriteKind == RK_NonFragile ||
+ (rewriteKind == RK_None &&
+ getToolChain().IsObjCNonFragileABIDefault()));
+ if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
+ options::OPT_fno_objc_nonfragile_abi,
+ nonFragileABIIsDefault)) {
+ // Determine the non-fragile ABI version to use.
+#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
+ unsigned nonFragileABIVersion = 1;
+#else
+ unsigned nonFragileABIVersion = 2;
+#endif
+
+ if (Arg *abiArg = args.getLastArg(
+ options::OPT_fobjc_nonfragile_abi_version_EQ)) {
+ StringRef value = abiArg->getValue();
+ if (value == "1")
+ nonFragileABIVersion = 1;
+ else if (value == "2")
+ nonFragileABIVersion = 2;
+ else
+ getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
+ << value;
+ }
+
+ objcABIVersion = 1 + nonFragileABIVersion;
+ } else {
+ objcABIVersion = 1;
+ }
+ }
+
+ // We don't actually care about the ABI version other than whether
+ // it's non-fragile.
+ bool isNonFragile = objcABIVersion != 1;
+
+ // If we have no runtime argument, ask the toolchain for its default runtime.
+ // However, the rewriter only really supports the Mac runtime, so assume that.
+ ObjCRuntime runtime;
+ if (!runtimeArg) {
+ switch (rewriteKind) {
+ case RK_None:
+ runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
+ break;
+ case RK_Fragile:
+ runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
+ break;
+ case RK_NonFragile:
+ runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
+ break;
+ }
+
+ // -fnext-runtime
+ } else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
+ // On Darwin, make this use the default behavior for the toolchain.
+ if (getToolChain().getTriple().isOSDarwin()) {
+ runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
+
+ // Otherwise, build for a generic macosx port.
+ } else {
+ runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
+ }
+
+ // -fgnu-runtime
+ } else {
+ assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
+ // Legacy behaviour is to target the gnustep runtime if we are i
+ // non-fragile mode or the GCC runtime in fragile mode.
+ if (isNonFragile)
+ runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(1,6));
+ else
+ runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
+ }
+
+ cmdArgs.push_back(args.MakeArgString(
+ "-fobjc-runtime=" + runtime.getAsString()));
+ return runtime;
+}
+
+static bool maybeConsumeDash(const std::string &EH, size_t &I) {
+ bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
+ I += HaveDash;
+ return !HaveDash;
+}
+
+struct EHFlags {
+ EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
+ bool Synch;
+ bool Asynch;
+ bool NoExceptC;
+};
+
+/// /EH controls whether to run destructor cleanups when exceptions are
+/// thrown. There are three modifiers:
+/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions.
+/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions.
+/// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
+/// - c: Assume that extern "C" functions are implicitly noexcept. This
+/// modifier is an optimization, so we ignore it for now.
+/// The default is /EHs-c-, meaning cleanups are disabled.
+static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
+ EHFlags EH;
+ std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
+ for (auto EHVal : EHArgs) {
+ for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
+ switch (EHVal[I]) {
+ case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
+ case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
+ case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
+ default: break;
+ }
+ D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
+ break;
+ }
+ }
+ return EH;
+}
+
+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");
+
+ // Both /showIncludes and /E (and /EP) write to stdout. Allowing both
+ // would produce interleaved output, so ignore /showIncludes in such cases.
+ if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_EP))
+ if (Arg *A = Args.getLastArg(options::OPT_show_includes))
+ A->render(Args, CmdArgs);
+
+ // This controls whether or not we emit RTTI data for polymorphic types.
+ if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
+ /*default=*/false))
+ CmdArgs.push_back("-fno-rtti-data");
+
+ const Driver &D = getToolChain().getDriver();
+ EHFlags EH = parseClangCLEHFlags(D, Args);
+ // FIXME: Do something with NoExceptC.
+ if (EH.Synch || EH.Asynch) {
+ CmdArgs.push_back("-fexceptions");
+ CmdArgs.push_back("-fcxx-exceptions");
+ }
+
+ // /EP should expand to -E -P.
+ if (Args.hasArg(options::OPT__SLASH_EP)) {
+ CmdArgs.push_back("-E");
+ CmdArgs.push_back("-P");
+ }
+
+ Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
+ Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
+ if (MostGeneralArg && BestCaseArg)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);
+
+ if (MostGeneralArg) {
+ Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
+ Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
+ Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);
+
+ Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
+ Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
+ if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << FirstConflict->getAsString(Args)
+ << SecondConflict->getAsString(Args);
+
+ if (SingleArg)
+ CmdArgs.push_back("-fms-memptr-rep=single");
+ else if (MultipleArg)
+ CmdArgs.push_back("-fms-memptr-rep=multiple");
+ else
+ CmdArgs.push_back("-fms-memptr-rep=virtual");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
+ 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");
+ }
+}
+
+visualstudio::Compile *Clang::getCLFallback() const {
+ if (!CLFallback)
+ CLFallback.reset(new visualstudio::Compile(getToolChain()));
+ return CLFallback.get();
+}
+
+void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+
+ // Don't warn about "clang -w -c foo.s"
+ Args.ClaimAllArgs(options::OPT_w);
+ // and "clang -emit-llvm -c foo.s"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+
+ // Invoke ourselves in -cc1as mode.
+ //
+ // FIXME: Implement custom jobs for internal actions.
+ CmdArgs.push_back("-cc1as");
+
+ // Add the "effective" target triple.
+ CmdArgs.push_back("-triple");
+ std::string TripleStr =
+ getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ // Set the output mode, we currently only expect to be used as a real
+ // assembler.
+ CmdArgs.push_back("-filetype");
+ CmdArgs.push_back("obj");
+
+ // Set the main file name, so that debug info works even with
+ // -save-temps or preprocessed assembly.
+ CmdArgs.push_back("-main-file-name");
+ CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs));
+
+ // 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, true);
+
+ // Ignore explicit -force_cpusubtype_ALL option.
+ (void) Args.hasArg(options::OPT_force__cpusubtype__ALL);
+
+ // Determine the original source input.
+ const Action *SourceAction = &JA;
+ while (SourceAction->getKind() != Action::InputClass) {
+ assert(!SourceAction->getInputs().empty() && "unexpected root action!");
+ SourceAction = SourceAction->getInputs()[0];
+ }
+
+ // Forward -g and handle debug info related flags, assuming we are dealing
+ // with an actual assembly file.
+ if (SourceAction->getType() == types::TY_Asm ||
+ SourceAction->getType() == types::TY_PP_Asm) {
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("-g");
+
+ if (Args.hasArg(options::OPT_gdwarf_2))
+ CmdArgs.push_back("-gdwarf-2");
+ if (Args.hasArg(options::OPT_gdwarf_3))
+ CmdArgs.push_back("-gdwarf-3");
+ if (Args.hasArg(options::OPT_gdwarf_4))
+ CmdArgs.push_back("-gdwarf-4");
+
+ // Add the -fdebug-compilation-dir flag if needed.
+ addDebugCompDirArg(Args, CmdArgs);
+
+ // Set the AT_producer to the clang version when using the integrated
+ // assembler on assembly source files.
+ CmdArgs.push_back("-dwarf-debug-producer");
+ CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
+ }
+
+ // Optionally embed the -cc1as level arguments into the debug info, for build
+ // analysis.
+ if (getToolChain().UseDwarfDebugFlags()) {
+ ArgStringList OriginalArgs;
+ for (const auto &Arg : Args)
+ Arg->render(Args, OriginalArgs);
+
+ SmallString<256> Flags;
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ Flags += Exec;
+ for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
+ Flags += " ";
+ Flags += OriginalArgs[i];
+ }
+ CmdArgs.push_back("-dwarf-debug-flags");
+ CmdArgs.push_back(Args.MakeArgString(Flags.str()));
+ }
+
+ // FIXME: Add -static support, once we have it.
+
+ // Consume all the warning flags. Usually this would be handled more
+ // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
+ // doesn't handle that so rather than warning about unused flags that are
+ // actually used, we'll lie by omission instead.
+ // FIXME: Stop lying and consume only the appropriate driver flags
+ for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group),
+ ie = Args.filtered_end();
+ it != ie; ++it)
+ (*it)->claim();
+
+ CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
+ getToolChain().getDriver());
+
+ Args.AddAllArgs(CmdArgs, options::OPT_mllvm);
+
+ assert(Output.isFilename() && "Unexpected lipo output.");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+
+ // Handle the debug info splitting at object creation time if we're
+ // creating an object.
+ // TODO: Currently only works on linux with newer objcopy.
+ if (Args.hasArg(options::OPT_gsplit_dwarf) &&
+ getToolChain().getTriple().isOSLinux())
+ SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
+ SplitDebugName(Args, Inputs));
+}
+
+void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ for (const auto &A : Args) {
+ if (forwardToGCC(A->getOption())) {
+ // Don't forward any -g arguments to assembly steps.
+ if (isa<AssembleJobAction>(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
+ // to get to the assembler.
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ RenderExtraToolArgs(JA, CmdArgs);
+
+ // If using a driver driver, force the arch.
+ llvm::Triple::ArchType Arch = getToolChain().getArch();
+ if (getToolChain().getTriple().isOSDarwin()) {
+ CmdArgs.push_back("-arch");
+
+ // FIXME: Remove these special cases.
+ if (Arch == llvm::Triple::ppc)
+ 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()));
+ }
+
+ // Try to force gcc to match the tool chain we want, if we recognize
+ // the arch.
+ //
+ // FIXME: The triple class should directly provide the information we want
+ // 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 ||
+ Arch == llvm::Triple::ppc64le)
+ CmdArgs.push_back("-m64");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Unexpected output");
+ CmdArgs.push_back("-fsyntax-only");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ // Only pass -x if gcc will understand it; otherwise hope gcc
+ // understands the suffix correctly. The main use case this would go
+ // wrong in is for linker inputs if they happened to have an odd
+ // suffix; really the only way to get this to happen is a command
+ // like '-x foobar a.c' which will treat a.c like a linker input.
+ //
+ // FIXME: For the linker case specifically, can we safely convert
+ // inputs into '-Wl,' options?
+ for (const auto &II : Inputs) {
+ // Don't try to pass LLVM or AST inputs to a generic gcc.
+ if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ D.Diag(diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_AST)
+ D.Diag(diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_ModuleFile)
+ D.Diag(diag::err_drv_no_module_support)
+ << getToolChain().getTripleString();
+
+ if (types::canTypeBeUserSpecified(II.getType())) {
+ CmdArgs.push_back("-x");
+ CmdArgs.push_back(types::getTypeName(II.getType()));
+ }
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else {
+ const Arg &A = II.getInputArg();
+
+ // Reverse translate some rewritten options.
+ if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) {
+ CmdArgs.push_back("-lstdc++");
+ continue;
+ }
+
+ // Don't render as input, we need gcc to do the translations.
+ A.render(Args, CmdArgs);
+ }
+ }
+
+ const std::string customGCCName = D.getCCCGenericGCCName();
+ const char *GCCName;
+ if (!customGCCName.empty())
+ GCCName = customGCCName.c_str();
+ else if (D.CCCIsCXX()) {
+ GCCName = "g++";
+ } else
+ GCCName = "gcc";
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-E");
+}
+
+void gcc::Compile::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
+ // If -flto, etc. are present then make sure not to force assembly output.
+ if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
+ JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
+ CmdArgs.push_back("-c");
+ else {
+ if (JA.getType() != types::TY_PP_Asm)
+ D.Diag(diag::err_drv_invalid_gcc_output_type)
+ << getTypeName(JA.getType());
+
+ CmdArgs.push_back("-S");
+ }
+}
+
+void gcc::Link::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ // The types are (hopefully) good enough.
+}
+
+// Hexagon tools start.
+void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+
+}
+void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ std::string MarchString = "-march=";
+ MarchString += toolchains::Hexagon_TC::GetTargetCPU(Args);
+ CmdArgs.push_back(Args.MakeArgString(MarchString));
+
+ RenderExtraToolArgs(JA, CmdArgs);
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Unexpected output");
+ CmdArgs.push_back("-fsyntax-only");
+ }
+
+ std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
+ if (!SmallDataThreshold.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-G") + SmallDataThreshold));
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ // Only pass -x if gcc will understand it; otherwise hope gcc
+ // understands the suffix correctly. The main use case this would go
+ // wrong in is for linker inputs if they happened to have an odd
+ // suffix; really the only way to get this to happen is a command
+ // like '-x foobar a.c' which will treat a.c like a linker input.
+ //
+ // FIXME: For the linker case specifically, can we safely convert
+ // inputs into '-Wl,' options?
+ for (const auto &II : Inputs) {
+ // Don't try to pass LLVM or AST inputs to a generic gcc.
+ if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_AST)
+ D.Diag(clang::diag::err_drv_no_ast_support)
+ << getToolChain().getTripleString();
+ else if (II.getType() == types::TY_ModuleFile)
+ D.Diag(diag::err_drv_no_module_support)
+ << getToolChain().getTripleString();
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ?
+ II.getInputArg().render(Args, CmdArgs);
+ }
+
+ const char *GCCName = "hexagon-as";
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void hexagon::Link::RenderExtraToolArgs(const JobAction &JA,
+ ArgStringList &CmdArgs) const {
+ // The types are (hopefully) good enough.
+}
+
+void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ const toolchains::Hexagon_TC& ToolChain =
+ static_cast<const toolchains::Hexagon_TC&>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+
+ ArgStringList CmdArgs;
+
+ //----------------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------------
+ bool hasStaticArg = Args.hasArg(options::OPT_static);
+ bool buildingLib = Args.hasArg(options::OPT_shared);
+ bool buildPIE = Args.hasArg(options::OPT_pie);
+ bool incStdLib = !Args.hasArg(options::OPT_nostdlib);
+ bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles);
+ bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
+ bool useShared = buildingLib && !hasStaticArg;
+
+ //----------------------------------------------------------------------------
+ // Silence warnings for various options
+ //----------------------------------------------------------------------------
+
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_static_libgcc);
+
+ //----------------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------------
+ for (const auto &Opt : ToolChain.ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
+
+ std::string MarchString = toolchains::Hexagon_TC::GetTargetCPU(Args);
+ CmdArgs.push_back(Args.MakeArgString("-m" + MarchString));
+
+ if (buildingLib) {
+ CmdArgs.push_back("-shared");
+ CmdArgs.push_back("-call_shared"); // should be the default, but doing as
+ // hexagon-gcc does
+ }
+
+ if (hasStaticArg)
+ CmdArgs.push_back("-static");
+
+ if (buildPIE && !buildingLib)
+ CmdArgs.push_back("-pie");
+
+ std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args);
+ if (!SmallDataThreshold.empty()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-G") + SmallDataThreshold));
+ }
+
+ //----------------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------------
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ const std::string MarchSuffix = "/" + MarchString;
+ const std::string G0Suffix = "/G0";
+ const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
+ const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir)
+ + "/";
+ const std::string StartFilesDir = RootDir
+ + "hexagon/lib"
+ + (buildingLib
+ ? MarchG0Suffix : MarchSuffix);
+
+ //----------------------------------------------------------------------------
+ // moslib
+ //----------------------------------------------------------------------------
+ std::vector<std::string> oslibs;
+ bool hasStandalone= false;
+
+ for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ (*it)->claim();
+ oslibs.push_back((*it)->getValue());
+ hasStandalone = hasStandalone || (oslibs.back() == "standalone");
+ }
+ if (oslibs.empty()) {
+ oslibs.push_back("standalone");
+ hasStandalone = true;
+ }
+
+ //----------------------------------------------------------------------------
+ // Start Files
+ //----------------------------------------------------------------------------
+ if (incStdLib && incStartFiles) {
+
+ if (!buildingLib) {
+ if (hasStandalone) {
+ CmdArgs.push_back(
+ Args.MakeArgString(StartFilesDir + "/crt0_standalone.o"));
+ }
+ CmdArgs.push_back(Args.MakeArgString(StartFilesDir + "/crt0.o"));
+ }
+ std::string initObj = useShared ? "/initS.o" : "/init.o";
+ CmdArgs.push_back(Args.MakeArgString(StartFilesDir + initObj));
+ }
+
+ //----------------------------------------------------------------------------
+ // Library Search Paths
+ //----------------------------------------------------------------------------
+ const ToolChain::path_list &LibPaths = ToolChain.getFilePaths();
+ for (const auto &LibPath : LibPaths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+
+ //----------------------------------------------------------------------------
+ //
+ //----------------------------------------------------------------------------
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ //----------------------------------------------------------------------------
+ // Libraries
+ //----------------------------------------------------------------------------
+ if (incStdLib && incDefLibs) {
+ if (D.CCCIsCXX()) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ CmdArgs.push_back("--start-group");
+
+ if (!buildingLib) {
+ for(std::vector<std::string>::iterator i = oslibs.begin(),
+ e = oslibs.end(); i != e; ++i)
+ CmdArgs.push_back(Args.MakeArgString("-l" + *i));
+ CmdArgs.push_back("-lc");
+ }
+ CmdArgs.push_back("-lgcc");
+
+ CmdArgs.push_back("--end-group");
+ }
+
+ //----------------------------------------------------------------------------
+ // End files
+ //----------------------------------------------------------------------------
+ if (incStdLib && incStartFiles) {
+ std::string finiObj = useShared ? "/finiS.o" : "/fini.o";
+ CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj));
+ }
+
+ std::string Linker = ToolChain.GetProgramPath("hexagon-ld");
+ C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs));
+}
+// Hexagon tools end.
+
+/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
+const char *arm::getARMCPUForMArch(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue();
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ // Handle -march=native.
+ if (MArch == "native") {
+ std::string CPU = llvm::sys::getHostCPUName();
+ if (CPU != "generic") {
+ // Translate the native cpu into the architecture. The switch below will
+ // then chose the minimum cpu for that arch.
+ MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU);
+ }
+ }
+
+ return Triple.getARMCPUForArch(MArch);
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
+StringRef arm::getARMTargetCPU(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 getARMCPUForMArch(Args, Triple);
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+const char *arm::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")
+ .Cases("arm940t", "ep9312","v4t")
+ .Cases("arm10tdmi", "arm1020t", "v5")
+ .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e")
+ .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e")
+ .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e")
+ .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6")
+ .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
+ .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
+ .Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "v7")
+ .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "v7")
+ .Cases("cortex-r4", "cortex-r5", "v7r")
+ .Case("cortex-m0", "v6m")
+ .Case("cortex-m3", "v7m")
+ .Case("cortex-m4", "v7em")
+ .Case("swift", "v7s")
+ .Case("cyclone", "v8")
+ .Cases("cortex-a53", "cortex-a57", "v8")
+ .Default("");
+}
+
+bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
+ Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
+ return A && (A->getValue() == StringRef(Value));
+}
+
+bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
+ if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
+ return llvm::StringSwitch<bool>(NaNArg->getValue())
+ .Case("2008", true)
+ .Case("legacy", false)
+ .Default(false);
+
+ // NaN2008 is the default for MIPS32r6/MIPS64r6.
+ return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
+ .Cases("mips32r6", "mips64r6", true)
+ .Default(false);
+
+ return false;
+}
+
+bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
+ StringRef ABIName) {
+ if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
+ Triple.getVendor() != llvm::Triple::MipsTechnologies)
+ return false;
+
+ if (ABIName != "32")
+ return false;
+
+ return llvm::StringSwitch<bool>(CPUName)
+ .Cases("mips2", "mips3", "mips4", "mips5", true)
+ .Cases("mips32", "mips32r2", true)
+ .Cases("mips64", "mips64r2", true)
+ .Default(false);
+}
+
+llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
+ // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
+ // archs which Darwin doesn't use.
+
+ // The matching this routine does is fairly pointless, since it is neither the
+ // complete architecture list, nor a reasonable subset. The problem is that
+ // historically the driver driver accepts this and also ties its -march=
+ // handling to the architecture name, so we need to be careful before removing
+ // support for it.
+
+ // This code must be kept in sync with Clang's Darwin specific argument
+ // translation.
+
+ return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
+ .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
+ .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
+ .Case("ppc64", llvm::Triple::ppc64)
+ .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
+ .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
+ llvm::Triple::x86)
+ .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", "armv7k", "armv7m", llvm::Triple::arm)
+ .Cases("armv7s", "xscale", llvm::Triple::arm)
+ .Case("arm64", llvm::Triple::arm64)
+ .Case("r600", llvm::Triple::r600)
+ .Case("nvptx", llvm::Triple::nvptx)
+ .Case("nvptx64", llvm::Triple::nvptx64)
+ .Case("amdil", llvm::Triple::amdil)
+ .Case("spir", llvm::Triple::spir)
+ .Default(llvm::Triple::UnknownArch);
+}
+
+void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
+ llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
+ T.setArch(Arch);
+
+ if (Str == "x86_64h")
+ T.setArchName(Str);
+ else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
+ T.setOS(llvm::Triple::UnknownOS);
+ T.setObjectFormat(llvm::Triple::MachO);
+ }
+}
+
+const char *Clang::getBaseInputName(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ return Args.MakeArgString(
+ llvm::sys::path::filename(Inputs[0].getBaseInput()));
+}
+
+const char *Clang::getBaseInputStem(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ const char *Str = getBaseInputName(Args, Inputs);
+
+ if (const char *End = strrchr(Str, '.'))
+ return Args.MakeArgString(std::string(Str, End));
+
+ return Str;
+}
+
+const char *Clang::getDependencyFileName(const ArgList &Args,
+ const InputInfoList &Inputs) {
+ // FIXME: Think about this more.
+ std::string Res;
+
+ if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+ std::string Str(OutputOpt->getValue());
+ Res = Str.substr(0, Str.rfind('.'));
+ } else {
+ Res = getBaseInputStem(Args, Inputs);
+ }
+ return Args.MakeArgString(Res + ".d");
+}
+
+void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+
+ // Determine the original source input.
+ const Action *SourceAction = &JA;
+ while (SourceAction->getKind() != Action::InputClass) {
+ assert(!SourceAction->getInputs().empty() && "unexpected root action!");
+ SourceAction = SourceAction->getInputs()[0];
+ }
+
+ // If -fno_integrated_as is used add -Q to the darwin assember driver to make
+ // sure it runs its system assembler not clang's integrated assembler.
+ // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
+ // FIXME: at run-time detect assembler capabilities or rely on version
+ // information forwarded by -target-assembler-version (future)
+ if (Args.hasArg(options::OPT_fno_integrated_as)) {
+ const llvm::Triple &T(getToolChain().getTriple());
+ if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
+ 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) {
+ if (Args.hasArg(options::OPT_gstabs))
+ CmdArgs.push_back("--gstabs");
+ else if (Args.hasArg(options::OPT_g_Group))
+ CmdArgs.push_back("-g");
+ }
+
+ // Derived from asm spec.
+ AddMachOArch(Args, CmdArgs);
+
+ // Use -force_cpusubtype_ALL on x86 by default.
+ 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().getArch() != llvm::Triple::x86_64 &&
+ (((Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext)) &&
+ getMachOToolChain().isKernelStatic()) ||
+ Args.hasArg(options::OPT_static)))
+ CmdArgs.push_back("-static");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ assert(Output.isFilename() && "Unexpected lipo output.");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ // asm_final spec is empty.
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::MachOTool::anchor() {}
+
+void darwin::MachOTool::AddMachOArch(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
+
+ // Derived from darwin_arch spec.
+ CmdArgs.push_back("-arch");
+ CmdArgs.push_back(Args.MakeArgString(ArchName));
+
+ // FIXME: Is this needed anymore?
+ if (ArchName == "arm")
+ CmdArgs.push_back("-force_cpusubtype_ALL");
+}
+
+bool darwin::Link::NeedsTempPath(const InputInfoList &Inputs) const {
+ // We only need to generate a temp path for LTO if we aren't compiling object
+ // files. When compiling source files, we run 'dsymutil' after linking. We
+ // don't run 'dsymutil' when compiling object files.
+ for (const auto &Input : Inputs)
+ if (Input.getType() != types::TY_Object)
+ return true;
+
+ return false;
+}
+
+void darwin::Link::AddLinkArgs(Compilation &C,
+ const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const InputInfoList &Inputs) const {
+ const Driver &D = getToolChain().getDriver();
+ const toolchains::MachO &MachOTC = getMachOToolChain();
+
+ unsigned Version[3] = { 0, 0, 0 };
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(), Version[0],
+ Version[1], Version[2], HadExtra) ||
+ HadExtra)
+ D.Diag(diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ }
+
+ // Newer linkers support -demangle. Pass it if supported and not disabled by
+ // the user.
+ if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("-demangle");
+
+ 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.
+ if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
+ const char *TmpPath = C.getArgs().MakeArgString(
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
+ C.addTempFile(TmpPath);
+ CmdArgs.push_back("-object_path_lto");
+ CmdArgs.push_back(TmpPath);
+ }
+
+ // Derived from the "link" spec.
+ Args.AddAllArgs(CmdArgs, options::OPT_static);
+ if (!Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-dynamic");
+ if (Args.hasArg(options::OPT_fgnu_runtime)) {
+ // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
+ // here. How do we wish to handle such things?
+ }
+
+ if (!Args.hasArg(options::OPT_dynamiclib)) {
+ AddMachOArch(Args, CmdArgs);
+ // FIXME: Why do this only on this path?
+ Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
+
+ Args.AddLastArg(CmdArgs, options::OPT_bundle);
+ Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
+ Args.AddAllArgs(CmdArgs, options::OPT_client__name);
+
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
+ (A = Args.getLastArg(options::OPT_current__version)) ||
+ (A = Args.getLastArg(options::OPT_install__name)))
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-dynamiclib";
+
+ Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
+ Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
+ Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
+ } else {
+ CmdArgs.push_back("-dylib");
+
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_bundle)) ||
+ (A = Args.getLastArg(options::OPT_bundle__loader)) ||
+ (A = Args.getLastArg(options::OPT_client__name)) ||
+ (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
+ (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
+ (A = Args.getLastArg(options::OPT_private__bundle)))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-dynamiclib";
+
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
+ "-dylib_compatibility_version");
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
+ "-dylib_current_version");
+
+ AddMachOArch(Args, CmdArgs);
+
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
+ "-dylib_install_name");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_all__load);
+ Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
+ Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
+ if (MachOTC.isTargetIOSBased())
+ Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
+ Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
+ Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
+ Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
+ Args.AddLastArg(CmdArgs, options::OPT_dynamic);
+ Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
+ Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
+ Args.AddAllArgs(CmdArgs, options::OPT_force__load);
+ Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
+ Args.AddAllArgs(CmdArgs, options::OPT_image__base);
+ Args.AddAllArgs(CmdArgs, options::OPT_init);
+
+ // Add the deployment target.
+ MachOTC.addMinVersionArgs(Args, CmdArgs);
+
+ Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
+ Args.AddLastArg(CmdArgs, options::OPT_multi__module);
+ Args.AddLastArg(CmdArgs, options::OPT_single__module);
+ Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
+ Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
+
+ if (const Arg *A = Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
+ options::OPT_fno_pie,
+ options::OPT_fno_PIE)) {
+ if (A->getOption().matches(options::OPT_fpie) ||
+ A->getOption().matches(options::OPT_fPIE))
+ CmdArgs.push_back("-pie");
+ else
+ CmdArgs.push_back("-no_pie");
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_prebind);
+ Args.AddLastArg(CmdArgs, options::OPT_noprebind);
+ Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
+ Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
+ Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segprot);
+ Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
+ Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
+ Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
+ Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
+
+ // Give --sysroot= preference, over the Apple specific behavior to also use
+ // --isysroot as the syslibroot.
+ StringRef sysroot = C.getSysRoot();
+ if (sysroot != "") {
+ CmdArgs.push_back("-syslibroot");
+ CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
+ } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ CmdArgs.push_back("-syslibroot");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
+ Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
+ Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
+ Args.AddAllArgs(CmdArgs, options::OPT_undefined);
+ Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
+ Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
+ Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_y);
+ Args.AddLastArg(CmdArgs, options::OPT_w);
+ Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
+ Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
+ Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
+ Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
+ Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
+ Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
+ Args.AddLastArg(CmdArgs, options::OPT_whyload);
+ Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
+ Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
+ Args.AddLastArg(CmdArgs, options::OPT_dylinker);
+ Args.AddLastArg(CmdArgs, options::OPT_Mach);
+}
+
+enum LibOpenMP {
+ LibUnknown,
+ LibGOMP,
+ LibIOMP5
+};
+
+void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
+
+ // The logic here is derived from gcc's behavior; most of which
+ // comes from specs (starting with link_command). Consult gcc for
+ // more information.
+ ArgStringList CmdArgs;
+
+ /// Hack(tm) to ignore linking errors when we are doing ARC migration.
+ if (Args.hasArg(options::OPT_ccc_arcmt_check,
+ options::OPT_ccc_arcmt_migrate)) {
+ for (const auto &Arg : Args)
+ Arg->claim();
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("touch"));
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ return;
+ }
+
+ // I'm not sure why this particular decomposition exists in gcc, but
+ // we follow suite for ease of comparison.
+ AddLinkArgs(C, Args, CmdArgs, Inputs);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_d_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ 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_r);
+
+ // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
+ // members of static archive libraries which implement Objective-C classes or
+ // categories.
+ if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
+ CmdArgs.push_back("-ObjC");
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles))
+ getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+
+ LibOpenMP UsedOpenMPLib = LibUnknown;
+ if (Args.hasArg(options::OPT_fopenmp)) {
+ UsedOpenMPLib = LibGOMP;
+ } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
+ UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
+ .Case("libgomp", LibGOMP)
+ .Case("libiomp5", LibIOMP5)
+ .Default(LibUnknown);
+ if (UsedOpenMPLib == LibUnknown)
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ }
+ switch (UsedOpenMPLib) {
+ case LibGOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case LibIOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case LibUnknown:
+ break;
+ }
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (isObjCRuntimeLinked(Args) &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // We use arclite library for both ARC and subscripting support.
+ getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
+
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("Foundation");
+ // Link libobj.
+ CmdArgs.push_back("-lobjc");
+ }
+
+ if (LinkingOutput) {
+ CmdArgs.push_back("-arch_multiple");
+ CmdArgs.push_back("-final_output");
+ CmdArgs.push_back(LinkingOutput);
+ }
+
+ if (Args.hasArg(options::OPT_fnested_functions))
+ CmdArgs.push_back("-allow_stack_execute");
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (getToolChain().getDriver().CCCIsCXX())
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+
+ // link_ssp spec is empty.
+
+ // Let the tool chain choose which runtime library to link.
+ getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs);
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ // endfile_spec is empty.
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_F);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-create");
+ assert(Output.isFilename() && "Unexpected lipo output.");
+
+ CmdArgs.push_back("-output");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs) {
+ assert(II.isFilename() && "Unexpected lipo input.");
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::Dsymutil::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());
+
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Unexpected dsymutil input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+ CmdArgs.push_back("--verify");
+ CmdArgs.push_back("--debug-info");
+ CmdArgs.push_back("--eh-frame");
+ CmdArgs.push_back("--quiet");
+
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Unexpected verify input");
+
+ // Grabbing the output of the earlier dsymutil run.
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ // FIXME: Find a real GCC, don't hard-code versions here
+ std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/";
+ const llvm::Triple &T = getToolChain().getTriple();
+ 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:
+ llvm_unreachable("Unsupported architecture");
+ }
+
+ ArgStringList CmdArgs;
+
+ // Demangle C++ names in errors
+ CmdArgs.push_back("-C");
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("_start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("-dn");
+ } else {
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("--dynamic-linker");
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1"));
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o"));
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
+ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o"));
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o"));
+ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o"));
+ }
+ if (getToolChain().getDriver().CCCIsCXX())
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o"));
+ }
+
+ CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (getToolChain().getDriver().CCCIsCXX())
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lgcc_s");
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lm");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o"));
+ }
+ CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o"));
+
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("_start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ CmdArgs.push_back("-dn");
+ } else {
+// CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("--dynamic-linker");
+ CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtn.o")));
+ }
+
+ CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/"
+ + getToolChain().getTripleString()
+ + "/4.2.4"));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-pthread");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ }
+
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+ bool NeedsKPIC = false;
+
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
+ // When building 32-bit code on OpenBSD/amd64, we have to explicitly
+ // instruct as in the base system to assemble 32-bit code.
+ CmdArgs.push_back("--32");
+ break;
+
+ case llvm::Triple::ppc:
+ CmdArgs.push_back("-mppc");
+ CmdArgs.push_back("-many");
+ break;
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-32");
+ NeedsKPIC = true;
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9a");
+ NeedsKPIC = true;
+ break;
+
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::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");
+
+ NeedsKPIC = true;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (NeedsKPIC)
+ addAssemblerKPIC(Args, CmdArgs);
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // 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");
+ CmdArgs.push_back("__start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld.so");
+ }
+ }
+
+ if (Args.hasArg(options::OPT_nopie))
+ CmdArgs.push_back("-nopie");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt0.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ std::string Triple = getToolChain().getTripleString();
+ if (Triple.substr(0, 6) == "x86_64")
+ Triple.replace(0, 6, "amd64");
+ CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
+ "/4.2.1"));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX()) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+
+ // FIXME: For some reason GCC passes -lgcc before adding
+ // the default system libraries. Just mimic this for now.
+ CmdArgs.push_back("-lgcc");
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (!Args.hasArg(options::OPT_shared) &&
+ Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lc_p");
+ else
+ CmdArgs.push_back("-lc");
+ }
+
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if ((!Args.hasArg(options::OPT_nostdlib)) &&
+ (!Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("__start");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ CmdArgs.push_back("-Bdynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld.so");
+ }
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt0.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX()) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (!Args.hasArg(options::OPT_shared) &&
+ Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lc_p");
+ else
+ CmdArgs.push_back("-lc");
+ }
+
+ 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) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // When building 32-bit code on FreeBSD/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("-a32");
+ else 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;
+ mips::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");
+
+ addAssemblerKPIC(Args, CmdArgs);
+ } else if (getToolChain().getArch() == llvm::Triple::arm ||
+ getToolChain().getArch() == llvm::Triple::armeb ||
+ getToolChain().getArch() == llvm::Triple::thumb ||
+ getToolChain().getArch() == llvm::Triple::thumbeb) {
+ const Driver &D = getToolChain().getDriver();
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple);
+
+ if (FloatABI == "hard") {
+ CmdArgs.push_back("-mfpu=vfp");
+ } else {
+ CmdArgs.push_back("-mfpu=softvfp");
+ }
+
+ switch(getToolChain().getTriple().getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::EABI:
+ CmdArgs.push_back("-meabi=5");
+ break;
+
+ default:
+ CmdArgs.push_back("-matpcs");
+ }
+ } else if (getToolChain().getArch() == llvm::Triple::sparc ||
+ getToolChain().getArch() == llvm::Triple::sparcv9) {
+ if (getToolChain().getArch() == llvm::Triple::sparc)
+ CmdArgs.push_back("-Av8plusa");
+ else
+ CmdArgs.push_back("-Av9a");
+
+ addAssemblerKPIC(Args, CmdArgs);
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::FreeBSD& ToolChain =
+ static_cast<const toolchains::FreeBSD&>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const bool IsPIE =
+ !Args.hasArg(options::OPT_shared) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (IsPIE)
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld-elf.so.1");
+ }
+ if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
+ llvm::Triple::ArchType Arch = ToolChain.getArch();
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
+ Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ CmdArgs.push_back("--hash-style=both");
+ }
+ }
+ CmdArgs.push_back("--enable-new-dtags");
+ }
+
+ // When building 32-bit code on FreeBSD/amd64, we have to explicitly
+ // instruct ld in the base system to link 32-bit code.
+ if (ToolChain.getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386_fbsd");
+ }
+
+ if (ToolChain.getArch() == llvm::Triple::ppc) {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32ppc_fbsd");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crt1 = nullptr;
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (IsPIE)
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin = nullptr;
+ if (Args.hasArg(options::OPT_static))
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared) || IsPIE)
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ const ToolChain::path_list Paths = ToolChain.getFilePaths();
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (D.IsUsingLTO(Args))
+ AddGoldPlugin(ToolChain, Args, CmdArgs);
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX()) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+ // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+ // the default system libraries. Just mimic this for now.
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgcc_p");
+ else
+ CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ else
+ CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lgcc_p");
+ } else {
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_shared) || IsPIE)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+
+ addProfileRT(ToolChain, Args, CmdArgs);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // GNU as needs different flags for creating the correct output format
+ // on architectures with different ABIs or optional feature sets.
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
+ CmdArgs.push_back("--32");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb: {
+ std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple()));
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch));
+ break;
+ }
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el: {
+ StringRef CPUName;
+ StringRef ABIName;
+ mips::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");
+
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+ }
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-32");
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9");
+ addAssemblerKPIC(Args, CmdArgs);
+ break;
+
+ default:
+ break;
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld.elf_so");
+ }
+ }
+
+ // Many NetBSD architectures support more than one ABI.
+ // Determine the correct emulation for ld.
+ switch (getToolChain().getArch()) {
+ case llvm::Triple::x86:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386");
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ CmdArgs.push_back("-m");
+ switch (getToolChain().getTriple().getEnvironment()) {
+ case llvm::Triple::EABI:
+ case llvm::Triple::GNUEABI:
+ CmdArgs.push_back("armelf_nbsd_eabi");
+ break;
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABIHF:
+ CmdArgs.push_back("armelf_nbsd_eabihf");
+ break;
+ default:
+ CmdArgs.push_back("armelf_nbsd");
+ break;
+ }
+ break;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ if (mips::hasMipsAbiArg(Args, "32")) {
+ CmdArgs.push_back("-m");
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("elf32btsmip");
+ else
+ CmdArgs.push_back("elf32ltsmip");
+ } else if (mips::hasMipsAbiArg(Args, "64")) {
+ CmdArgs.push_back("-m");
+ if (getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("elf64btsmip");
+ else
+ CmdArgs.push_back("elf64ltsmip");
+ }
+ break;
+
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32_sparc");
+ break;
+
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf64_sparc");
+ break;
+
+ default:
+ break;
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ unsigned Major, Minor, Micro;
+ getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
+ bool useLibgcc = true;
+ if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) {
+ switch(getToolChain().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ useLibgcc = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX()) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lc");
+
+ 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");
+ }
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtn.o")));
+ }
+
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+ bool NeedsKPIC = false;
+
+ // Add --32/--64 to make sure we get the format we want.
+ // This is incomplete
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("--32");
+ } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+ if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ CmdArgs.push_back("--x32");
+ else
+ CmdArgs.push_back("--64");
+ } else if (getToolChain().getArch() == llvm::Triple::ppc) {
+ CmdArgs.push_back("-a32");
+ CmdArgs.push_back("-mppc");
+ CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::ppc64) {
+ 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("-mppc64");
+ CmdArgs.push_back("-many");
+ CmdArgs.push_back("-mlittle-endian");
+ } else if (getToolChain().getArch() == llvm::Triple::sparc) {
+ CmdArgs.push_back("-32");
+ CmdArgs.push_back("-Av8plusa");
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9a");
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::arm ||
+ getToolChain().getArch() == llvm::Triple::armeb) {
+ 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" ||
+ MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a")
+ CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8");
+
+ StringRef ARMFloatABI = tools::arm::getARMFloatABI(
+ getToolChain().getDriver(), Args, getToolChain().getTriple());
+ CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI));
+
+ Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
+
+ // FIXME: remove krait check when GNU tools support krait cpu
+ // for now replace it with -march=armv7-a to avoid a lower
+ // march from being picked in the absence of a cpu flag.
+ Arg *A;
+ if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
+ StringRef(A->getValue()) == "krait")
+ CmdArgs.push_back("-march=armv7-a");
+ else
+ Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
+ } else 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;
+ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ ABIName = getGnuCompatibleMipsABIName(ABIName);
+
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(CPUName.data());
+
+ CmdArgs.push_back("-mabi");
+ CmdArgs.push_back(ABIName.data());
+
+ // -mno-shared should be emitted unless -fpic, -fpie, -fPIC, -fPIE,
+ // or -mshared (not implemented) is in effect.
+ bool IsPicOrPie = false;
+ if (Arg *A = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+ options::OPT_fpic, options::OPT_fno_pic,
+ options::OPT_fPIE, options::OPT_fno_PIE,
+ options::OPT_fpie, options::OPT_fno_pie)) {
+ if (A->getOption().matches(options::OPT_fPIC) ||
+ A->getOption().matches(options::OPT_fpic) ||
+ A->getOption().matches(options::OPT_fPIE) ||
+ A->getOption().matches(options::OPT_fpie))
+ IsPicOrPie = true;
+ }
+ if (!IsPicOrPie)
+ CmdArgs.push_back("-mno-shared");
+
+ // LLVM doesn't support -mplt yet and acts as if it is always given.
+ // However, -mplt has no effect with the N64 ABI.
+ CmdArgs.push_back(ABIName == "64" ? "-KPIC" : "-call_nonpic");
+
+ if (getToolChain().getArch() == llvm::Triple::mips ||
+ getToolChain().getArch() == llvm::Triple::mips64)
+ CmdArgs.push_back("-EB");
+ 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"));
+ }
+
+ // Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
+ if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
+ options::OPT_mfp64)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
+ ABIName))
+ CmdArgs.push_back("-mfpxx");
+
+ // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
+ // -mno-mips16 is actually -no-mips16.
+ if (Arg *A = Args.getLastArg(options::OPT_mips16,
+ options::OPT_mno_mips16)) {
+ if (A->getOption().matches(options::OPT_mips16)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ } else {
+ A->claim();
+ CmdArgs.push_back("-no-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"));
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
+ options::OPT_msoft_float);
+
+ Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
+ options::OPT_mno_odd_spreg);
+
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::systemz) {
+ // 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));
+ }
+
+ if (NeedsKPIC)
+ addAssemblerKPIC(Args, CmdArgs);
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ 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(const llvm::Triple &Triple, const Driver &D,
+ ArgStringList &CmdArgs, const ArgList &Args) {
+ bool isAndroid = Triple.getEnvironment() == llvm::Triple::Android;
+ bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
+ Args.hasArg(options::OPT_static);
+ if (!D.CCCIsCXX())
+ CmdArgs.push_back("-lgcc");
+
+ if (StaticLibgcc || isAndroid) {
+ if (D.CCCIsCXX())
+ CmdArgs.push_back("-lgcc");
+ } else {
+ if (!D.CCCIsCXX())
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ if (!D.CCCIsCXX())
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (StaticLibgcc && !isAndroid)
+ CmdArgs.push_back("-lgcc_eh");
+ 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
+ // linking with non-static libgcc.
+ //
+ // NOTE: This fixes a link error on Android MIPS as well. The non-static
+ // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
+ if (isAndroid && !StaticLibgcc)
+ CmdArgs.push_back("-ldl");
+}
+
+static StringRef getLinuxDynamicLinker(const ArgList &Args,
+ const toolchains::Linux &ToolChain) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) {
+ if (ToolChain.getTriple().isArch64Bit())
+ return "/system/bin/linker64";
+ else
+ return "/system/bin/linker";
+ } else if (ToolChain.getArch() == llvm::Triple::x86 ||
+ ToolChain.getArch() == llvm::Triple::sparc)
+ return "/lib/ld-linux.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
+ ToolChain.getArch() == llvm::Triple::arm64)
+ return "/lib/ld-linux-aarch64.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
+ return "/lib/ld-linux-aarch64_be.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::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb) {
+ if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
+ return "/lib/ld-linux-armhf.so.3"; /* TODO: check which dynamic linker name. */
+ else
+ return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */
+ } else if (ToolChain.getArch() == llvm::Triple::mips ||
+ ToolChain.getArch() == llvm::Triple::mipsel) {
+ if (mips::isNaN2008(Args, ToolChain.getTriple()))
+ return "/lib/ld-linux-mipsn8.so.1";
+ return "/lib/ld.so.1";
+ } else if (ToolChain.getArch() == llvm::Triple::mips64 ||
+ ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (mips::hasMipsAbiArg(Args, "n32"))
+ return mips::isNaN2008(Args, ToolChain.getTriple())
+ ? "/lib32/ld-linux-mipsn8.so.1" : "/lib32/ld.so.1";
+ return mips::isNaN2008(Args, ToolChain.getTriple())
+ ? "/lib64/ld-linux-mipsn8.so.1" : "/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::systemz)
+ return "/lib64/ld64.so.1";
+ else if (ToolChain.getArch() == llvm::Triple::ppc64le)
+ return "/lib64/ld64.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::sparcv9)
+ return "/lib64/ld-linux.so.2";
+ else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ return "/libx32/ld-linux-x32.so.2";
+ else
+ return "/lib64/ld-linux-x86-64.so.2";
+}
+
+static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
+ ArgStringList &CmdArgs, const ArgList &Args) {
+ // Make use of compiler-rt if --rtlib option is used
+ ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);
+
+ switch(RLT) {
+ case ToolChain::RLT_CompilerRT:
+ addClangRTLinux(TC, Args, CmdArgs);
+ break;
+ case ToolChain::RLT_Libgcc:
+ AddLibgcc(TC.getTriple(), D, CmdArgs, Args);
+ break;
+ }
+}
+
+void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::Linux& ToolChain =
+ static_cast<const toolchains::Linux&>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const bool isAndroid =
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::Android;
+ const bool IsPIE =
+ !Args.hasArg(options::OPT_shared) &&
+ !Args.hasArg(options::OPT_static) &&
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() ||
+ // On Android every code is PIC so every executable is PIE
+ // Cannot use isPIEDefault here since otherwise
+ // PIE only logic will be enabled during compilation
+ isAndroid);
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (IsPIE)
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ for (const auto &Opt : ToolChain.ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
+
+ if (!Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--eh-frame-hdr");
+ }
+
+ CmdArgs.push_back("-m");
+ if (ToolChain.getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("elf_i386");
+ else if (ToolChain.getArch() == llvm::Triple::aarch64 ||
+ ToolChain.getArch() == llvm::Triple::arm64)
+ CmdArgs.push_back("aarch64linux");
+ else if (ToolChain.getArch() == llvm::Triple::aarch64_be ||
+ ToolChain.getArch() == llvm::Triple::arm64_be)
+ CmdArgs.push_back("aarch64_be_linux");
+ else if (ToolChain.getArch() == llvm::Triple::arm
+ || ToolChain.getArch() == llvm::Triple::thumb)
+ CmdArgs.push_back("armelf_linux_eabi");
+ else if (ToolChain.getArch() == llvm::Triple::armeb
+ || ToolChain.getArch() == llvm::Triple::thumbeb)
+ CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME. */
+ else if (ToolChain.getArch() == llvm::Triple::ppc)
+ CmdArgs.push_back("elf32ppclinux");
+ else if (ToolChain.getArch() == llvm::Triple::ppc64)
+ CmdArgs.push_back("elf64ppc");
+ else if (ToolChain.getArch() == llvm::Triple::ppc64le)
+ CmdArgs.push_back("elf64lppc");
+ else if (ToolChain.getArch() == llvm::Triple::sparc)
+ CmdArgs.push_back("elf32_sparc");
+ else if (ToolChain.getArch() == llvm::Triple::sparcv9)
+ CmdArgs.push_back("elf64_sparc");
+ else if (ToolChain.getArch() == llvm::Triple::mips)
+ CmdArgs.push_back("elf32btsmip");
+ else if (ToolChain.getArch() == llvm::Triple::mipsel)
+ CmdArgs.push_back("elf32ltsmip");
+ else if (ToolChain.getArch() == llvm::Triple::mips64) {
+ if (mips::hasMipsAbiArg(Args, "n32"))
+ CmdArgs.push_back("elf32btsmipn32");
+ else
+ CmdArgs.push_back("elf64btsmip");
+ }
+ else if (ToolChain.getArch() == llvm::Triple::mips64el) {
+ if (mips::hasMipsAbiArg(Args, "n32"))
+ CmdArgs.push_back("elf32ltsmipn32");
+ else
+ CmdArgs.push_back("elf64ltsmip");
+ }
+ else if (ToolChain.getArch() == llvm::Triple::systemz)
+ CmdArgs.push_back("elf64_s390");
+ else if (ToolChain.getArch() == llvm::Triple::x86_64 &&
+ ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ CmdArgs.push_back("elf32_x86_64");
+ else
+ CmdArgs.push_back("elf_x86_64");
+
+ if (Args.hasArg(options::OPT_static)) {
+ if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb)
+ CmdArgs.push_back("-Bstatic");
+ else
+ CmdArgs.push_back("-static");
+ } else if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ }
+
+ if (ToolChain.getArch() == llvm::Triple::arm ||
+ ToolChain.getArch() == llvm::Triple::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb ||
+ (!Args.hasArg(options::OPT_static) &&
+ !Args.hasArg(options::OPT_shared))) {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back(Args.MakeArgString(
+ D.DyldPrefix + getLinuxDynamicLinker(Args, ToolChain)));
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!isAndroid) {
+ const char *crt1 = nullptr;
+ if (!Args.hasArg(options::OPT_shared)){
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (IsPIE)
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ }
+
+ const char *crtbegin;
+ if (Args.hasArg(options::OPT_static))
+ crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared))
+ crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
+ else if (IsPIE)
+ crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
+ else
+ crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+
+ // Add crtfastmath.o if available and fast math is enabled.
+ ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
+
+ const ToolChain::path_list Paths = ToolChain.getFilePaths();
+
+ for (const auto &Path : Paths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
+
+ if (D.IsUsingLTO(Args))
+ AddGoldPlugin(ToolChain, Args, CmdArgs);
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+ // The profile runtime also needs access to system libraries.
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ if (D.CCCIsCXX() &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !Args.hasArg(options::OPT_static);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ if (!Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--start-group");
+
+ LibOpenMP UsedOpenMPLib = LibUnknown;
+ if (Args.hasArg(options::OPT_fopenmp)) {
+ UsedOpenMPLib = LibGOMP;
+ } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
+ UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue())
+ .Case("libgomp", LibGOMP)
+ .Case("libiomp5", LibIOMP5)
+ .Default(LibUnknown);
+ if (UsedOpenMPLib == LibUnknown)
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ }
+ switch (UsedOpenMPLib) {
+ case LibGOMP:
+ CmdArgs.push_back("-lgomp");
+
+ // FIXME: Exclude this for platforms with libgomp that don't require
+ // librt. Most modern Linux platforms require it, but some may not.
+ CmdArgs.push_back("-lrt");
+ break;
+ case LibIOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case LibUnknown:
+ break;
+ }
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
+
+ if ((Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) &&
+ !isAndroid)
+ CmdArgs.push_back("-lpthread");
+
+ CmdArgs.push_back("-lc");
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--end-group");
+ else
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
+ }
+
+ if (!Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crtend;
+ if (Args.hasArg(options::OPT_shared))
+ crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
+ else if (IsPIE)
+ crtend = isAndroid ? "crtend_android.o" : "crtendS.o";
+ else
+ crtend = isAndroid ? "crtend_android.o" : "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ if (!isAndroid)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ }
+
+ C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
+}
+
+void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX()) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lCompilerRT-Generic");
+ CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ }
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+/// DragonFly Tools
+
+// For now, DragonFly Assemble does just about the same as for
+// FreeBSD, but this may change soon.
+void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // When building 32-bit code on DragonFly/pc64, 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");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs)
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ bool UseGCC47 = false;
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47))
+ UseGCC47 = false;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-Bshareable");
+ else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
+ }
+ CmdArgs.push_back("--hash-style=both");
+ }
+
+ // When building 32-bit code on DragonFly/pc64, we have to explicitly
+ // instruct ld in the base system to link 32-bit code.
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt1.o")));
+ else {
+ if (Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("Scrt1.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ }
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of
+ // rpaths
+ if (UseGCC47)
+ CmdArgs.push_back("-L/usr/lib/gcc47");
+ else
+ CmdArgs.push_back("-L/usr/lib/gcc44");
+
+ if (!Args.hasArg(options::OPT_static)) {
+ if (UseGCC47) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc47");
+ } else {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back("/usr/lib/gcc44");
+ }
+ }
+
+ if (D.CCCIsCXX()) {
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ if (Args.hasArg(options::OPT_pthread))
+ CmdArgs.push_back("-lpthread");
+
+ if (!Args.hasArg(options::OPT_nolibc)) {
+ CmdArgs.push_back("-lc");
+ }
+
+ if (UseGCC47) {
+ if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_static_libgcc)) {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lgcc_eh");
+ } else {
+ if (Args.hasArg(options::OPT_shared_libgcc)) {
+ CmdArgs.push_back("-lgcc_pic");
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lgcc");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_pic");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+ } else {
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-lgcc_pic");
+ } else {
+ CmdArgs.push_back("-lgcc");
+ }
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtendS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtn.o")));
+ }
+
+ addProfileRT(getToolChain(), Args, CmdArgs);
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const StringRef RTName) {
+ SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
+ llvm::sys::path::append(LibSanitizer,
+ Twine("clang_rt.") + RTName + ".lib");
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+}
+
+void visualstudio::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(Args.MakeArgString(std::string("-out:") +
+ Output.getFilename()));
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles) &&
+ !C.getDriver().IsCLMode()) {
+ CmdArgs.push_back("-defaultlib:libcmt");
+ }
+
+ CmdArgs.push_back("-nologo");
+
+ if (Args.hasArg(options::OPT_g_Group)) {
+ CmdArgs.push_back("-debug");
+ }
+
+ 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"));
+ // FIXME: Handle 64-bit.
+ if (DLL) {
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
+ "asan_dll_thunk-i386");
+ } else {
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
+ addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
+ }
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_l);
+ Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
+
+ // Add filenames immediately.
+ for (const auto &Input : Inputs)
+ if (Input.isFilename())
+ CmdArgs.push_back(Input.getFilename());
+ else
+ Input.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;
+
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ SmallVector<StringRef, 8> PathSegments;
+ llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
+
+ 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 (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
+ /*default=*/false))
+ CmdArgs.push_back("/GR-");
+ if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections))
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
+ ? "/Gy"
+ : "/Gy-");
+ if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
+ options::OPT_fno_data_sections))
+ CmdArgs.push_back(
+ A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
+ if (Args.hasArg(options::OPT_fsyntax_only))
+ CmdArgs.push_back("/Zs");
+ if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only))
+ CmdArgs.push_back("/Z7");
+
+ std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include);
+ for (const auto &Include : Includes)
+ CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
+
+ // Flags that can simply be passed through.
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
+ Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
+
+ // 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_v))
+ CmdArgs.push_back("-v");
+
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("-g");
+
+ if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
+ false))
+ CmdArgs.push_back("-fverbose-asm");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ for (const auto &II : Inputs)
+ 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.");
+ }
+
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("-v");
+
+ ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
+ if (EH.ShouldUseExceptionTables)
+ CmdArgs.push_back("-fexceptions");
+
+ 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
new file mode 100644
index 0000000..4c89676
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h
@@ -0,0 +1,654 @@
+//===--- Tools.h - Tool Implementations -------------------------*- 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_TOOLS_H_
+#define CLANG_LIB_DRIVER_TOOLS_H_
+
+#include "clang/Driver/Tool.h"
+#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 {
+ class MachO;
+}
+
+namespace tools {
+
+namespace visualstudio {
+ class Compile;
+}
+
+using llvm::opt::ArgStringList;
+
+ /// \brief Clang compiler tool.
+ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
+ public:
+ static const char *getBaseInputName(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs);
+ static const char *getBaseInputStem(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs);
+ static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
+ const InputInfoList &Inputs);
+
+ private:
+ void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
+ const Driver &D,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ const InputInfoList &Inputs) const;
+
+ 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 AddARM64TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::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 llvm::opt::ArgList &args,
+ llvm::opt::ArgStringList &cmdArgs,
+ RewriteKind rewrite) const;
+
+ void AddClangCLArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ visualstudio::Compile *getCLFallback() const;
+
+ mutable std::unique_ptr<visualstudio::Compile> CLFallback;
+
+ public:
+ Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ /// \brief Clang integrated assembler tool.
+ class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
+ public:
+ ClangAs(const ToolChain &TC) : Tool("clang::as",
+ "clang integrated assembler", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedAssembler() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ /// gcc - Generic GCC tool implementations.
+namespace gcc {
+ class LLVM_LIBRARY_VISIBILITY Common : public Tool {
+ public:
+ Common(const char *Name, const char *ShortName,
+ const ToolChain &TC) : Tool(Name, ShortName, TC) {}
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+ /// RenderExtraToolArgs - Render any arguments necessary to force
+ /// the particular tool mode.
+ 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",
+ "gcc preprocessor", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedCPP() const override { return false; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Compile : public Common {
+ public:
+ Compile(const ToolChain &TC) : Common("gcc::Compile",
+ "gcc frontend", TC) {}
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public Common {
+ public:
+ Link(const ToolChain &TC) : Common("gcc::Link",
+ "linker (via gcc)", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ };
+} // end namespace gcc
+
+namespace hexagon {
+ // For Hexagon, 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("hexagon::Assemble",
+ "hexagon-as", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("hexagon::Link",
+ "hexagon-ld", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ virtual void RenderExtraToolArgs(const JobAction &JA,
+ llvm::opt::ArgStringList &CmdArgs) const;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace hexagon.
+
+namespace arm {
+ StringRef getARMTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+ const char* getARMCPUForMArch(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+ const char* getLLVMArchSuffixForARM(StringRef CPU);
+}
+
+namespace mips {
+ void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple, StringRef &CPUName,
+ StringRef &ABIName);
+ bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value);
+ bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
+ bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
+ StringRef ABIName);
+}
+
+namespace darwin {
+ llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
+ void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
+
+ class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
+ virtual void anchor();
+ protected:
+ void AddMachOArch(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ const toolchains::MachO &getMachOToolChain() const {
+ return reinterpret_cast<const toolchains::MachO&>(getToolChain());
+ }
+
+ public:
+ MachOTool(const char *Name, const char *ShortName,
+ const ToolChain &TC) : Tool(Name, ShortName, TC) {}
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Assemble : public MachOTool {
+ public:
+ Assemble(const ToolChain &TC) : MachOTool("darwin::Assemble",
+ "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public MachOTool {
+ bool NeedsTempPath(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) : MachOTool("darwin::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
+ public:
+ Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
+ public:
+ Dsymutil(const ToolChain &TC) : MachOTool("darwin::Dsymutil",
+ "dsymutil", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isDsymutilJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
+ public:
+ VerifyDebug(const ToolChain &TC) : MachOTool("darwin::VerifyDebug",
+ "dwarfdump", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+}
+
+ /// openbsd -- Directly call GNU Binutils assembler and linker
+namespace openbsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace openbsd
+
+ /// bitrig -- Directly call GNU Binutils assembler and linker
+namespace bitrig {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("bitrig::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("bitrig::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace bitrig
+
+ /// freebsd -- Directly call GNU Binutils assembler and linker
+namespace freebsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace freebsd
+
+ /// netbsd -- Directly call GNU Binutils assembler and linker
+namespace netbsd {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+
+ public:
+ Assemble(const ToolChain &TC)
+ : Tool("netbsd::Assemble", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+
+ public:
+ Link(const ToolChain &TC)
+ : Tool("netbsd::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace netbsd
+
+ /// Directly call GNU Binutils' assembler and linker.
+namespace gnutools {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("GNU::Assemble", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("GNU::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+}
+ /// minix -- Directly call GNU Binutils assembler and linker
+namespace minix {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("minix::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace minix
+
+ /// solaris -- Directly call Solaris assembler and linker
+namespace solaris {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("solaris::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("solaris::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace solaris
+
+ /// auroraux -- Directly call GNU Binutils assembler and linker
+namespace auroraux {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace auroraux
+
+ /// dragonfly -- Directly call GNU Binutils assembler and linker
+namespace dragonfly {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler",
+ TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace dragonfly
+
+/// Visual studio tools.
+namespace visualstudio {
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Compile : public Tool {
+ public:
+ Compile(const ToolChain &TC) : Tool("visualstudio::Compile", "compiler", TC) {}
+
+ bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+ bool isLinkJob() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+ 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 arm {
+ StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+}
+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) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("XCore::Link",
+ "XCore-ld", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+ };
+} // end namespace XCore.
+
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // CLANG_LIB_DRIVER_TOOLS_H_
diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
new file mode 100644
index 0000000..3538dbc
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp
@@ -0,0 +1,231 @@
+//===--- Types.cpp - Driver input & temporary type information ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Types.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include <cassert>
+#include <string.h>
+
+using namespace clang::driver;
+using namespace clang::driver::types;
+
+struct TypeInfo {
+ const char *Name;
+ const char *Flags;
+ const char *TempSuffix;
+ ID PreprocessedType;
+};
+
+static const TypeInfo TypeInfos[] = {
+#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \
+ { NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, },
+#include "clang/Driver/Types.def"
+#undef TYPE
+};
+static const unsigned numTypes = llvm::array_lengthof(TypeInfos);
+
+static const TypeInfo &getInfo(unsigned id) {
+ assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
+ return TypeInfos[id - 1];
+}
+
+const char *types::getTypeName(ID Id) {
+ return getInfo(Id).Name;
+}
+
+types::ID types::getPreprocessedType(ID Id) {
+ return getInfo(Id).PreprocessedType;
+}
+
+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;
+}
+
+bool types::onlyAssembleType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'a');
+}
+
+bool types::onlyPrecompileType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'p');
+}
+
+bool types::canTypeBeUserSpecified(ID Id) {
+ return strchr(getInfo(Id).Flags, 'u');
+}
+
+bool types::appendSuffixForType(ID Id) {
+ return strchr(getInfo(Id).Flags, 'A');
+}
+
+bool types::canLipoType(ID Id) {
+ return (Id == TY_Nothing ||
+ Id == TY_Image ||
+ Id == TY_Object ||
+ Id == TY_LTO_BC);
+}
+
+bool types::isAcceptedByClang(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_Asm:
+ case TY_C: case TY_PP_C:
+ case TY_CL:
+ case TY_CUDA:
+ case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
+ case TY_CXX: case TY_PP_CXX:
+ case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
+ case TY_CHeader: case TY_PP_CHeader:
+ case TY_CLHeader:
+ case TY_ObjCHeader: case TY_PP_ObjCHeader:
+ case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ case TY_AST: case TY_ModuleFile:
+ case TY_LLVM_IR: case TY_LLVM_BC:
+ return true;
+ }
+}
+
+bool types::isObjC(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
+ case TY_ObjCXX: case TY_PP_ObjCXX:
+ case TY_ObjCHeader: case TY_PP_ObjCHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias:
+ return true;
+ }
+}
+
+bool types::isCXX(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_CXX: case TY_PP_CXX:
+ case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
+ case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ case TY_CUDA:
+ return true;
+ }
+}
+
+types::ID types::lookupTypeForExtension(const char *Ext) {
+ return llvm::StringSwitch<types::ID>(Ext)
+ .Case("c", TY_C)
+ .Case("i", TY_PP_C)
+ .Case("m", TY_ObjC)
+ .Case("M", TY_ObjCXX)
+ .Case("h", TY_CHeader)
+ .Case("C", TY_CXX)
+ .Case("H", TY_CXXHeader)
+ .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)
+ .Case("bc", TY_LLVM_BC)
+ .Case("cc", TY_CXX)
+ .Case("CC", TY_CXX)
+ .Case("cl", TY_CL)
+ .Case("cp", TY_CXX)
+ .Case("cu", TY_CUDA)
+ .Case("hh", TY_CXXHeader)
+ .Case("ll", TY_LLVM_IR)
+ .Case("hpp", TY_CXXHeader)
+ .Case("ads", TY_Ada)
+ .Case("adb", TY_Ada)
+ .Case("ast", TY_AST)
+ .Case("c++", TY_CXX)
+ .Case("C++", TY_CXX)
+ .Case("cxx", TY_CXX)
+ .Case("cpp", TY_CXX)
+ .Case("CPP", TY_CXX)
+ .Case("CXX", TY_CXX)
+ .Case("for", TY_PP_Fortran)
+ .Case("FOR", TY_PP_Fortran)
+ .Case("fpp", TY_Fortran)
+ .Case("FPP", TY_Fortran)
+ .Case("f90", TY_PP_Fortran)
+ .Case("f95", TY_PP_Fortran)
+ .Case("F90", TY_Fortran)
+ .Case("F95", TY_Fortran)
+ .Case("mii", TY_PP_ObjCXX)
+ .Case("pcm", TY_ModuleFile)
+ .Case("pch", TY_PCH)
+ .Case("gch", TY_PCH)
+ .Default(TY_INVALID);
+}
+
+types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
+ for (unsigned i=0; i<numTypes; ++i) {
+ types::ID Id = (types::ID) (i + 1);
+ if (canTypeBeUserSpecified(Id) &&
+ strcmp(Name, getInfo(Id).Name) == 0)
+ return Id;
+ }
+
+ return TY_INVALID;
+}
+
+// FIXME: Why don't we just put this list in the defs file, eh.
+void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
+ if (Id != TY_Object) {
+ if (getPreprocessedType(Id) != TY_INVALID) {
+ P.push_back(phases::Preprocess);
+ }
+
+ if (onlyPrecompileType(Id)) {
+ P.push_back(phases::Precompile);
+ } else {
+ if (!onlyAssembleType(Id)) {
+ P.push_back(phases::Compile);
+ }
+ P.push_back(phases::Assemble);
+ }
+ }
+ if (!onlyPrecompileType(Id)) {
+ P.push_back(phases::Link);
+ }
+ assert(0 < P.size() && "Not enough phases in list");
+ assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
+ return;
+}
+
+ID types::lookupCXXTypeForCType(ID Id) {
+ switch (Id) {
+ default:
+ return Id;
+
+ case types::TY_C:
+ return types::TY_CXX;
+ case types::TY_PP_C:
+ return types::TY_PP_CXX;
+ case types::TY_CHeader:
+ return types::TY_CXXHeader;
+ case types::TY_PP_CHeader:
+ return types::TY_PP_CXXHeader;
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
new file mode 100644
index 0000000..913425a
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp
@@ -0,0 +1,338 @@
+//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ToolChains.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
+
+// Include the necessary headers to interface with the Windows registry and
+// environment.
+#if defined(LLVM_ON_WIN32)
+#define USE_WIN32
+#endif
+
+#ifdef USE_WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #define NOGDI
+ #define NOMINMAX
+ #include <windows.h>
+#endif
+
+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)
+ : ToolChain(D, Triple, Args) {
+}
+
+Tool *Windows::buildLinker() const {
+ return new tools::visualstudio::Link(*this);
+}
+
+Tool *Windows::buildAssembler() const {
+ if (getTriple().isOSBinFormatMachO())
+ return new tools::darwin::Assemble(*this);
+ getDriver().Diag(clang::diag::err_no_external_assembler);
+ return nullptr;
+}
+
+bool Windows::IsIntegratedAssemblerDefault() const {
+ return true;
+}
+
+bool Windows::IsUnwindTablesDefault() const {
+ // FIXME: LLVM's lowering of Win64 data is broken right now. MSVC's linker
+ // says that our object files provide invalid .pdata contributions. Until
+ // that is fixed, don't ask for unwind tables.
+ return false;
+ //return getArch() == llvm::Triple::x86_64;
+}
+
+bool Windows::isPICDefault() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+bool Windows::isPIEDefault() const {
+ return false;
+}
+
+bool Windows::isPICDefaultForced() const {
+ return getArch() == llvm::Triple::x86_64;
+}
+
+/// \brief Read registry string.
+/// This also supports a means to look for high-versioned keys by use
+/// of a $VERSION placeholder in the key path.
+/// $VERSION in the key path is a placeholder for the version number,
+/// causing the highest value path to be searched for and used.
+/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
+/// There can be additional characters in the component. Only the numberic
+/// characters are compared.
+static bool getSystemRegistryString(const char *keyPath, const char *valueName,
+ char *value, size_t maxLength) {
+#ifndef USE_WIN32
+ return false;
+#else
+ HKEY hRootKey = NULL;
+ HKEY hKey = NULL;
+ const char* subKey = NULL;
+ DWORD valueType;
+ DWORD valueSize = maxLength - 1;
+ long lResult;
+ bool returnValue = false;
+
+ if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
+ hRootKey = HKEY_CLASSES_ROOT;
+ subKey = keyPath + 18;
+ } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
+ hRootKey = HKEY_USERS;
+ subKey = keyPath + 11;
+ } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
+ hRootKey = HKEY_LOCAL_MACHINE;
+ subKey = keyPath + 19;
+ } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
+ hRootKey = HKEY_CURRENT_USER;
+ subKey = keyPath + 18;
+ } else {
+ return false;
+ }
+
+ const char *placeHolder = strstr(subKey, "$VERSION");
+ char bestName[256];
+ bestName[0] = '\0';
+ // If we have a $VERSION placeholder, do the highest-version search.
+ if (placeHolder) {
+ const char *keyEnd = placeHolder - 1;
+ const char *nextKey = placeHolder;
+ // Find end of previous key.
+ while ((keyEnd > subKey) && (*keyEnd != '\\'))
+ keyEnd--;
+ // Find end of key containing $VERSION.
+ while (*nextKey && (*nextKey != '\\'))
+ nextKey++;
+ size_t partialKeyLength = keyEnd - subKey;
+ char partialKey[256];
+ if (partialKeyLength > sizeof(partialKey))
+ partialKeyLength = sizeof(partialKey);
+ strncpy(partialKey, subKey, partialKeyLength);
+ partialKey[partialKeyLength] = '\0';
+ HKEY hTopKey = NULL;
+ lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
+ &hTopKey);
+ if (lResult == ERROR_SUCCESS) {
+ char keyName[256];
+ int bestIndex = -1;
+ double bestValue = 0.0;
+ DWORD index, size = sizeof(keyName) - 1;
+ for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
+ NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
+ const char *sp = keyName;
+ while (*sp && !isDigit(*sp))
+ sp++;
+ if (!*sp)
+ continue;
+ const char *ep = sp + 1;
+ while (*ep && (isDigit(*ep) || (*ep == '.')))
+ ep++;
+ char numBuf[32];
+ strncpy(numBuf, sp, sizeof(numBuf) - 1);
+ numBuf[sizeof(numBuf) - 1] = '\0';
+ 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;
+ }
+ RegCloseKey(hTopKey);
+ }
+ } else {
+ lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY,
+ &hKey);
+ if (lResult == ERROR_SUCCESS) {
+ lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
+ (LPBYTE)value, &valueSize);
+ if (lResult == ERROR_SUCCESS)
+ returnValue = true;
+ RegCloseKey(hKey);
+ }
+ }
+ return returnValue;
+#endif // USE_WIN32
+}
+
+/// \brief Get Windows SDK installation directory.
+static bool getWindowsSDKDir(std::string &path) {
+ char windowsSDKInstallDir[256];
+ // Try the Windows registry.
+ bool hasSDKDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
+ "InstallationFolder",
+ windowsSDKInstallDir,
+ sizeof(windowsSDKInstallDir) - 1);
+ // If we have both vc80 and vc90, pick version we were compiled with.
+ if (hasSDKDir && windowsSDKInstallDir[0]) {
+ path = windowsSDKInstallDir;
+ return true;
+ }
+ return false;
+}
+
+// Get Visual Studio installation directory.
+static bool getVisualStudioDir(std::string &path) {
+ // First check the environment variables that vsvars32.bat sets.
+ const char* vcinstalldir = getenv("VCINSTALLDIR");
+ if (vcinstalldir) {
+ char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
+ if (p)
+ *p = '\0';
+ path = vcinstalldir;
+ return true;
+ }
+
+ char vsIDEInstallDir[256];
+ char vsExpressIDEInstallDir[256];
+ // Then try the windows registry.
+ bool hasVCDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
+ "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
+ bool hasVCExpressDir = getSystemRegistryString(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
+ "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
+ // If we have both vc80 and vc90, pick version we were compiled with.
+ if (hasVCDir && vsIDEInstallDir[0]) {
+ char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
+ if (p)
+ *p = '\0';
+ path = vsIDEInstallDir;
+ return true;
+ }
+
+ if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
+ char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
+ if (p)
+ *p = '\0';
+ path = vsExpressIDEInstallDir;
+ return true;
+ }
+
+ // Try the environment.
+ const char *vs100comntools = getenv("VS100COMNTOOLS");
+ const char *vs90comntools = getenv("VS90COMNTOOLS");
+ const char *vs80comntools = getenv("VS80COMNTOOLS");
+
+ const char *vscomntools = nullptr;
+
+ // Find any version we can
+ if (vs100comntools)
+ vscomntools = vs100comntools;
+ else if (vs90comntools)
+ vscomntools = vs90comntools;
+ else if (vs80comntools)
+ vscomntools = vs80comntools;
+
+ if (vscomntools && *vscomntools) {
+ const char *p = strstr(vscomntools, "\\Common7\\Tools");
+ path = p ? std::string(vscomntools, p) : vscomntools;
+ return true;
+ }
+ return false;
+}
+
+void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
+ if (const char *cl_include_dir = getenv("INCLUDE")) {
+ SmallVector<StringRef, 8> Dirs;
+ StringRef(cl_include_dir)
+ .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ for (StringRef Dir : Dirs)
+ addSystemInclude(DriverArgs, CC1Args, Dir);
+ if (!Dirs.empty())
+ return;
+ }
+
+ std::string VSDir;
+ std::string WindowsSDKDir;
+
+ // When built with access to the proper Windows APIs, try to actually find
+ // the correct include paths first.
+ if (getVisualStudioDir(VSDir)) {
+ SmallString<128> P;
+ P = VSDir;
+ llvm::sys::path::append(P, "VC\\include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ if (getWindowsSDKDir(WindowsSDKDir)) {
+ P = WindowsSDKDir;
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ } else {
+ P = VSDir;
+ llvm::sys::path::append(P, "VC\\PlatformSDK\\Include");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+ return;
+ }
+
+ // As a fallback, select default install paths.
+ // FIXME: Don't guess drives and paths like this on Windows.
+ const StringRef Paths[] = {
+ "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
+ "C:/Program Files/Microsoft Visual Studio 8/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
+ };
+ addSystemIncludes(DriverArgs, CC1Args, Paths);
+}
+
+void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // FIXME: There should probably be logic here to find libc++ on Windows.
+}
OpenPOWER on IntegriCloud