diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Action.cpp | 30 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp | 44 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Compilation.cpp | 21 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 324 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Job.cpp | 16 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Multilib.cpp | 334 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp | 127 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp | 200 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 1541 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.h | 612 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 2848 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.h | 524 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Types.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp | 91 |
14 files changed, 4275 insertions, 2439 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp index ddd2d59..86a48fd 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp @@ -33,7 +33,8 @@ const char *Action::getClassName(ActionClass AC) { case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; - case VerifyJobClass: return "verify"; + case VerifyDebugInfoJobClass: return "verify-debug-info"; + case VerifyPCHJobClass: return "verify-pch"; } llvm_unreachable("invalid class"); @@ -117,6 +118,29 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) void VerifyJobAction::anchor() {} -VerifyJobAction::VerifyJobAction(ActionList &Inputs, types::ID Type) - : JobAction(VerifyJobClass, Inputs, Type) { +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/CC1AsOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp deleted file mode 100644 index 22180c9..0000000 --- a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//===--- CC1AsOptions.cpp - Clang Assembler 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/CC1AsOptions.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Option/OptTable.h" -#include "llvm/Option/Option.h" -using namespace clang; -using namespace clang::driver; -using namespace llvm::opt; -using namespace clang::driver::cc1asoptions; - -#define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; -#include "clang/Driver/CC1AsOptions.inc" -#undef PREFIX - -static const OptTable::Info CC1AsInfoTable[] = { -#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/CC1AsOptions.inc" -#undef OPTION -}; - -namespace { - -class CC1AsOptTable : public OptTable { -public: - CC1AsOptTable() - : OptTable(CC1AsInfoTable, llvm::array_lengthof(CC1AsInfoTable)) {} -}; - -} - -OptTable *clang::driver::createCC1AsOptTable() { - return new CC1AsOptTable(); -} diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index f077fd6..49b7edd 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -17,8 +17,6 @@ #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" -#include <errno.h> -#include <sys/stat.h> using namespace clang::driver; using namespace clang; @@ -26,9 +24,9 @@ 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(0) { -} + : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args), + TranslatedArgs(_TranslatedArgs), Redirects(nullptr), + ForDiagnostics(false) {} Compilation::~Compilation() { delete TranslatedArgs; @@ -70,8 +68,6 @@ const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC, } bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { - std::string P(File); - // 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 @@ -88,7 +84,7 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File)) return true; - if (llvm::error_code EC = llvm::sys::fs::remove(File)) { + 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. @@ -137,7 +133,8 @@ int Compilation::ExecuteCommand(const Command &C, 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_Append | + llvm::sys::fs::F_Text); if (!Error.empty()) { getDriver().Diag(clang::diag::err_drv_cc_print_options_failure) << Error; @@ -200,7 +197,7 @@ void Compilation::ExecuteJob(const Job &J, if (const Command *C = dyn_cast<Command>(&J)) { if (!InputsOk(*C, FailingCommands)) return; - const Command *FailingCommand = 0; + const Command *FailingCommand = nullptr; if (int Res = ExecuteCommand(*C, FailingCommand)) FailingCommands.push_back(std::make_pair(Res, FailingCommand)); } else { @@ -212,6 +209,8 @@ void Compilation::ExecuteJob(const Job &J, } void Compilation::initCompilationForDiagnostics() { + ForDiagnostics = true; + // Free actions and jobs. DeleteContainerPointers(Actions); Jobs.clear(); @@ -233,7 +232,7 @@ void Compilation::initCompilationForDiagnostics() { // Redirect stdout/stderr to /dev/null. Redirects = new const StringRef*[3](); - Redirects[0] = 0; + Redirects[0] = nullptr; Redirects[1] = new const StringRef(); Redirects[2] = new const StringRef(); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 1c76509..ef26bfa 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -11,6 +11,7 @@ #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" @@ -19,27 +20,25 @@ #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/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/Option/OptSpecifier.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> - -// FIXME: It would prevent us from including llvm-config.h -// if config.h were included before system_error.h. -#include "clang/Config/config.h" +#include <memory> using namespace clang::driver; using namespace clang; @@ -47,15 +46,14 @@ using namespace llvm::opt; Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, - StringRef DefaultImageName, DiagnosticsEngine &Diags) : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), - DefaultImageName(DefaultImageName), + DefaultImageName("a.out"), DriverTitle("clang LLVM compiler"), - CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), - CCLogDiagnosticsFilename(0), + CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), + CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), @@ -77,10 +75,7 @@ Driver::Driver(StringRef ClangExecutable, Driver::~Driver() { delete Opts; - for (llvm::StringMap<ToolChain *>::iterator I = ToolChains.begin(), - E = ToolChains.end(); - I != E; ++I) - delete I->second; + llvm::DeleteContainerSeconds(ToolChains); } void Driver::ParseDriverMode(ArrayRef<const char *> Args) { @@ -112,7 +107,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { unsigned IncludedFlagsBitmask; unsigned ExcludedFlagsBitmask; - llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = + std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = getIncludeExcludeOptionFlagMasks(); unsigned MissingArgIndex, MissingArgCount; @@ -156,18 +151,21 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { // option we used to determine the final phase. phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg) const { - Arg *PhaseArg = 0; + Arg *PhaseArg = nullptr; phases::ID FinalPhase; - // -{E,M,MM} only run the preprocessor. + // -{E,EP,P,M,MM} only run the preprocessor. if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || - (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) { + (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)) || @@ -191,10 +189,11 @@ const { return FinalPhase; } -static Arg* MakeInputArg(const DerivedArgList &Args, OptTable *Opts, +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; } @@ -336,9 +335,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld // and getToolChain is const. if (IsCLMode()) { - // clang-cl targets Win32. + // clang-cl targets MSVC-style Win32. llvm::Triple T(DefaultTargetTriple); - T.setOSName(llvm::Triple::getOSTypeName(llvm::Triple::Win32)); + T.setOS(llvm::Triple::Win32); + T.setEnvironment(llvm::Triple::MSVC); DefaultTargetTriple = T.str(); } if (const Arg *A = Args->getLastArg(options::OPT_target)) @@ -378,8 +378,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); // Construct the list of abstract actions to perform for this compilation. On - // Darwin target OSes this uses the driver-driver and universal actions. - if (TC.getTriple().isOSDarwin()) + // MachO targets this uses the driver-driver and universal actions. + if (TC.getTriple().isOSBinFormatMachO()) BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(), Inputs, C->getActions()); else @@ -419,7 +419,6 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // Suppress driver output and emit preprocessor output to temp file. Mode = CPPMode; CCGenDiagnostics = true; - C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes)); // Save the original job command(s). std::string Cmd; @@ -447,13 +446,14 @@ void Driver::generateCompilationDiagnostics(Compilation &C, bool IgnoreInput = false; // Ignore input from stdin or any inputs that cannot be preprocessed. - if (!strcmp(it->second->getValue(), "-")) { + // 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; - } else if (types::getPreprocessedType(it->first) == types::TY_INVALID) { - IgnoreInput = true; } if (IgnoreInput) { @@ -491,7 +491,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // 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().isOSDarwin()) + if (TC.getTriple().isOSBinFormatMachO()) BuildUniversalActions(TC, C.getArgs(), Inputs, C.getActions()); else BuildActions(TC, C.getArgs(), Inputs, C.getActions()); @@ -519,17 +519,25 @@ void Driver::generateCompilationDiagnostics(Compilation &C, 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; - std::string Script = StringRef(*it).rsplit('.').first; Script += ".sh"; - llvm::raw_fd_ostream ScriptOS( - Script.c_str(), Err, llvm::sys::fs::F_Excl | llvm::sys::fs::F_Binary); + 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 { - // Append the new filename with correct preprocessed suffix. + // 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"); @@ -542,6 +550,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C, 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; } @@ -599,7 +612,7 @@ int Driver::ExecuteCompilation(const Compilation &C, // 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 + // 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. @@ -621,7 +634,7 @@ int Driver::ExecuteCompilation(const Compilation &C, void Driver::PrintHelp(bool ShowHidden) const { unsigned IncludedFlagsBitmask; unsigned ExcludedFlagsBitmask; - llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = + std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = getIncludeExcludeOptionFlagMasks(); ExcludedFlagsBitmask |= options::NoDriverOption; @@ -746,54 +759,37 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { } if (C.getArgs().hasArg(options::OPT_print_multi_lib)) { - // FIXME: We need tool chain support for this. - llvm::outs() << ".;\n"; - - switch (C.getDefaultToolChain().getTriple().getArch()) { - default: - break; - - case llvm::Triple::x86_64: - llvm::outs() << "x86_64;@m64" << "\n"; - break; + const MultilibSet &Multilibs = TC.getMultilibs(); - case llvm::Triple::ppc64: - llvm::outs() << "ppc64;@m64" << "\n"; - break; - - case llvm::Triple::ppc64le: - llvm::outs() << "ppc64le;@m64" << "\n"; - break; + for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end(); + I != E; ++I) { + llvm::outs() << *I << "\n"; } return false; } - // FIXME: What is the difference between print-multi-directory and - // print-multi-os-directory? - if (C.getArgs().hasArg(options::OPT_print_multi_directory) || - C.getArgs().hasArg(options::OPT_print_multi_os_directory)) { - switch (C.getDefaultToolChain().getTriple().getArch()) { - default: - case llvm::Triple::x86: - case llvm::Triple::ppc: - llvm::outs() << "." << "\n"; - break; - - case llvm::Triple::x86_64: - llvm::outs() << "." << "\n"; - break; - - case llvm::Triple::ppc64: - llvm::outs() << "ppc64" << "\n"; - break; - - case llvm::Triple::ppc64le: - llvm::outs() << "ppc64le" << "\n"; - break; + 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; } @@ -867,7 +863,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, // 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::getArchTypeForDarwinArchName(A->getValue()); + tools::darwin::getArchTypeForMachOArchName(A->getValue()); if (Arch == llvm::Triple::UnknownArch) { Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); @@ -934,13 +930,12 @@ void Driver::BuildUniversalActions(const ToolChain &TC, Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); } - // Verify the output (debug information only) if we passed '-verify'. - if (Args.hasArg(options::OPT_verify)) { - ActionList VerifyInputs; - VerifyInputs.push_back(Actions.back()); + // Verify the debug info output. + if (Args.hasArg(options::OPT_verify_debug_info)) { + Action *VerifyInput = Actions.back(); Actions.pop_back(); - Actions.push_back(new VerifyJobAction(VerifyInputs, - types::TY_Nothing)); + Actions.push_back(new VerifyDebugInfoJobAction(VerifyInput, + types::TY_Nothing)); } } } @@ -948,7 +943,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, /// \brief Check that the file referenced by Value exists. If it doesn't, /// issue a diagnostic and return false. -static bool DiagnoseInputExistance(const Driver &D, const DerivedArgList &Args, +static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, StringRef Value) { if (!D.getCheckInputsExist()) return true; @@ -969,18 +964,21 @@ static bool DiagnoseInputExistance(const Driver &D, const DerivedArgList &Args, 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, const DerivedArgList &Args, +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 = 0; + 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, @@ -1029,7 +1027,8 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, // Otherwise emit an error but still use a valid type to avoid // spurious errors (e.g., no inputs). if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP()) - Diag(clang::diag::err_drv_unknown_stdin_type); + 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. @@ -1075,19 +1074,19 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, Ty = InputType; } - if (DiagnoseInputExistance(*this, Args, Value)) + 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 (DiagnoseInputExistance(*this, Args, Value)) { + 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 (DiagnoseInputExistance(*this, Args, Value)) { + if (DiagnoseInputExistence(*this, Args, Value)) { Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_CXX, InputArg)); } @@ -1177,7 +1176,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, // Construct the actions to perform. ActionList LinkerInputs; - ActionList SplitInputs; + llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL; for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { types::ID InputType = Inputs[i].first; @@ -1211,18 +1210,18 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, Diag(clang::diag::warn_drv_preprocessed_input_file_unused) << InputArg->getAsString(Args) << !!FinalPhaseArg - << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""; + << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""); else Diag(clang::diag::warn_drv_input_file_unused) << InputArg->getAsString(Args) << getPhaseName(InitialPhase) << !!FinalPhaseArg - << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""; + << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : ""); continue; } // Build the pipeline for this file. - OwningPtr<Action> Current(new InputAction(*InputArg, InputType)); + 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; @@ -1234,7 +1233,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, // Queue linker inputs. if (Phase == phases::Link) { assert((i + 1) == e && "linking must be final compilation step."); - LinkerInputs.push_back(Current.take()); + LinkerInputs.push_back(Current.release()); break; } @@ -1245,14 +1244,14 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, continue; // Otherwise construct the appropriate action. - Current.reset(ConstructPhaseAction(Args, Phase, Current.take())); + 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.take()); + Actions.push_back(Current.release()); } // Add a link action if necessary. @@ -1284,7 +1283,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, } else { OutputTy = Input->getType(); if (!Args.hasFlag(options::OPT_frewrite_includes, - options::OPT_fno_rewrite_includes, false)) + options::OPT_fno_rewrite_includes, false) && + !CCGenDiagnostics) OutputTy = types::getPreprocessedType(OutputTy); assert(OutputTy != types::TY_INVALID && "Cannot preprocess this input type!"); @@ -1314,6 +1314,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, 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; @@ -1356,13 +1358,13 @@ void Driver::BuildJobs(Compilation &C) const { if (NumOutputs > 1) { Diag(clang::diag::err_drv_output_argument_with_multiple_files); - FinalOutput = 0; + FinalOutput = nullptr; } } // Collect the list of architectures. llvm::StringSet<> ArchNames; - if (C.getDefaultToolChain().getTriple().isOSDarwin()) { + if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) { for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { Arg *A = *it; @@ -1381,7 +1383,7 @@ void Driver::BuildJobs(Compilation &C) const { // // FIXME: This is a hack; find a cleaner way to integrate this into the // process. - const char *LinkingOutput = 0; + const char *LinkingOutput = nullptr; if (isa<LipoJobAction>(A)) { if (FinalOutput) LinkingOutput = FinalOutput->getValue(); @@ -1391,7 +1393,7 @@ void Driver::BuildJobs(Compilation &C) const { InputInfo II; BuildJobsForAction(C, A, &C.getDefaultToolChain(), - /*BoundArch*/0, + /*BoundArch*/nullptr, /*AtTopLevel*/ true, /*MultipleArchs*/ ArchNames.size() > 1, /*LinkingOutput*/ LinkingOutput, @@ -1448,7 +1450,7 @@ void Driver::BuildJobs(Compilation &C) const { static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, const JobAction *JA, const ActionList *&Inputs) { - const Tool *ToolForJob = 0; + 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 @@ -1456,6 +1458,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, 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) && @@ -1463,7 +1466,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, const Tool *Compiler = TC->SelectTool(cast<JobAction>(**Inputs->begin())); if (!Compiler) - return NULL; + return nullptr; if (Compiler->hasIntegratedAssembler()) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = Compiler; @@ -1587,7 +1590,7 @@ void Driver::BuildJobsForAction(Compilation &C, 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; @@ -1626,6 +1629,17 @@ const char *Driver::GetNamedOutputPath(Compilation &C, 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)) @@ -1831,8 +1845,7 @@ std::string Driver::GetProgramPath(const char *Name, std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) const { SmallString<128> Path; - llvm::error_code EC = - llvm::sys::fs::createTemporaryFile(Prefix, Suffix, 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 ""; @@ -1854,36 +1867,43 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); - // Handle Darwin-specific options available here. - if (Target.isOSDarwin()) { + // Handle Apple-specific options available here. + if (Target.isOSBinFormatMachO()) { // If an explict Darwin arch name is given, that trumps all. if (!DarwinArchName.empty()) { - Target.setArch( - tools::darwin::getArchTypeForDarwinArchName(DarwinArchName)); + tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName); return Target; } // Handle the Darwin '-arch' flag. if (Arg *A = Args.getLastArg(options::OPT_arch)) { - llvm::Triple::ArchType DarwinArch - = tools::darwin::getArchTypeForDarwinArchName(A->getValue()); - if (DarwinArch != llvm::Triple::UnknownArch) - Target.setArch(DarwinArch); + StringRef ArchName = A->getValue(); + tools::darwin::setTripleTypeForMachOArchName(Target, ArchName); } } - // Handle pseudo-target flags '-EL' and '-EB'. - if (Arg *A = Args.getLastArg(options::OPT_EL, options::OPT_EB)) { - if (A->getOption().matches(options::OPT_EL)) { + // 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); } } @@ -1893,20 +1913,27 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, Target.getOS() == llvm::Triple::Minix) return Target; - // Handle pseudo-target flags '-m32' and '-m64'. - // FIXME: Should this information be in llvm::Triple? - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (A->getOption().matches(options::OPT_m32)) { - if (Target.getArch() == llvm::Triple::x86_64) - Target.setArch(llvm::Triple::x86); - if (Target.getArch() == llvm::Triple::ppc64) - Target.setArch(llvm::Triple::ppc); - } else { - if (Target.getArch() == llvm::Triple::x86) - Target.setArch(llvm::Triple::x86_64); - if (Target.getArch() == llvm::Triple::ppc) - Target.setArch(llvm::Triple::ppc64); + // 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; @@ -1926,13 +1953,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: - if (Target.getArch() == llvm::Triple::x86 || - Target.getArch() == llvm::Triple::x86_64 || - Target.getArch() == llvm::Triple::arm || - Target.getArch() == llvm::Triple::thumb) - TC = new toolchains::DarwinClang(*this, Target, Args); - else - TC = new toolchains::Darwin_Generic_GCC(*this, Target, Args); + TC = new toolchains::DarwinClang(*this, Target, Args); break; case llvm::Triple::DragonFly: TC = new toolchains::DragonFly(*this, Target, Args); @@ -1962,10 +1983,29 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = new toolchains::Solaris(*this, Target, Args); break; case llvm::Triple::Win32: - TC = new toolchains::Windows(*this, Target, Args); + 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; - case llvm::Triple::MinGW32: - // FIXME: We need a MinGW toolchain. Fallthrough for now. default: // TCE is an OSless target if (Target.getArchName() == "tce") { @@ -1981,6 +2021,14 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, 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; } diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp index ee68e6f..42cc1bc 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp @@ -7,7 +7,11 @@ // //===----------------------------------------------------------------------===// +#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" @@ -37,7 +41,7 @@ static int skipArgs(const char *Flag) { .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true) .Cases("-iwithprefixbefore", "-isysroot", "-isystem", "-iquote", true) .Cases("-resource-dir", "-serialize-diagnostic-file", true) - .Case("-dwarf-debug-flags", true) + .Cases("-dwarf-debug-flags", "-ivfsoverlay", true) .Default(false); // Match found. @@ -58,7 +62,8 @@ static int skipArgs(const char *Flag) { // These flags are treated as a single argument (e.g., -F<Dir>). StringRef FlagRef(Flag); - if (FlagRef.startswith("-F") || FlagRef.startswith("-I")) + if (FlagRef.startswith("-F") || FlagRef.startswith("-I") || + FlagRef.startswith("-fmodules-cache-path=")) return 1; return 0; @@ -119,9 +124,9 @@ int Command::Execute(const StringRef **Redirects, std::string *ErrMsg, Argv.push_back(Executable); for (size_t i = 0, e = Arguments.size(); i != e; ++i) Argv.push_back(Arguments[i]); - Argv.push_back(0); + Argv.push_back(nullptr); - return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ 0, + return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } @@ -159,6 +164,9 @@ int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg, 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; } 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/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp index 43209f0..b64f027 100644 --- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// #include "clang/Driver/SanitizerArgs.h" - #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "llvm/Transforms/Utils/SpecialCaseList.h" +#include "llvm/Support/SpecialCaseList.h" +#include <memory> using namespace clang::driver; using namespace llvm::opt; @@ -24,9 +24,10 @@ using namespace llvm::opt; void SanitizerArgs::clear() { Kind = 0; BlacklistFile = ""; - MsanTrackOrigins = false; + MsanTrackOrigins = 0; AsanZeroBaseShadow = false; UbsanTrapOnError = false; + AsanSharedRuntime = false; } SanitizerArgs::SanitizerArgs() { @@ -72,30 +73,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, } UbsanTrapOnError = - Args.hasArg(options::OPT_fcatch_undefined_behavior) || Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, options::OPT_fno_sanitize_undefined_trap_on_error, false); - if (Args.hasArg(options::OPT_fcatch_undefined_behavior) && - !Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, - options::OPT_fno_sanitize_undefined_trap_on_error, true)) { - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fcatch-undefined-behavior" - << "-fno-sanitize-undefined-trap-on-error"; - } - // Warn about undefined sanitizer options that require runtime support. if (UbsanTrapOnError && notAllowedWithTrap()) { - if (Args.hasArg(options::OPT_fcatch_undefined_behavior)) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NotAllowedWithTrap) - << "-fcatch-undefined-behavior"; - else if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, - options::OPT_fno_sanitize_undefined_trap_on_error, - false)) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NotAllowedWithTrap) - << "-fsanitize-undefined-trap-on-error"; + 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. @@ -123,19 +108,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, D.Diag(diag::err_drv_argument_not_allowed_with) << lastArgumentForKind(D, Args, NeedsLeakDetection) << lastArgumentForKind(D, Args, NeedsMsanRt); - // FIXME: Currenly -fsanitize=leak is silently ignored in the presence of + // 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? - // If -fsanitize contains extra features of ASan, it should also - // explicitly contain -fsanitize=address (probably, turned off later in the - // command line). - if ((Kind & AddressFull) != 0 && (AllAdd & Address) == 0) - D.Diag(diag::warn_drv_unused_sanitizer) - << lastArgumentForKind(D, Args, AddressFull) - << "-fsanitize=address"; - // Parse -f(no-)sanitize-blacklist options. if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist, options::OPT_fno_sanitize_blacklist)) { @@ -144,7 +121,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, if (llvm::sys::fs::exists(BLPath)) { // Validate the blacklist format. std::string BLError; - llvm::OwningPtr<llvm::SpecialCaseList> SCL( + std::unique_ptr<llvm::SpecialCaseList> SCL( llvm::SpecialCaseList::create(BLPath, BLError)); if (!SCL.get()) D.Diag(diag::err_drv_malformed_sanitizer_blacklist) << BLError; @@ -163,27 +140,33 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, BlacklistFile = BLPath; } - // Parse -f(no-)sanitize-memory-track-origins options. - if (NeedsMsan) - MsanTrackOrigins = - Args.hasFlag(options::OPT_fsanitize_memory_track_origins, - options::OPT_fno_sanitize_memory_track_origins, - /* Default */false); + // Parse -f[no-]sanitize-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; + } + } + } + } - // Parse -f(no-)sanitize-address-zero-base-shadow options. if (NeedsAsan) { - bool IsAndroid = (TC.getTriple().getEnvironment() == llvm::Triple::Android); - bool ZeroBaseShadowDefault = IsAndroid; + AsanSharedRuntime = + Args.hasArg(options::OPT_shared_libasan) || + (TC.getTriple().getEnvironment() == llvm::Triple::Android); AsanZeroBaseShadow = - Args.hasFlag(options::OPT_fsanitize_address_zero_base_shadow, - options::OPT_fno_sanitize_address_zero_base_shadow, - ZeroBaseShadowDefault); - // Zero-base shadow is a requirement on Android. - if (IsAndroid && !AsanZeroBaseShadow) { - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fno-sanitize-address-zero-base-shadow" - << lastArgumentForKind(D, Args, Address); - } + (TC.getTriple().getEnvironment() == llvm::Triple::Android); } } @@ -205,11 +188,8 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, } if (MsanTrackOrigins) - CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins")); - - if (AsanZeroBaseShadow) - CmdArgs.push_back( - Args.MakeArgString("-fsanitize-address-zero-base-shadow")); + CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + + llvm::utostr(MsanTrackOrigins))); // Workaround for PR16386. if (needsMsanRt()) @@ -222,11 +202,6 @@ unsigned SanitizerArgs::parse(const char *Value) { #define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group) #include "clang/Basic/Sanitizers.def" .Default(SanitizeKind()); - // Assume -fsanitize=address implies -fsanitize=init-order,use-after-return. - // FIXME: This should be either specified in Sanitizers.def, or go away when - // we get rid of "-fsanitize=init-order,use-after-return" flags at all. - if (ParsedKind & Address) - ParsedKind |= InitOrder | UseAfterReturn; return ParsedKind; } @@ -296,28 +271,7 @@ bool SanitizerArgs::parse(const Driver &D, const llvm::opt::ArgList &Args, unsigned &Remove, bool DiagnoseErrors) { Add = 0; Remove = 0; - const char *DeprecatedReplacement = 0; - if (A->getOption().matches(options::OPT_faddress_sanitizer)) { - Add = Address; - DeprecatedReplacement = "-fsanitize=address"; - } else if (A->getOption().matches(options::OPT_fno_address_sanitizer)) { - Remove = Address; - DeprecatedReplacement = "-fno-sanitize=address"; - } else if (A->getOption().matches(options::OPT_fthread_sanitizer)) { - Add = Thread; - DeprecatedReplacement = "-fsanitize=thread"; - } else if (A->getOption().matches(options::OPT_fno_thread_sanitizer)) { - Remove = Thread; - DeprecatedReplacement = "-fno-sanitize=thread"; - } else if (A->getOption().matches(options::OPT_fcatch_undefined_behavior)) { - Add = UndefinedTrap; - DeprecatedReplacement = - "-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error"; - } else if (A->getOption().matches(options::OPT_fbounds_checking) || - A->getOption().matches(options::OPT_fbounds_checking_EQ)) { - Add = LocalBounds; - DeprecatedReplacement = "-fsanitize=local-bounds"; - } else if (A->getOption().matches(options::OPT_fsanitize_EQ)) { + 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); @@ -325,11 +279,6 @@ bool SanitizerArgs::parse(const Driver &D, const llvm::opt::ArgList &Args, // Flag is not relevant to sanitizers. return false; } - // If this is a deprecated synonym, produce a warning directing users - // towards the new spelling. - if (DeprecatedReplacement && DiagnoseErrors) - D.Diag(diag::warn_drv_deprecated_arg) - << A->getAsString(Args) << DeprecatedReplacement; return true; } @@ -369,7 +318,7 @@ std::string SanitizerArgs::describeSanitizeArg(const llvm::opt::ArgList &Args, bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind, std::string &BLPath) { - const char *BlacklistFile = 0; + const char *BlacklistFile = nullptr; if (Kind & NeedsAsanRt) BlacklistFile = "asan_blacklist.txt"; else if (Kind & NeedsMsanRt) diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 69b642e..4f90d08 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -15,6 +15,7 @@ #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" @@ -38,8 +39,8 @@ const Driver &ToolChain::getDriver() const { } bool ToolChain::useIntegratedAs() const { - return Args.hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, + return Args.hasFlag(options::OPT_fintegrated_as, + options::OPT_fno_integrated_as, IsIntegratedAssemblerDefault()); } @@ -114,7 +115,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::BindArchClass: case Action::LipoJobClass: case Action::DsymutilJobClass: - case Action::VerifyJobClass: + case Action::VerifyDebugInfoJobClass: llvm_unreachable("Invalid tool kind."); case Action::CompileJobClass: @@ -122,6 +123,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::PreprocessJobClass: case Action::AnalyzeJobClass: case Action::MigrateJobClass: + case Action::VerifyPCHJobClass: return getClang(); } @@ -146,6 +148,30 @@ 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); } @@ -154,110 +180,27 @@ 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()); } -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. -// -// FIXME: tblgen this. -static const char *getARMTargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { - // For Darwin targets, the -arch option (which is translated to a - // corresponding -march option) should determine the architecture - // (and the Mach-O slice) regardless of any -mcpu options. - if (!Triple.isOSDarwin()) { - // FIXME: Warn on inconsistent use of -mcpu and -march. - // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - return A->getValue(); - } - - 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(); - } - - if (Triple.getOS() == llvm::Triple::NetBSD || - Triple.getOS() == llvm::Triple::FreeBSD) { - if (MArch == "armv6") - return "arm1176jzf-s"; - } - - const char *result = llvm::StringSwitch<const char *>(MArch) - .Cases("armv2", "armv2a","arm2") - .Case("armv3", "arm6") - .Case("armv3m", "arm7m") - .Case("armv4", "strongarm") - .Case("armv4t", "arm7tdmi") - .Cases("armv5", "armv5t", "arm10tdmi") - .Cases("armv5e", "armv5te", "arm1026ejs") - .Case("armv5tej", "arm926ej-s") - .Cases("armv6", "armv6k", "arm1136jf-s") - .Case("armv6j", "arm1136j-s") - .Cases("armv6z", "armv6zk", "arm1176jzf-s") - .Case("armv6t2", "arm1156t2-s") - .Cases("armv6m", "armv6-m", "cortex-m0") - .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") - .Cases("armv7l", "armv7-l", "cortex-a8") - .Cases("armv7f", "armv7-f", "cortex-a9-mp") - .Cases("armv7s", "armv7-s", "swift") - .Cases("armv7r", "armv7-r", "cortex-r4") - .Cases("armv7m", "armv7-m", "cortex-m3") - .Cases("armv7em", "armv7e-m", "cortex-m4") - .Cases("armv8", "armv8a", "armv8-a", "cortex-a53") - .Case("ep9312", "ep9312") - .Case("iwmmxt", "iwmmxt") - .Case("xscale", "xscale") - // If all else failed, return the most base CPU with thumb interworking - // supported by LLVM. - .Default(0); - - if (result) - return result; - - return - Triple.getEnvironment() == llvm::Triple::GNUEABIHF - ? "arm1176jzf-s" - : "arm7tdmi"; -} - -/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular -/// CPU. -// -// FIXME: This is redundant with -mcpu, why does LLVM use this. -// FIXME: tblgen this, or kill it! -static const char *getLLVMArchSuffixForARM(StringRef CPU) { - return llvm::StringSwitch<const char *>(CPU) - .Case("strongarm", "v4") - .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") - .Cases("arm720t", "arm9", "arm9tdmi", "v4t") - .Cases("arm920", "arm920t", "arm922t", "v4t") - .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", "v7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7") - .Cases("cortex-r4", "cortex-r5", "v7r") - .Case("cortex-m0", "v6m") - .Case("cortex-m3", "v7m") - .Case("cortex-m4", "v7em") - .Case("cortex-a9-mp", "v7f") - .Case("swift", "v7s") - .Cases("cortex-a53", "cortex-a57", "v8") - .Default(""); -} - std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, types::ID InputType) const { switch (getTriple().getArch()) { @@ -266,7 +209,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, case llvm::Triple::x86_64: { llvm::Triple Triple = getTriple(); - if (!Triple.isOSDarwin()) + if (!Triple.isOSBinFormatMachO()) return getTripleString(); if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { @@ -279,23 +222,51 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, return Triple.getTriple(); } case llvm::Triple::arm: - case llvm::Triple::thumb: { + 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 = - getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); - bool ThumbDefault = Suffix.startswith("v6m") || - (Suffix.startswith("v7") && getTriple().isOSDarwin()); - std::string ArchName = "arm"; + 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)) - ArchName = "thumb"; + { + if (IsBigEndian) + ArchName = "thumbeb"; + else + ArchName = "thumb"; + } Triple.setArchName(ArchName + Suffix.str()); return Triple.getTriple(); @@ -305,13 +276,6 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { - // Diagnose use of Darwin OS deployment target arguments on non-Darwin. - if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ, - options::OPT_miphoneos_version_min_EQ, - options::OPT_mios_simulator_version_min_EQ)) - getDriver().Diag(diag::err_drv_clang_unsupported) - << A->getAsString(Args); - return ComputeLLVMTriple(Args, InputType); } @@ -324,6 +288,8 @@ void ToolChain::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args) const { } +void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} + ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index b568593..b46f69d 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -10,6 +10,7 @@ #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" @@ -27,26 +28,33 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include "llvm/Support/Program.h" - -// FIXME: This needs to be listed last until we fix the broken include guards -// in these files and the LLVM config.h files. -#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX - +#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; -/// Darwin - Darwin tool chain for i386 and x86_64. +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); -Darwin::Darwin(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), TargetInitialized(false) -{ + // 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)) @@ -67,7 +75,7 @@ Darwin::Darwin(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) << Major << '.' << Minor << '.' << Micro; } -types::ID Darwin::LookupTypeForExtension(const char *Ext) const { +types::ID MachO::LookupTypeForExtension(const char *Ext) const { types::ID Ty = types::lookupTypeForExtension(Ext); // Darwin always preprocesses assembly files (unless -x is used explicitly). @@ -77,13 +85,13 @@ types::ID Darwin::LookupTypeForExtension(const char *Ext) const { return Ty; } -bool Darwin::HasNativeLLVMSupport() const { +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 (isTargetIPhoneOS()) + if (isTargetIOSBased()) return ObjCRuntime(ObjCRuntime::iOS, TargetVersion); if (isNonFragile) return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion); @@ -92,10 +100,12 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. bool Darwin::hasBlocksRuntime() const { - if (isTargetIPhoneOS()) + if (isTargetIOSBased()) return !isIPhoneOSVersionLT(3, 2); - else + else { + assert(isTargetMacOS() && "unexpected darwin target"); return !isMacosxVersionLT(10, 6); + } } static const char *GetArmArchForMArch(StringRef Value) { @@ -109,11 +119,10 @@ static const char *GetArmArchForMArch(StringRef Value) { .Cases("armv7a", "armv7-a", "armv7") .Cases("armv7r", "armv7-r", "armv7") .Cases("armv7em", "armv7e-m", "armv7em") - .Cases("armv7f", "armv7-f", "armv7f") .Cases("armv7k", "armv7-k", "armv7k") .Cases("armv7m", "armv7-m", "armv7m") .Cases("armv7s", "armv7-s", "armv7s") - .Default(0); + .Default(nullptr); } static const char *GetArmArchForMCpu(StringRef Value) { @@ -124,17 +133,27 @@ static const char *GetArmArchForMCpu(StringRef Value) { .Case("xscale", "xscale") .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6") .Case("cortex-m0", "armv6m") - .Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "armv7") + .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-a9-mp", "armv7f") .Case("cortex-m3", "armv7m") .Case("cortex-m4", "armv7em") .Case("swift", "armv7s") - .Default(0); + .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 Darwin::getDarwinArchName(const ArgList &Args) const { +StringRef MachO::getMachOArchName(const ArgList &Args) const { switch (getTriple().getArch()) { default: return getArchName(); @@ -157,6 +176,17 @@ StringRef Darwin::getDarwinArchName(const ArgList &Args) const { 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)); @@ -166,25 +196,17 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, if (!isTargetInitialized()) return Triple.getTriple(); - if (Triple.getArchName() == "thumbv6m" || - Triple.getArchName() == "thumbv7m" || - Triple.getArchName() == "thumbv7em") { - // OS is ios or macosx unless it's the v6m or v7m. - Triple.setOS(llvm::Triple::Darwin); - Triple.setEnvironment(llvm::Triple::EABI); - } else { - SmallString<16> Str; - Str += isTargetIPhoneOS() ? "ios" : "macosx"; - Str += getTargetVersion().getAsString(); - Triple.setOSName(Str); - } + SmallString<16> Str; + Str += isTargetIOSBased() ? "ios" : "macosx"; + Str += getTargetVersion().getAsString(); + Triple.setOSName(Str); return Triple.getTriple(); } void Generic_ELF::anchor() {} -Tool *Darwin::getTool(Action::ActionClass AC) const { +Tool *MachO::getTool(Action::ActionClass AC) const { switch (AC) { case Action::LipoJobClass: if (!Lipo) @@ -194,7 +216,7 @@ Tool *Darwin::getTool(Action::ActionClass AC) const { if (!Dsymutil) Dsymutil.reset(new tools::darwin::Dsymutil(*this)); return Dsymutil.get(); - case Action::VerifyJobClass: + case Action::VerifyDebugInfoJobClass: if (!VerifyDebug) VerifyDebug.reset(new tools::darwin::VerifyDebug(*this)); return VerifyDebug.get(); @@ -203,30 +225,50 @@ Tool *Darwin::getTool(Action::ActionClass AC) const { } } -Tool *Darwin::buildLinker() const { +Tool *MachO::buildLinker() const { return new tools::darwin::Link(*this); } -Tool *Darwin::buildAssembler() const { +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) -{ - getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); + : Darwin(D, Triple, Args) { +} - // 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); +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); @@ -245,12 +287,12 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(P)); } -void DarwinClang::AddLinkRuntimeLib(const ArgList &Args, - ArgStringList &CmdArgs, - const char *DarwinStaticLib, - bool AlwaysLink) const { +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", "darwin", DarwinStaticLib); + 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 @@ -290,14 +332,14 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // 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 (isTargetIPhoneOS()) { + if (isTargetIOSBased()) AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a"); - } else { + else AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a"); - } } const SanitizerArgs &Sanitize = getSanitizerArgs(); @@ -305,10 +347,11 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // Add Ubsan runtime library, if required. if (Sanitize.needsUbsanRt()) { // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. - if (isTargetIPhoneOS()) { + 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++. @@ -320,7 +363,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // should not be linked with the runtime library. if (Sanitize.needsAsanRt()) { // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. - if (isTargetIPhoneOS() && !isTargetIOSSimulator()) { + if (isTargetIPhoneOS()) { getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) << "-fsanitize=address"; } else { @@ -348,16 +391,19 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, CmdArgs.push_back("-lSystem"); // Select the dynamic runtime library and the target specific static library. - if (isTargetIPhoneOS()) { + 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()) + 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)) @@ -400,7 +446,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) && StringRef(env) != "/") { Args.append(Args.MakeSeparateArg( - 0, Opts.getOption(options::OPT_isysroot), env)); + nullptr, Opts.getOption(options::OPT_isysroot), env)); } } } @@ -414,12 +460,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { getDriver().Diag(diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args); - iOSVersion = iOSSimVersion = 0; + iOSVersion = iOSSimVersion = nullptr; } else if (iOSVersion && iOSSimVersion) { getDriver().Diag(diag::err_drv_argument_not_allowed_with) << iOSVersion->getAsString(Args) << iOSSimVersion->getAsString(Args); - iOSSimVersion = 0; + iOSSimVersion = nullptr; } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) { // If no deployment target was specified on the command line, check for // environment defines. @@ -440,7 +486,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef first, second; StringRef isysroot = A->getValue(); - llvm::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS")); + std::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS")); if (second != "") iOSTarget = second.substr(0,3); } @@ -448,9 +494,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // 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() && - (getDarwinArchName(Args) == "armv7" || - getDarwinArchName(Args) == "armv7s")) + (MachOArchName == "armv7" || MachOArchName == "armv7s" || + MachOArchName == "arm64")) iOSTarget = iOSVersionMin; // Handle conflicting deployment targets @@ -469,6 +516,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // 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 @@ -477,25 +526,36 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (!OSXTarget.empty()) { const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); - OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget); + 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(0, O, iOSTarget); + 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(0, O, iOSSimTarget); + iOSSimVersion = Args.MakeJoinedArg(nullptr, O, iOSSimTarget); Args.append(iOSSimVersion); - } else { + } 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(0, O, MacosxVersionMin); + 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)) { @@ -506,14 +566,14 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // Set the tool chain target information. unsigned Major, Minor, Micro; bool HadExtra; - if (OSXVersion) { + 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 { + } else if (Platform == IPhoneOS || Platform == IPhoneOSSimulator) { const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; assert(Version && "Unknown target platform!"); if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor, @@ -521,9 +581,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << Version->getAsString(Args); - } - - bool IsIOSSim = bool(iOSSimVersion); + } 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 @@ -531,9 +590,9 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // 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)) - IsIOSSim = true; + Platform = IPhoneOSSimulator; - setTarget(/*IsIPhoneOS=*/ !OSXVersion, Major, Minor, Micro, IsIOSSim); + setTarget(Platform, Major, Minor, Micro); } void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, @@ -594,6 +653,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args, // 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 { @@ -606,8 +667,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(P.str())); } -DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, - const char *BoundArch) const { +DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, + const char *BoundArch) const { DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); const OptTable &Opts = getDriver().getOpts(); @@ -618,24 +679,21 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // have something that works, we should reevaluate each translation // and try to push it down into tool specific logic. - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) { - Arg *A = *it; - + 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::getArchTypeForDarwinArchName(A->getValue(0)); + tools::darwin::getArchTypeForMachOArchName(A->getValue(0)); if (!(XarchArch == getArch() || (BoundArch && XarchArch == - tools::darwin::getArchTypeForDarwinArchName(BoundArch)))) + tools::darwin::getArchTypeForMachOArchName(BoundArch)))) continue; Arg *OriginalArg = A; unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); unsigned Prev = Index; - Arg *XarchArg = Opts.ParseOneArg(Args, 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 @@ -656,8 +714,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, } XarchArg->setBaseArg(A); - A = XarchArg; + A = XarchArg.release(); DAL->AddSynthesizedArg(A); // Linker input arguments require custom handling. The problem is that we @@ -741,7 +799,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64) if (!Args.hasArgNoClaim(options::OPT_mtune_EQ)) - DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2"); + 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. @@ -755,89 +814,114 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, if (Name == "ppc") ; else if (Name == "ppc601") - DAL->AddJoinedArg(0, MCpu, "601"); + DAL->AddJoinedArg(nullptr, MCpu, "601"); else if (Name == "ppc603") - DAL->AddJoinedArg(0, MCpu, "603"); + DAL->AddJoinedArg(nullptr, MCpu, "603"); else if (Name == "ppc604") - DAL->AddJoinedArg(0, MCpu, "604"); + DAL->AddJoinedArg(nullptr, MCpu, "604"); else if (Name == "ppc604e") - DAL->AddJoinedArg(0, MCpu, "604e"); + DAL->AddJoinedArg(nullptr, MCpu, "604e"); else if (Name == "ppc750") - DAL->AddJoinedArg(0, MCpu, "750"); + DAL->AddJoinedArg(nullptr, MCpu, "750"); else if (Name == "ppc7400") - DAL->AddJoinedArg(0, MCpu, "7400"); + DAL->AddJoinedArg(nullptr, MCpu, "7400"); else if (Name == "ppc7450") - DAL->AddJoinedArg(0, MCpu, "7450"); + DAL->AddJoinedArg(nullptr, MCpu, "7450"); else if (Name == "ppc970") - DAL->AddJoinedArg(0, MCpu, "970"); + DAL->AddJoinedArg(nullptr, MCpu, "970"); else if (Name == "ppc64" || Name == "ppc64le") - DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64)); + DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); else if (Name == "i386") ; else if (Name == "i486") - DAL->AddJoinedArg(0, MArch, "i486"); + DAL->AddJoinedArg(nullptr, MArch, "i486"); else if (Name == "i586") - DAL->AddJoinedArg(0, MArch, "i586"); + DAL->AddJoinedArg(nullptr, MArch, "i586"); else if (Name == "i686") - DAL->AddJoinedArg(0, MArch, "i686"); + DAL->AddJoinedArg(nullptr, MArch, "i686"); else if (Name == "pentium") - DAL->AddJoinedArg(0, MArch, "pentium"); + DAL->AddJoinedArg(nullptr, MArch, "pentium"); else if (Name == "pentium2") - DAL->AddJoinedArg(0, MArch, "pentium2"); + DAL->AddJoinedArg(nullptr, MArch, "pentium2"); else if (Name == "pentpro") - DAL->AddJoinedArg(0, MArch, "pentiumpro"); + DAL->AddJoinedArg(nullptr, MArch, "pentiumpro"); else if (Name == "pentIIm3") - DAL->AddJoinedArg(0, MArch, "pentium2"); + DAL->AddJoinedArg(nullptr, MArch, "pentium2"); else if (Name == "x86_64") - DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64)); + DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); else if (Name == "x86_64h") { - DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64)); - DAL->AddJoinedArg(0, MArch, "x86_64h"); + DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); + DAL->AddJoinedArg(nullptr, MArch, "x86_64h"); } else if (Name == "arm") - DAL->AddJoinedArg(0, MArch, "armv4t"); + DAL->AddJoinedArg(nullptr, MArch, "armv4t"); else if (Name == "armv4t") - DAL->AddJoinedArg(0, MArch, "armv4t"); + DAL->AddJoinedArg(nullptr, MArch, "armv4t"); else if (Name == "armv5") - DAL->AddJoinedArg(0, MArch, "armv5tej"); + DAL->AddJoinedArg(nullptr, MArch, "armv5tej"); else if (Name == "xscale") - DAL->AddJoinedArg(0, MArch, "xscale"); + DAL->AddJoinedArg(nullptr, MArch, "xscale"); else if (Name == "armv6") - DAL->AddJoinedArg(0, MArch, "armv6k"); + DAL->AddJoinedArg(nullptr, MArch, "armv6k"); else if (Name == "armv6m") - DAL->AddJoinedArg(0, MArch, "armv6m"); + DAL->AddJoinedArg(nullptr, MArch, "armv6m"); else if (Name == "armv7") - DAL->AddJoinedArg(0, MArch, "armv7a"); + DAL->AddJoinedArg(nullptr, MArch, "armv7a"); else if (Name == "armv7em") - DAL->AddJoinedArg(0, MArch, "armv7em"); - else if (Name == "armv7f") - DAL->AddJoinedArg(0, MArch, "armv7f"); + DAL->AddJoinedArg(nullptr, MArch, "armv7em"); else if (Name == "armv7k") - DAL->AddJoinedArg(0, MArch, "armv7k"); + DAL->AddJoinedArg(nullptr, MArch, "armv7k"); else if (Name == "armv7m") - DAL->AddJoinedArg(0, MArch, "armv7m"); + DAL->AddJoinedArg(nullptr, MArch, "armv7m"); else if (Name == "armv7s") - DAL->AddJoinedArg(0, MArch, "armv7s"); - - else - llvm_unreachable("invalid Darwin arch"); + 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. - if (BoundArch) - AddDeploymentTarget(*DAL); + 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 (isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) { + 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; @@ -854,9 +938,10 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // Default to use libc++ on OS X 10.9+ and iOS 7+. if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) || - (isTargetIPhoneOS() && !isIPhoneOSVersionLT(7, 0))) && + (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) && !Args.getLastArg(options::OPT_stdlib_EQ)) - DAL->AddJoinedArg(0, Opts.getOption(options::OPT_stdlib_EQ), "libc++"); + DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ), + "libc++"); // Validate the C++ standard library choice. CXXStdlibType Type = GetCXXStdlibType(*DAL); @@ -864,8 +949,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // Check whether the target provides libc++. StringRef where; - // Complain about targetting iOS < 5.0 in any way. - if (isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)) + // Complain about targeting iOS < 5.0 in any way. + if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0)) where = "iOS 5.0"; if (where != StringRef()) { @@ -877,11 +962,11 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, return DAL; } -bool Darwin::IsUnwindTablesDefault() const { +bool MachO::IsUnwindTablesDefault() const { return getArch() == llvm::Triple::x86_64; } -bool Darwin::UseDwarfDebugFlags() const { +bool MachO::UseDwarfDebugFlags() const { if (const char *S = ::getenv("RC_DEBUG_OPTIONS")) return S[0] != '\0'; return false; @@ -893,40 +978,145 @@ bool Darwin::UseSjLjExceptions() const { getTriple().getArch() == llvm::Triple::thumb); } -bool Darwin::isPICDefault() const { +bool MachO::isPICDefault() const { return true; } -bool Darwin::isPIEDefault() const { +bool MachO::isPIEDefault() const { return false; } -bool Darwin::isPICDefaultForced() const { - return getArch() == llvm::Triple::x86_64; +bool MachO::isPICDefaultForced() const { + return (getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::arm64 || + getArch() == llvm::Triple::aarch64); } -bool Darwin::SupportsProfiling() const { +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 { - // Garbage collection is supported everywhere except on iPhone OS. - return !isTargetIPhoneOS(); + return isTargetMacOS(); } void Darwin::CheckObjCARC() const { - if (isTargetIPhoneOS() || !isMacosxVersionLT(10, 6)) + if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6))) return; getDriver().Diag(diag::err_arc_unsupported_on_toolchain); } -std::string -Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args, - types::ID InputType) const { - return ComputeLLVMTriple(Args, InputType); -} - /// Generic_GCC - A tool chain using the 'gcc' command to perform /// all subcommands; this relies on gcc translating the majority of /// command line options. @@ -1007,7 +1197,7 @@ bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor, return false; } -static StringRef getGCCToolchainDir(const ArgList &Args) { +static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain); if (A) return A->getValue(); @@ -1025,11 +1215,10 @@ static StringRef getGCCToolchainDir(const ArgList &Args) { /// triple. void Generic_GCC::GCCInstallationDetector::init( - const llvm::Triple &TargetTriple, const ArgList &Args) { + const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) { llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() : TargetTriple.get32BitArchVariant(); - llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // The library directories which may contain GCC installations. SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs; // The compatible GCC triples for this particular architecture. @@ -1075,7 +1264,7 @@ Generic_GCC::GCCInstallationDetector::init( if (!llvm::sys::fs::exists(LibDir)) continue; for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, Args, LibDir, + ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, CandidateTripleAliases[k]); } for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) { @@ -1084,7 +1273,7 @@ Generic_GCC::GCCInstallationDetector::init( continue; for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, Args, LibDir, + ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, CandidateBiarchTripleAliases[k], /*NeedsBiarchSuffix=*/ true); } @@ -1092,13 +1281,25 @@ Generic_GCC::GCCInstallationDetector::init( } void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { - for (std::set<std::string>::const_iterator - I = CandidateGCCInstallPaths.begin(), - E = CandidateGCCInstallPaths.end(); - I != E; ++I) - OS << "Found candidate GCC installation: " << *I << "\n"; + 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"; +} - OS << "Selected GCC installation: " << GCCInstallPath << "\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( @@ -1110,43 +1311,62 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { // Declare a bunch of static data sets that we'll select between below. These // are specifically designed to always refer to string literals to avoid any // lifetime or initialization issues. - static const char *const AArch64LibDirs[] = { "/lib" }; + static const char *const AArch64LibDirs[] = { "/lib64", "/lib" }; static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu", - "aarch64-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-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-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-mti-linux-gnu", + "mips-img-linux-gnu" }; static const char *const MIPSELLibDirs[] = { "/lib" }; static const char *const MIPSELTriples[] = { "mipsel-linux-gnu", - "mipsel-linux-android" }; + "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-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-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[] = { @@ -1178,6 +1398,7 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { }; switch (TargetTriple.getArch()) { + case llvm::Triple::arm64: case llvm::Triple::aarch64: LibDirs.append(AArch64LibDirs, AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs)); @@ -1188,6 +1409,17 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { 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)); @@ -1199,15 +1431,35 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { 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)); - BiarchLibDirs.append(X86LibDirs, - X86LibDirs + llvm::array_lengthof(X86LibDirs)); - BiarchTripleAliases.append(X86Triples, - X86Triples + llvm::array_lengthof(X86Triples)); + // 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)); @@ -1332,42 +1584,47 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const { BiarchTripleAliases.push_back(BiarchTriple.str()); } -static bool isSoftFloatABI(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_msoft_float, - options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ); - if (!A) return false; +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 - return A->getOption().matches(options::OPT_msoft_float) || - (A->getOption().matches(options::OPT_mfloat_abi_EQ) && - A->getValue() == StringRef("soft")); +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; + return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || + Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; } -static bool isMips16(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mips16, - options::OPT_mno_mips16); - return A && A->getOption().matches(options::OPT_mips16); +static bool isMips32(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel; } -static bool isMips32r2(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_march_EQ, - options::OPT_mcpu_EQ); - - return A && A->getValue() == StringRef("mips32r2"); +static bool isMips64(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; } -static bool isMips64r2(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_march_EQ, - options::OPT_mcpu_EQ); +static bool isMipsEL(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el; +} - return A && A->getValue() == StringRef("mips64r2"); +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) { @@ -1376,53 +1633,21 @@ static bool isMicroMips(const ArgList &Args) { return A && A->getOption().matches(options::OPT_mmicromips); } -static bool isMipsFP64(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mfp64, options::OPT_mfp32); - return A && A->getOption().matches(options::OPT_mfp64); -} - -static bool isMipsNan2008(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mnan_EQ); - return A && A->getValue() == StringRef("2008"); -} - -// FIXME: There is the same routine in the Tools.cpp. -static bool hasMipsN32ABIArg(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef("n32")); -} - -static bool hasCrtBeginObj(Twine Path) { - return llvm::sys::fs::exists(Path + "/crtbegin.o"); -} +struct DetectedMultilibs { + /// The set of multilibs that the detected installation supports. + MultilibSet Multilibs; -static bool findTargetBiarchSuffix(std::string &Suffix, StringRef Path, - llvm::Triple::ArchType TargetArch, - const ArgList &Args) { - // FIXME: This routine was only intended to model bi-arch toolchains which - // use -m32 and -m64 to swap between variants of a target. It shouldn't be - // doing ABI-based builtin location for MIPS. - if (hasMipsN32ABIArg(Args)) - Suffix = "/n32"; - else if (TargetArch == llvm::Triple::x86_64 || - TargetArch == llvm::Triple::ppc64 || - TargetArch == llvm::Triple::sparcv9 || - TargetArch == llvm::Triple::systemz || - TargetArch == llvm::Triple::mips64 || - TargetArch == llvm::Triple::mips64el) - Suffix = "/64"; - else - Suffix = "/32"; + /// The primary multilib appropriate for the given flags. + Multilib SelectedMultilib; - return hasCrtBeginObj(Path + Suffix); -} - -void Generic_GCC::GCCInstallationDetector::findMIPSABIDirSuffix( - std::string &Suffix, llvm::Triple::ArchType TargetArch, StringRef Path, - const llvm::opt::ArgList &Args) { - if (!isMipsArch(TargetArch)) - return; + /// 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 @@ -1447,71 +1672,362 @@ void Generic_GCC::GCCInstallationDetector::findMIPSABIDirSuffix( // /mips32 // /usr // /lib <= crt*.o files compiled with '-mips32' - // - // Unfortunately different toolchains use different and partially - // overlapped naming schemes. So we have to make a trick for detection - // of using toolchain. We lookup a path which unique for each toolchains. - - bool IsMentorToolChain = hasCrtBeginObj(Path + "/mips16/soft-float"); - bool IsFSFToolChain = hasCrtBeginObj(Path + "/mips32/mips16/sof"); - - if (IsMentorToolChain && IsFSFToolChain) - D.Diag(diag::err_drv_unknown_toolchain); - - if (IsMentorToolChain) { - if (isMips16(Args)) - Suffix += "/mips16"; - else if (isMicroMips(Args)) - Suffix += "/micromips"; - - if (isSoftFloatABI(Args)) - Suffix += "/soft-float"; - - if (TargetArch == llvm::Triple::mipsel || - TargetArch == llvm::Triple::mips64el) - Suffix += "/el"; - } else if (IsFSFToolChain) { - if (TargetArch == llvm::Triple::mips || - TargetArch == llvm::Triple::mipsel) { - if (isMicroMips(Args)) - Suffix += "/micromips"; - else if (isMips32r2(Args)) - Suffix += ""; - else - Suffix += "/mips32"; - if (isMips16(Args)) - Suffix += "/mips16"; - } else { - if (isMips64r2(Args)) - Suffix += hasMipsN32ABIArg(Args) ? "/mips64r2" : "/mips64r2/64"; - else - Suffix += hasMipsN32ABIArg(Args) ? "/mips64" : "/mips64/64"; + 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; + } - if (TargetArch == llvm::Triple::mipsel || - TargetArch == llvm::Triple::mips64el) - Suffix += "/el"; + // 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; + } + } - if (isSoftFloatABI(Args)) - Suffix += "/sof"; - else { - if (isMipsFP64(Args)) - Suffix += "/fp64"; + { + // Fallback to the regular toolchain-tree structure. + Multilib Default; + Result.Multilibs.push_back(Default); + Result.Multilibs.FilterOut(NonExistent); - if (isMipsNan2008(Args)) - Suffix += "/nan2008"; + if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) { + Result.BiarchSibling = Multilib(); + return true; } } - if (!hasCrtBeginObj(Path + Suffix)) - Suffix.clear(); + 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( - llvm::Triple::ArchType TargetArch, const ArgList &Args, + 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. @@ -1543,7 +2059,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( (llvm::array_lengthof(LibSuffixes) - (TargetArch != llvm::Triple::x86)); for (unsigned i = 0; i < NumLibSuffixes; ++i) { StringRef LibSuffix = LibSuffixes[i]; - llvm::error_code EC; + 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()); @@ -1556,28 +2072,21 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( if (CandidateVersion <= Version) continue; - std::string MIPSABIDirSuffix; - findMIPSABIDirSuffix(MIPSABIDirSuffix, TargetArch, LI->path(), Args); - - // Some versions of SUSE and Fedora on ppc64 put 32-bit libs - // in what would normally be GCCInstallPath and put the 64-bit - // libs in a subdirectory named 64. The simple logic we follow is that - // *if* there is a subdirectory of the right name with crtbegin.o in it, - // we use that. If not, and if not a biarch triple alias, we look for - // crtbegin.o without the subdirectory. - - std::string BiarchSuffix; - if (findTargetBiarchSuffix(BiarchSuffix, - LI->path() + MIPSABIDirSuffix, - TargetArch, Args)) { - GCCBiarchSuffix = BiarchSuffix; - } else if (NeedsBiarchSuffix || - !hasCrtBeginObj(LI->path() + MIPSABIDirSuffix)) { + 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; - } else { - GCCBiarchSuffix.clear(); } + Multilibs = Detected.Multilibs; + SelectedMultilib = Detected.SelectedMultilib; + BiarchSibling = Detected.BiarchSibling; Version = CandidateVersion; GCCTriple.setTriple(CandidateTriple); // FIXME: We hack together the directory name here instead of @@ -1585,7 +2094,6 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // Linux. GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str(); GCCParentLibPath = GCCInstallPath + InstallSuffixes[i]; - GCCMIPSABIDirSuffix = MIPSABIDirSuffix; IsValid = true; } } @@ -1593,7 +2101,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), GCCInstallation(getDriver()) { + : ToolChain(D, Triple, Args), GCCInstallation() { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -1608,10 +2116,6 @@ Tool *Generic_GCC::getTool(Action::ActionClass AC) const { if (!Preprocess) Preprocess.reset(new tools::gcc::Preprocess(*this)); return Preprocess.get(); - case Action::PrecompileJobClass: - if (!Precompile) - Precompile.reset(new tools::gcc::Precompile(*this)); - return Precompile.get(); case Action::CompileJobClass: if (!Compile) Compile.reset(new tools::gcc::Compile(*this)); @@ -1622,7 +2126,7 @@ Tool *Generic_GCC::getTool(Action::ActionClass AC) const { } Tool *Generic_GCC::buildAssembler() const { - return new tools::gcc::Assemble(*this); + return new tools::gnutools::Assemble(*this); } Tool *Generic_GCC::buildLinker() const { @@ -1650,14 +2154,30 @@ bool Generic_GCC::isPICDefaultForced() const { return false; } -void Generic_GCC::addClangTargetOptions(const ArgList &DriverArgs, +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 = + bool UseInitArrayDefault = getTriple().getArch() == llvm::Triple::aarch64 || - (getTriple().getOS() == llvm::Triple::Linux && ( - !V.isOlderThan(4, 7, 0) || - getTriple().getEnvironment() == llvm::Triple::Android)); + 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, @@ -1749,7 +2269,7 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, // Determine version of GCC libraries and headers to use. const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon"); - llvm::error_code ec; + 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)) { @@ -1941,6 +2461,21 @@ 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) || @@ -1950,7 +2485,7 @@ void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: addSystemInclude(DriverArgs, CC1Args, - getDriver().SysRoot + "/usr/include/c++/"); + getDriver().SysRoot + "/usr/include/c++/v1"); break; case ToolChain::CST_Libstdcxx: addSystemInclude(DriverArgs, CC1Args, @@ -1976,9 +2511,8 @@ void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args, switch (GetCXXStdlibType(Args)) { case ToolChain::CST_Libcxx: CmdArgs.push_back("-lc++"); - CmdArgs.push_back("-lcxxrt"); - // Include supc++ to provide Unwind until provided by libcxx. - CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lpthread"); break; case ToolChain::CST_Libstdcxx: CmdArgs.push_back("-lstdc++"); @@ -2060,6 +2594,14 @@ bool FreeBSD::UseSjLjExceptions() const { } } +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) @@ -2071,8 +2613,39 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) // 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. - if (Triple.getArch() == llvm::Triple::x86) + 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"); } @@ -2101,9 +2674,18 @@ NetBSD::GetCXXStdlibType(const ArgList &Args) const { unsigned Major, Minor, Micro; getTriple().getOSVersion(Major, Minor, Micro); - if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) { - if (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64) + 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; } @@ -2239,8 +2821,9 @@ static bool IsUbuntu(enum Distro Distro) { } static Distro DetectDistro(llvm::Triple::ArchType Arch) { - OwningPtr<llvm::MemoryBuffer> File; - if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) { + 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"); @@ -2265,25 +2848,25 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { return Version; } - if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { + File = llvm::MemoryBuffer::getFile("/etc/redhat-release"); + if (File) { StringRef Data = File.get()->getBuffer(); if (Data.startswith("Fedora release")) return Fedora; - else if (Data.startswith("Red Hat Enterprise Linux") && - Data.find("release 6") != StringRef::npos) - return RHEL6; - else if ((Data.startswith("Red Hat Enterprise Linux") || - Data.startswith("CentOS")) && - Data.find("release 5") != StringRef::npos) - return RHEL5; - else if ((Data.startswith("Red Hat Enterprise Linux") || - Data.startswith("CentOS")) && - Data.find("release 4") != StringRef::npos) - return RHEL4; + 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; } - if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) { + File = llvm::MemoryBuffer::getFile("/etc/debian_version"); + if (File) { StringRef Data = File.get()->getBuffer(); if (Data[0] == '5') return DebianLenny; @@ -2314,7 +2897,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { /// 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, +static std::string getMultiarchTriple(const llvm::Triple &TargetTriple, StringRef SysRoot) { // For most architectures, just use whatever we have rather than trying to be // clever. @@ -2336,18 +2919,36 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple, 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: - if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu")) + // 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"; @@ -2356,6 +2957,18 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple, 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"; @@ -2376,36 +2989,40 @@ static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); } -static StringRef getMultilibDir(const llvm::Triple &Triple, - const ArgList &Args) { +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 (hasMipsN32ABIArg(Args)) + 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 multilib, and + // 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' multilib search path being considered. So we only enable + // 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 multilib spellings with the lib dir spellings in the + // 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(Triple, Args); + GCCInstallation.init(D, Triple, Args); + Multilibs = GCCInstallation.getMultilibs(); llvm::Triple::ArchType Arch = Triple.getArch(); std::string SysRoot = computeSysRoot(); @@ -2421,7 +3038,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" + GCCInstallation.getTriple().str() + "/bin").str()); - Linker = GetProgramPath("ld"); + Linker = GetLinkerPath(); Distro Distro = DetectDistro(Arch); @@ -2473,29 +3090,20 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // to the link paths. path_list &Paths = getFilePaths(); - const std::string Multilib = getMultilibDir(Triple, Args); + 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. - // - // FIXME: It would be cleaner to model this as a variant of bi-arch. IE, - // instead of a '64' biarch suffix it would be 'el' or something. - if (IsAndroid && IsMips && isMips32r2(Args)) { - assert(GCCInstallation.getBiarchSuffix().empty() && - "Unexpected bi-arch suffix"); - addPathIfExists(GCCInstallation.getInstallPath() + "/mips-r2", Paths); - } else { - addPathIfExists((GCCInstallation.getInstallPath() + - GCCInstallation.getMIPSABIDirSuffix() + - GCCInstallation.getBiarchSuffix()), - Paths); - } + 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 @@ -2503,7 +3111,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat // debatable, but is the reality today. We need to search this tree even // when we have a sysroot somewhere else. It is the responsibility of - // whomever is doing the cross build targetting a sysroot using a GCC + // 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 @@ -2515,8 +3123,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib + - GCCInstallation.getMIPSABIDirSuffix(), + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir + + Multilib.osSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -2530,45 +3138,64 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // a bug. if (StringRef(LibPath).startswith(SysRoot)) { addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); - addPathIfExists(LibPath + "/../" + Multilib, 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/../" + Multilib, Paths); + addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths); addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths); - addPathIfExists(SysRoot + "/usr/lib/../" + Multilib, 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() + - "/../../" + Multilib, Paths); + "/../../" + OSLibDir, Paths); - // Add the non-multilib suffixed paths (if potentially different). - const std::string &LibPath = GCCInstallation.getParentLibPath(); - const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); - if (!GCCInstallation.getBiarchSuffix().empty()) + // Add the 'other' biarch variant path + Multilib BiarchSibling; + if (GCCInstallation.getBiarchSibling(BiarchSibling)) { addPathIfExists(GCCInstallation.getInstallPath() + - GCCInstallation.getMIPSABIDirSuffix(), Paths); + 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" + GCCInstallation.getMIPSABIDirSuffix(), Paths); + "/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 FreeBSD::HasNativeLLVMSupport() const { - return true; -} - bool Linux::HasNativeLLVMSupport() const { return true; } @@ -2594,15 +3221,15 @@ std::string Linux::computeSysRoot() const { const StringRef InstallDir = GCCInstallation.getInstallPath(); const StringRef TripleStr = GCCInstallation.getTriple().str(); - const StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix(); + const Multilib &Multilib = GCCInstallation.getMultilib(); std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" + - MIPSABIDirSuffix).str(); + Multilib.osSuffix()).str(); if (llvm::sys::fs::exists(Path)) return Path; - Path = (InstallDir + "/../../../../sysroot" + MIPSABIDirSuffix).str(); + Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str(); if (llvm::sys::fs::exists(Path)) return Path; @@ -2635,10 +3262,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (CIncludeDirs != "") { SmallVector<StringRef, 5> dirs; CIncludeDirs.split(dirs, ":"); - for (SmallVectorImpl<StringRef>::iterator I = dirs.begin(), E = dirs.end(); - I != E; ++I) { - StringRef Prefix = llvm::sys::path::is_absolute(*I) ? SysRoot : ""; - addExternCSystemInclude(DriverArgs, CC1Args, Prefix + *I); + for (StringRef dir : dirs) { + StringRef Prefix = llvm::sys::path::is_absolute(dir) ? SysRoot : ""; + addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); } return; } @@ -2695,18 +3321,32 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 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) { + } 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) @@ -2717,16 +3357,20 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 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 (ArrayRef<StringRef>::iterator I = MultiarchIncludeDirs.begin(), - E = MultiarchIncludeDirs.end(); - I != E; ++I) { - if (llvm::sys::fs::exists(SysRoot + *I)) { - addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + *I); + for (StringRef Dir : MultiarchIncludeDirs) { + if (llvm::sys::fs::exists(SysRoot + Dir)) { + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir); break; } } @@ -2742,33 +3386,39 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); } -/// \brief Helper to add the three variant paths for a libstdc++ installation. -/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, - const ArgList &DriverArgs, - ArgStringList &CC1Args) { - if (!llvm::sys::fs::exists(Base)) - return false; - addSystemInclude(DriverArgs, CC1Args, Base); - addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir); - addSystemInclude(DriverArgs, CC1Args, Base + "/backward"); - return true; -} - -/// \brief Helper to add an extra variant path for an (Ubuntu) multilib -/// libstdc++ installation. +/// \brief Helper to add the variant paths of a libstdc++ installation. /*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix, - Twine TargetArchDir, - Twine BiarchSuffix, - Twine MIPSABIDirSuffix, + StringRef GCCTriple, + StringRef GCCMultiarchTriple, + StringRef TargetMultiarchTriple, + Twine IncludeSuffix, const ArgList &DriverArgs, ArgStringList &CC1Args) { - if (!addLibStdCXXIncludePaths(Base + Suffix, - TargetArchDir + MIPSABIDirSuffix + BiarchSuffix, - DriverArgs, CC1Args)) + if (!llvm::sys::fs::exists(Base + Suffix)) return false; - addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix - + MIPSABIDirSuffix + BiarchSuffix); + 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; } @@ -2780,9 +3430,23 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, // Check if libc++ has been enabled and provide its include paths if so. if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) { - // libc++ is always installed at a fixed path on Linux currently. - addSystemInclude(DriverArgs, CC1Args, - getDriver().SysRoot + "/usr/include/c++/v1"); + 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; } @@ -2797,16 +3461,23 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef TripleStr = GCCInstallation.getTriple().str(); - StringRef MIPSABIDirSuffix = GCCInstallation.getMIPSABIDirSuffix(); - StringRef BiarchSuffix = GCCInstallation.getBiarchSuffix(); + 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, BiarchSuffix, - MIPSABIDirSuffix, DriverArgs, CC1Args)) + "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple, + TargetMultiarchTriple, + Multilib.includeSuffix(), DriverArgs, CC1Args)) return; - const std::string IncludePathCandidates[] = { + // 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 + "." + @@ -2819,10 +3490,11 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, LibDir.str() + "/../include/c++", }; - for (unsigned i = 0; i < llvm::array_lengthof(IncludePathCandidates); ++i) { - if (addLibStdCXXIncludePaths(IncludePathCandidates[i], - TripleStr + MIPSABIDirSuffix + BiarchSuffix, - DriverArgs, CC1Args)) + for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { + if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr, + /*GCCMultiarchTriple*/ "", + /*TargetMultiarchTriple*/ "", + Multilib.includeSuffix(), DriverArgs, CC1Args)) break; } } @@ -2892,7 +3564,6 @@ bool XCore::hasBlocksRuntime() const { return false; } - void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc) || diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index 50e745a..b5df866 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -13,11 +13,13 @@ #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 <vector> #include <set> +#include <vector> namespace clang { namespace driver { @@ -67,7 +69,6 @@ protected: bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } }; - /// \brief This is a class to find a viable GCC installation for Clang to /// use. /// @@ -76,14 +77,17 @@ protected: /// Driver, and has logic for fuzzing that where appropriate. class GCCInstallationDetector { bool IsValid; - const Driver &D; llvm::Triple GCCTriple; // FIXME: These might be better as path objects. std::string GCCInstallPath; - std::string GCCBiarchSuffix; std::string GCCParentLibPath; - std::string GCCMIPSABIDirSuffix; + + /// 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; @@ -91,9 +95,13 @@ protected: // 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(const Driver &D) : IsValid(false), D(D) {} - void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args); + 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; } @@ -104,26 +112,18 @@ protected: /// \brief Get the detected GCC installation path. StringRef getInstallPath() const { return GCCInstallPath; } - /// \brief Get the detected GCC installation path suffix for the bi-arch - /// target variant. - StringRef getBiarchSuffix() const { return GCCBiarchSuffix; } - /// \brief Get the detected GCC parent lib path. StringRef getParentLibPath() const { return GCCParentLibPath; } - /// \brief Get the detected GCC MIPS ABI directory suffix. - /// - /// This is used as a suffix both to the install directory of GCC and as - /// a suffix to its parent lib path in order to select a MIPS ABI-specific - /// subdirectory. - /// - /// This will always be empty for any non-MIPS target. - /// - // FIXME: This probably shouldn't exist at all, and should be factored - // into the multiarch and/or biarch support. Please don't add more uses of - // this interface, it is meant as a legacy crutch for the MIPS driver - // logic. - StringRef getMIPSABIDirSuffix() const { return GCCMIPSABIDirSuffix; } + /// \brief Get the detected 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; } @@ -140,15 +140,11 @@ protected: SmallVectorImpl<StringRef> &BiarchLibDirs, SmallVectorImpl<StringRef> &BiarchTripleAliases); - void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, + void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsBiarchSuffix = false); - - void findMIPSABIDirSuffix(std::string &Suffix, - llvm::Triple::ArchType TargetArch, StringRef Path, - const llvm::opt::ArgList &Args); }; GCCInstallationDetector GCCInstallation; @@ -158,19 +154,18 @@ public: const llvm::opt::ArgList &Args); ~Generic_GCC(); - virtual void printVerboseInfo(raw_ostream &OS) const; + void printVerboseInfo(raw_ostream &OS) const override; - virtual bool IsUnwindTablesDefault() const; - virtual bool isPICDefault() const; - virtual bool isPIEDefault() const; - virtual bool isPICDefaultForced() const; - virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; + bool IsUnwindTablesDefault() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; + bool IsIntegratedAssemblerDefault() const override; protected: - virtual Tool *getTool(Action::ActionClass AC) const; - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *getTool(Action::ActionClass AC) const override; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; /// \name ToolChain Implementation Helper Functions /// @{ @@ -184,27 +179,138 @@ protected: /// @} private: - mutable OwningPtr<tools::gcc::Preprocess> Preprocess; - mutable OwningPtr<tools::gcc::Precompile> Precompile; - mutable OwningPtr<tools::gcc::Compile> Compile; + 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 ToolChain { +class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { public: /// The host version. unsigned DarwinVersion[3]; -protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; - virtual Tool *getTool(Action::ActionClass AC) const; - -private: - mutable OwningPtr<tools::darwin::Lipo> Lipo; - mutable OwningPtr<tools::darwin::Dsymutil> Dsymutil; - mutable OwningPtr<tools::darwin::VerifyDebug> VerifyDebug; - /// Whether the information on the target has been initialized. // // FIXME: This should be eliminated. What we want to do is make this part of @@ -212,11 +318,13 @@ private: // the argument translation business. mutable bool TargetInitialized; - /// Whether we are targeting iPhoneOS target. - mutable bool TargetIsIPhoneOS; + enum DarwinPlatformKind { + MacOS, + IPhoneOS, + IPhoneOSSimulator + }; - /// Whether we are targeting the iPhoneOS simulator target. - mutable bool TargetIsIPhoneOSSimulator; + mutable DarwinPlatformKind TargetPlatform; /// The OS version we are targeting. mutable VersionTuple TargetVersion; @@ -239,43 +347,62 @@ public: ~Darwin(); std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, - types::ID InputType) const; + 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; - /// @name Darwin Specific Toolchain API + 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(bool IsIPhoneOS, unsigned Major, unsigned Minor, - unsigned Micro, bool IsIOSSim) const { - assert((!IsIOSSim || IsIPhoneOS) && "Unexpected deployment target!"); - + 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 && TargetIsIPhoneOS == IsIPhoneOS && - TargetIsIPhoneOSSimulator == IsIOSSim && + if (TargetInitialized && TargetPlatform == Platform && TargetVersion == VersionTuple(Major, Minor, Micro)) return; assert(!TargetInitialized && "Target already initialized!"); TargetInitialized = true; - TargetIsIPhoneOS = IsIPhoneOS; - TargetIsIPhoneOSSimulator = IsIOSSim; + TargetPlatform = Platform; TargetVersion = VersionTuple(Major, Minor, Micro); } bool isTargetIPhoneOS() const { assert(TargetInitialized && "Target not initialized!"); - return TargetIsIPhoneOS; + return TargetPlatform == IPhoneOS; } bool isTargetIOSSimulator() const { assert(TargetInitialized && "Target not initialized!"); - return TargetIsIPhoneOSSimulator; + return TargetPlatform == IPhoneOSSimulator; + } + + bool isTargetIOSBased() const { + assert(TargetInitialized && "Target not initialized!"); + return isTargetIPhoneOS() || isTargetIOSSimulator(); } bool isTargetMacOS() const { - return !isTargetIOSSimulator() && !isTargetIPhoneOS(); + return TargetPlatform == MacOS; } bool isTargetInitialized() const { return TargetInitialized; } @@ -285,101 +412,58 @@ public: return TargetVersion; } - /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler - /// invocation. For example, Darwin treats different ARM variations as - /// distinct architectures. - StringRef getDarwinArchName(const llvm::opt::ArgList &Args) const; - bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const { - assert(isTargetIPhoneOS() && "Unexpected call for OS X target!"); + 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(!isTargetIPhoneOS() && "Unexpected call for iPhoneOS target!"); + assert(isTargetMacOS() && "Unexpected call for non OS X target!"); return TargetVersion < VersionTuple(V0, V1, V2); } - /// AddLinkARCArgs - Add the linker arguments to link the ARC runtime library. - virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const = 0; - - /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler - /// runtime library. - virtual void - AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const = 0; - +public: /// } /// @name ToolChain Implementation /// { - virtual types::ID LookupTypeForExtension(const char *Ext) const; + // 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; } - virtual bool HasNativeLLVMSupport() const; - - virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const; - virtual bool hasBlocksRuntime() const; - - virtual llvm::opt::DerivedArgList * + llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, - const char *BoundArch) const; - - virtual bool IsBlocksDefault() const { - // Always allow blocks on Darwin; users interested in versioning are - // expected to use /usr/include/Blocks.h. - return true; - } - virtual bool IsIntegratedAssemblerDefault() const { - // Default integrated assembler to on for Darwin. - return true; - } + const char *BoundArch) const override; - virtual bool IsMathErrnoDefault() const { - return false; - } + ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override; + bool hasBlocksRuntime() const override; - virtual bool IsEncodeExtendedBlockSignatureDefault() const { - return true; - } - - virtual bool IsObjCNonFragileABIDefault() const { - // Non-fragile ABI is default for everything but i386. - return getTriple().getArch() != llvm::Triple::x86; - } - - virtual bool UseObjCMixedDispatch() const { + 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 !(!isTargetIPhoneOS() && isMacosxVersionLT(10, 6)); + return !(isTargetMacOS() && isMacosxVersionLT(10, 6)); } - virtual bool IsUnwindTablesDefault() const; - virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { + + 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 - return isTargetIPhoneOS() || - (!isMacosxVersionLT(10, 6) || - (!isMacosxVersionLT(10, 5) && !KernelOrKext)); + if (isTargetIOSBased()) + return 1; + else if (isTargetMacOS() && !isMacosxVersionLT(10, 6)) + return 1; + else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext) + return 1; + + return 0; } - virtual RuntimeLibType GetDefaultRuntimeLibType() const { - return ToolChain::RLT_CompilerRT; - } - virtual bool isPICDefault() const; - virtual bool isPIEDefault() const; - virtual bool isPICDefaultForced() const; - - virtual bool SupportsProfiling() const; - virtual bool SupportsObjCGC() const; + bool SupportsObjCGC() const override; - virtual void CheckObjCARC() const; + void CheckObjCARC() const override; - virtual bool UseDwarfDebugFlags() const; - - virtual bool UseSjLjExceptions() const; - - /// } + bool UseSjLjExceptions() const override; }; /// DarwinClang - The Darwin toolchain used by Clang. @@ -388,38 +472,27 @@ public: DarwinClang(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - /// @name Darwin ToolChain Implementation + /// @name Apple ToolChain Implementation /// { - virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; - void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs, - const char *DarwinStaticLib, - bool AlwaysLink = false) const; - - virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; + void + AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; - virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; + void + AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; - virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; - /// } -}; + void + AddCCKextLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; -/// Darwin_Generic_GCC - Generic Darwin tool chain using gcc. -class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC { -public: - Darwin_Generic_GCC(const Driver &D, const llvm::Triple &Triple, - const llvm::opt::ArgList &Args) - : Generic_GCC(D, Triple, Args) {} + virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const; - std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, - types::ID InputType) const; - - virtual bool isPICDefault() const { return false; } + void + AddLinkARCArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + /// } }; class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { @@ -429,12 +502,8 @@ public: const llvm::opt::ArgList &Args) : Generic_GCC(D, Triple, Args) {} - virtual bool IsIntegratedAssemblerDefault() const { - // Default integrated assembler to on for x86. - return (getTriple().getArch() == llvm::Triple::aarch64 || - getTriple().getArch() == llvm::Triple::x86 || - getTriple().getArch() == llvm::Triple::x86_64); - } + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; }; class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { @@ -443,8 +512,8 @@ public: const llvm::opt::ArgList &Args); protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC { @@ -452,10 +521,10 @@ public: Solaris(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsIntegratedAssemblerDefault() const { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; @@ -465,17 +534,25 @@ public: OpenBSD(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsMathErrnoDefault() const { return false; } - virtual bool IsObjCNonFragileABIDefault() const { return true; } - virtual bool isPIEDefault() const { return true; } + 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 unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { - return 1; + 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: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY Bitrig : public Generic_ELF { @@ -483,48 +560,49 @@ public: Bitrig(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsMathErrnoDefault() const { return false; } - virtual bool IsObjCNonFragileABIDefault() const { return true; } - virtual bool IsObjCLegacyDispatchDefault() const { return false; } + bool IsMathErrnoDefault() const override { return false; } + bool IsObjCNonFragileABIDefault() const override { return true; } - virtual void + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; - virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { + 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: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + 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); - virtual bool HasNativeLLVMSupport() const; + bool HasNativeLLVMSupport() const override; - virtual bool IsMathErrnoDefault() const { return false; } - virtual bool IsObjCNonFragileABIDefault() const { return true; } + bool IsMathErrnoDefault() const override { return false; } + bool IsObjCNonFragileABIDefault() const override { return true; } - virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const; - virtual void + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual bool IsIntegratedAssemblerDefault() const { + 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(); } - virtual bool UseSjLjExceptions() const; + bool UseSjLjExceptions() const override; + bool isPIEDefault() const override; protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF { @@ -532,26 +610,26 @@ public: NetBSD(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsMathErrnoDefault() const { return false; } - virtual bool IsObjCNonFragileABIDefault() const { return true; } + bool IsMathErrnoDefault() const override { return false; } + bool IsObjCNonFragileABIDefault() const override { return true; } - virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const; + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; - virtual void + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual bool IsUnwindTablesDefault() const { + llvm::opt::ArgStringList &CC1Args) const override; + bool IsUnwindTablesDefault() const override { return true; } - virtual bool IsIntegratedAssemblerDefault() const { + bool IsIntegratedAssemblerDefault() const override { if (getTriple().getArch() == llvm::Triple::ppc) return true; return Generic_ELF::IsIntegratedAssemblerDefault(); } protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF { @@ -560,8 +638,8 @@ public: const llvm::opt::ArgList &Args); protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF { @@ -569,11 +647,11 @@ public: DragonFly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsMathErrnoDefault() const { return false; } + bool IsMathErrnoDefault() const override { return false; } protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { @@ -581,31 +659,29 @@ public: Linux(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool HasNativeLLVMSupport() const; + bool HasNativeLLVMSupport() const override; - virtual void + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void + llvm::opt::ArgStringList &CC1Args) const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual bool isPIEDefault() const; + llvm::opt::ArgStringList &CC1Args) const override; + bool isPIEDefault() const override; std::string Linker; std::vector<std::string> ExtraOpts; protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; private: static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, - Twine TargetArchDir, - Twine BiarchSuffix, - Twine MIPSABIDirSuffix, - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args); - static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, + StringRef GCCTriple, + StringRef GCCMultiarchTriple, + StringRef TargetMultiarchTriple, + Twine IncludeSuffix, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args); @@ -615,21 +691,21 @@ private: class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public Linux { protected: GCCVersion GCCLibAndIncVersion; - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + 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(); - virtual void + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void + llvm::opt::ArgStringList &CC1Args) const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const; + llvm::opt::ArgStringList &CC1Args) const override; + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; } @@ -646,10 +722,10 @@ public: const llvm::opt::ArgList &Args); ~TCEToolChain(); - bool IsMathErrnoDefault() const; - bool isPICDefault() const; - bool isPIEDefault() const; - bool isPICDefaultForced() const; + bool IsMathErrnoDefault() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; }; class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { @@ -657,22 +733,22 @@ public: Windows(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - virtual bool IsIntegratedAssemblerDefault() const; - virtual bool IsUnwindTablesDefault() const; - virtual bool isPICDefault() const; - virtual bool isPIEDefault() const; - virtual bool isPICDefaultForced() const; + bool IsIntegratedAssemblerDefault() const override; + bool IsUnwindTablesDefault() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; - virtual void + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void + llvm::opt::ArgStringList &CC1Args) const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; + llvm::opt::ArgStringList &CC1Args) const override; protected: - virtual Tool *buildLinker() const; - virtual Tool *buildAssembler() const; + Tool *buildLinker() const override; + Tool *buildAssembler() const override; }; @@ -681,22 +757,22 @@ public: XCore(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); protected: - virtual Tool *buildAssembler() const; - virtual Tool *buildLinker() const; + Tool *buildAssembler() const override; + Tool *buildLinker() const override; public: - virtual bool isPICDefault() const; - virtual bool isPIEDefault() const; - virtual bool isPICDefaultForced() const; - virtual bool SupportsProfiling() const; - virtual bool hasBlocksRuntime() const; - virtual void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const; + 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 diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 525a9f0..89db52e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -10,6 +10,7 @@ #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" @@ -21,7 +22,6 @@ #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" -#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -29,28 +29,47 @@ #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/Program.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include <sys/stat.h> using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +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) && !D.CCCIsCPP()) + 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->getAsString(Args) << "-E"; + << A->getBaseArg().getAsString(Args) + << (D.IsCLMode() ? "/E, /P or /EP" : "-E"); + } + } } /// CheckCodeGenerationOptions - Perform some validation of code generation @@ -157,10 +176,7 @@ static void AddLinkerInputs(const ToolChain &TC, // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + 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 || @@ -181,16 +197,23 @@ static void AddLinkerInputs(const ToolChain &TC, const Arg &A = II.getInputArg(); // Handle reserved library options. - if (A.getOption().matches(options::OPT_Z_reserved_lib_stdcxx)) { + 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)) { + else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext)) TC.AddCCKextLibArgs(Args, CmdArgs); - } else - A.renderAsInput(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. - addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + // and only supported on native toolchains. + if (!TC.isCrossCompiling()) + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); } /// \brief Determine whether Objective-C automated reference counting is @@ -208,25 +231,6 @@ static bool isObjCRuntimeLinked(const ArgList &Args) { return Args.hasArg(options::OPT_fobjc_link_runtime); } -static void addProfileRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, - llvm::Triple Triple) { - if (!(Args.hasArg(options::OPT_fprofile_arcs) || - Args.hasArg(options::OPT_fprofile_generate) || - Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_coverage))) - return; - - // GCC links libgcov.a by adding -L<inst>/gcc/lib/gcc/<triple>/<ver> -lgcov to - // the link line. We cannot do the same thing because unlike gcov there is a - // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is - // not supported by old linkers. - std::string ProfileRT = - std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a"; - - CmdArgs.push_back(Args.MakeArgString(ProfileRT)); -} - static bool forwardToGCC(const Option &O) { // Don't forward inputs from the original command line. They are added from // InputInfoList. @@ -297,6 +301,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, 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)) { @@ -442,130 +449,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs); } -/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular -/// CPU. -// -// FIXME: This is redundant with -mcpu, why does LLVM use this. -// FIXME: tblgen this, or kill it! -static const char *getLLVMArchSuffixForARM(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", "v7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7") - .Cases("cortex-r4", "cortex-r5", "v7r") - .Case("cortex-m0", "v6m") - .Case("cortex-m3", "v7m") - .Case("cortex-m4", "v7em") - .Case("cortex-a9-mp", "v7f") - .Case("swift", "v7s") - .Cases("cortex-a53", "cortex-a57", "v8") - .Default(""); -} - -/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. -// -// FIXME: tblgen this. -static std::string 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; - } - - 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(); - } - - if (Triple.getOS() == llvm::Triple::NetBSD || - Triple.getOS() == llvm::Triple::FreeBSD) { - if (MArch == "armv6") - return "arm1176jzf-s"; - } - - // Handle -march=native. - std::string NativeMArch; - 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. - NativeMArch = std::string("arm") + getLLVMArchSuffixForARM(CPU); - MArch = NativeMArch; - } - } - - return llvm::StringSwitch<const char *>(MArch) - .Cases("armv2", "armv2a","arm2") - .Case("armv3", "arm6") - .Case("armv3m", "arm7m") - .Case("armv4", "strongarm") - .Case("armv4t", "arm7tdmi") - .Cases("armv5", "armv5t", "arm10tdmi") - .Cases("armv5e", "armv5te", "arm1022e") - .Case("armv5tej", "arm926ej-s") - .Cases("armv6", "armv6k", "arm1136jf-s") - .Case("armv6j", "arm1136j-s") - .Cases("armv6z", "armv6zk", "arm1176jzf-s") - .Case("armv6t2", "arm1156t2-s") - .Cases("armv6m", "armv6-m", "cortex-m0") - .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") - .Cases("armv7em", "armv7e-m", "cortex-m4") - .Cases("armv7f", "armv7-f", "cortex-a9-mp") - .Cases("armv7s", "armv7-s", "swift") - .Cases("armv7r", "armv7-r", "cortex-r4") - .Cases("armv7m", "armv7-m", "cortex-m3") - .Cases("armv8", "armv8a", "armv8-a", "cortex-a53") - .Case("ep9312", "ep9312") - .Case("iwmmxt", "iwmmxt") - .Case("xscale", "xscale") - // If all else failed, return the most base CPU with thumb interworking - // supported by LLVM. - .Default("arm7tdmi"); -} - -/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are targeting. -// -// FIXME: tblgen this. -static std::string getAArch64TargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { - // FIXME: Warn on inconsistent use of -mcpu and -march. - - // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef MCPU = A->getValue(); - // Handle -mcpu=native. - if (MCPU == "native") - return llvm::sys::getHostCPUName(); - else - return MCPU; - } - - return "generic"; -} - // FIXME: Move to target hook. static bool isSignedCharDefault(const llvm::Triple &Triple) { switch (Triple.getArch()) { @@ -573,7 +456,15 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { 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()) @@ -597,33 +488,6 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { } } -// Handle -mfpu=. -// -// FIXME: Centralize feature selection, defaulting shouldn't be also in the -// frontend target. -static void getAArch64FPUFeatures(const Driver &D, const Arg *A, - const ArgList &Args, - std::vector<const char *> &Features) { - StringRef FPU = A->getValue(); - if (FPU == "fp-armv8") { - Features.push_back("+fp-armv8"); - } else if (FPU == "neon-fp-armv8") { - Features.push_back("+fp-armv8"); - Features.push_back("+neon"); - } else if (FPU == "crypto-neon-fp-armv8") { - Features.push_back("+fp-armv8"); - Features.push_back("+neon"); - Features.push_back("+crypto"); - } else if (FPU == "neon") { - Features.push_back("+neon"); - } else if (FPU == "none") { - Features.push_back("-fp-armv8"); - Features.push_back("-crypto"); - Features.push_back("-neon"); - } else - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - // Handle -mhwdiv=. static void getARMHWDivFeatures(const Driver &D, const Arg *A, const ArgList &Args, @@ -660,16 +524,28 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, 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 == "vfp") { - Features.push_back("+vfp2"); - 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"); @@ -697,9 +573,8 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. -static StringRef getARMFloatABI(const Driver &D, - const ArgList &Args, - const llvm::Triple &Triple) { +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, @@ -728,7 +603,7 @@ static StringRef getARMFloatABI(const Driver &D, // // FIXME: Factor out an ARM class so we can cache the arch somewhere. std::string ArchName = - getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v6") || StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; @@ -737,6 +612,11 @@ static StringRef getARMFloatABI(const Driver &D, 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: @@ -757,13 +637,16 @@ static StringRef getARMFloatABI(const Driver &D, 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 = - getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); if (StringRef(ArchName).startswith("v7")) FloatABI = "softfp"; else @@ -773,7 +656,9 @@ static StringRef getARMFloatABI(const Driver &D, default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + if (Triple.getOS() != llvm::Triple::UnknownOS || + !Triple.isOSBinFormatMachO()) + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; break; } } @@ -784,18 +669,30 @@ static StringRef getARMFloatABI(const Driver &D, static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, - std::vector<const char *> &Features) { - StringRef FloatABI = getARMFloatABI(D, Args, Triple); - // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these - // yet (it uses the -mfloat-abi and -msoft-float options), and it is - // stripped out by the ARM target. - // Use software floating point operations? - if (FloatABI == "soft") - Features.push_back("+soft-float"); + 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 argument passing? - if (FloatABI != "hard") - Features.push_back("+soft-float-abi"); + // 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)) @@ -805,8 +702,11 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. - if (FloatABI == "soft") + 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, @@ -825,23 +725,28 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Get the effective triple, which takes into account the deployment target. std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); llvm::Triple Triple(TripleStr); - std::string CPUName = getARMTargetCPU(Args, Triple); + std::string CPUName = arm::getARMTargetCPU(Args, Triple); // Select the ABI to use. // // FIXME: Support -meabi. - const char *ABIName = 0; + const char *ABIName = nullptr; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); - } else if (Triple.isOSDarwin()) { + } 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()) { @@ -850,6 +755,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, case llvm::Triple::GNUEABIHF: ABIName = "aapcs-linux"; break; + case llvm::Triple::EABIHF: case llvm::Triple::EABI: ABIName = "aapcs"; break; @@ -861,7 +767,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back(ABIName); // Determine floating point ABI from the options & target defaults. - StringRef FloatABI = getARMFloatABI(D, Args, Triple); + StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple); if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // @@ -908,23 +814,97 @@ void Clang::AddARMTargetArgs(const ArgList &Args, 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"); - } + // 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. -static void getMipsCPUAndABI(const ArgList &Args, - const llvm::Triple &Triple, - StringRef &CPUName, - StringRef &ABIName) { - const char *DefMips32CPU = "mips32"; - const char *DefMips64CPU = "mips64"; +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)) @@ -956,22 +936,22 @@ static void getMipsCPUAndABI(const ArgList &Args, } } - if (!ABIName.empty()) { + 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("32", "o32", "eabi", DefMips32CPU) - .Cases("n32", "n64", "64", DefMips64CPU) + .Cases("o32", "eabi", DefMips32CPU) + .Cases("n32", "n64", DefMips64CPU) .Default(""); } - else if (!CPUName.empty()) { - // Deduce ABI name from CPU name. - ABIName = llvm::StringSwitch<const char *>(CPUName) - .Cases("mips32", "mips32r2", "o32") - .Cases("mips64", "mips64r2", "n64") - .Default(""); - } - - // FIXME: Warn on inconsistent cpu and abi usage. } // Convert ABI name to the GNU tools acceptable variant. @@ -1025,11 +1005,27 @@ static void AddTargetFeature(const ArgList &Args, } } -static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, +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); - bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; - if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { + 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. @@ -1037,8 +1033,14 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, } if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { - if (StringRef(A->getValue()) == "2008") + 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, @@ -1053,8 +1055,25 @@ static void getMIPSTargetFeatures(const Driver &D, const ArgList &Args, "dspr2"); AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, "msa"); - AddTargetFeature(Args, Features, options::OPT_mfp64, options::OPT_mfp32, - "fp64"); + + // 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, @@ -1063,25 +1082,18 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, StringRef CPUName; StringRef ABIName; const llvm::Triple &Triple = getToolChain().getTriple(); - getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); StringRef FloatABI = getMipsFloatABI(D, Args); - bool IsMips16 = Args.getLastArg(options::OPT_mips16) != NULL; - - if (FloatABI == "soft" || (FloatABI == "hard" && IsMips16)) { + 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"); - - if (FloatABI == "hard" && IsMips16) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-mips16-hard-float"); - } } else { // Floating point operations and argument passing are hard. @@ -1167,6 +1179,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("power6", "pwr6") .Case("power6x", "pwr6x") .Case("power7", "pwr7") + .Case("power8", "pwr8") .Case("pwr3", "pwr3") .Case("pwr4", "pwr4") .Case("pwr5", "pwr5") @@ -1174,6 +1187,7 @@ static std::string getPPCTargetCPU(const ArgList &Args) { .Case("pwr6", "pwr6") .Case("pwr6x", "pwr6x") .Case("pwr7", "pwr7") + .Case("pwr8", "pwr8") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Case("powerpc64le", "ppc64le") @@ -1247,7 +1261,7 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); - // Select the float ABI as determined by -msoft-float, -mhard-float, and + // 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)) { @@ -1305,7 +1319,7 @@ static const char *getX86TargetCPU(const ArgList &Args, if (Triple.getArch() != llvm::Triple::x86_64 && Triple.getArch() != llvm::Triple::x86) - return 0; // This routine is only handling x86 targets. + return nullptr; // This routine is only handling x86 targets. bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; @@ -1316,10 +1330,9 @@ static const char *getX86TargetCPU(const ArgList &Args, return Is64Bit ? "core2" : "yonah"; } - // All x86 devices running Android have core2 as their common - // denominator. This makes a better choice than pentium4. + // On Android use targets compatible with gcc if (Triple.getEnvironment() == llvm::Triple::Android) - return "core2"; + return Is64Bit ? "x86-64" : "i686"; // Everything else goes to x86-64 in 64-bit mode. if (Is64Bit) @@ -1346,11 +1359,16 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { return ""; case llvm::Triple::aarch64: - return getAArch64TargetCPU(Args, T); + 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: - return getARMTargetCPU(Args, T); + case llvm::Triple::thumbeb: + return arm::getARMTargetCPU(Args, T); case llvm::Triple::mips: case llvm::Triple::mipsel: @@ -1358,7 +1376,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, T, CPUName, ABIName); + mips::getMipsCPUAndABI(Args, T, CPUName, ABIName); return CPUName; } @@ -1401,7 +1419,26 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { } } -static void getX86TargetFeatures(const llvm::Triple &Triple, +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") { @@ -1415,6 +1452,40 @@ static void getX86TargetFeatures(const llvm::Triple &Triple, 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), @@ -1458,6 +1529,17 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } 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) { @@ -1505,15 +1587,146 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, 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) { - // Honor -mfpu=. - if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) - getAArch64FPUFeatures(D, A, Args, 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) { + const ArgList &Args, ArgStringList &CmdArgs, + bool ForAS) { std::vector<const char *> Features; switch (Triple.getArch()) { default: @@ -1522,12 +1735,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: - getMIPSTargetFeatures(D, Args, Features); + getMIPSTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::thumb: - getARMTargetFeatures(D, Triple, Args, Features); + case llvm::Triple::thumbeb: + getARMTargetFeatures(D, Triple, Args, Features, ForAS); break; case llvm::Triple::ppc: @@ -1539,11 +1754,14 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, 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(Triple, Args, Features); + getX86TargetFeatures(D, Triple, Args, Features); break; } @@ -1578,7 +1796,7 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, if (runtime.isNonFragile()) return true; - if (!Triple.isOSDarwin()) + if (!Triple.isMacOSX()) return false; return (!Triple.isMacOSXVersionLT(10,5) && @@ -1586,6 +1804,45 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, 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. @@ -1608,28 +1865,8 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, return; } - // Exceptions are enabled by default. - bool ExceptionsEnabled = true; - - // 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)) - ExceptionsEnabled = true; - else - ExceptionsEnabled = false; - - DidHaveExplicitExceptionFlag = true; - } - - bool ShouldUseExceptionTables = false; - - // Exception tables and cleanups can be enabled with -fexceptions even if the - // language itself doesn't support exceptions. - if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) - ShouldUseExceptionTables = true; + // 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. @@ -1639,12 +1876,12 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, true)) { CmdArgs.push_back("-fobjc-exceptions"); - ShouldUseExceptionTables |= + ES.ShouldUseExceptionTables |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); } if (types::isCXX(InputType)) { - bool CXXExceptionsEnabled = ExceptionsEnabled; + bool CXXExceptionsEnabled = ES.ExceptionsEnabled; if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, @@ -1659,11 +1896,11 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, if (CXXExceptionsEnabled) { CmdArgs.push_back("-fcxx-exceptions"); - ShouldUseExceptionTables = true; + ES.ShouldUseExceptionTables = true; } } - if (ShouldUseExceptionTables) + if (ES.ShouldUseExceptionTables) CmdArgs.push_back("-fexceptions"); } @@ -1679,19 +1916,6 @@ static bool ShouldDisableAutolink(const ArgList &Args, Default); } -static bool ShouldDisableCFI(const ArgList &Args, - const ToolChain &TC) { - bool Default = true; - if (TC.getTriple().isOSDarwin()) { - // The native darwin assembler doesn't support cfi directives, so - // we disable them if we think the .s file will be passed to it. - Default = TC.useIntegratedAs(); - } - return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, - options::OPT_fno_dwarf2_cfi_asm, - Default); -} - static bool ShouldDisableDwarfDirectory(const ArgList &Args, const ToolChain &TC) { bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm, @@ -1705,8 +1929,8 @@ static bool ContainsCompileAction(const Action *A) { if (isa<CompileJobAction>(A)) return true; - for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it) - if (ContainsCompileAction(*it)) + for (const auto &Act : *A) + if (ContainsCompileAction(Act)) return true; return false; @@ -1722,9 +1946,8 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { if (RelaxDefault) { RelaxDefault = false; - for (ActionList::const_iterator it = C.getActions().begin(), - ie = C.getActions().end(); it != ie; ++it) { - if (ContainsCompileAction(*it)) { + for (const auto &Act : C.getActions()) { + if (ContainsCompileAction(Act)) { RelaxDefault = true; break; } @@ -1751,6 +1974,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // 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) { @@ -1774,48 +1998,116 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, 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 void addProfileRTLinux( +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; - // The profile runtime is located in the Linux library directory and has name - // "libclang_rt.profile-<ArchName>.a". - SmallString<128> LibProfile(TC.getDriver().ResourceDir); - llvm::sys::path::append( - LibProfile, "lib", "linux", - Twine("libclang_rt.profile-") + TC.getArchName() + ".a"); + // -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 void addSanitizerRTLinkFlagsLinux( - const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, - const StringRef Sanitizer, bool BeforeLibStdCXX, - bool ExportSymbols = true) { - // Sanitizer runtime is located in the Linux library directory and - // has name "libclang_rt.<Sanitizer>-<ArchName>.a". - SmallString<128> LibSanitizer(TC.getDriver().ResourceDir); - llvm::sys::path::append( - LibSanitizer, "lib", "linux", - (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".a")); +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 @@ -1831,10 +2123,15 @@ static void addSanitizerRTLinkFlagsLinux( CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(), LibSanitizerArgs.begin(), LibSanitizerArgs.end()); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-lrt"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-lm"); + 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 @@ -1850,66 +2147,102 @@ static void addSanitizerRTLinkFlagsLinux( /// 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 addAsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (TC.getTriple().getEnvironment() == llvm::Triple::Android) { - SmallString<128> LibAsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibAsan, "lib", "linux", - (Twine("libclang_rt.asan-") + - TC.getArchName() + "-android.so")); - CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan)); +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 { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); + 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 addTsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addTsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true); + 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 addMsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addMsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true); + 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 addLsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addLsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "lsan", true); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true); } /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags /// (Linux). -static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, bool IsCXX, - bool HasOtherSanitizerRt) { +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) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true, false); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false); - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", 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) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false); + addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true); } -static void addDfsanRTLinux(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { +static void addDfsanRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "dfsan", true); + 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, @@ -1971,7 +2304,8 @@ static const char *SplitDebugName(const ArgList &Args, return Args.MakeArgString(T); } else { // Use the compilation dir. - SmallString<128> T(Args.getLastArgValue(options::OPT_fdebug_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; @@ -2005,7 +2339,8 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, } /// \brief Vectorize at all optimization levels greater than 1 except for -Oz. -static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { +/// 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)) @@ -2021,9 +2356,9 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { if (S == "s") return true; - // Don't vectorize -Oz. + // Don't vectorize -Oz, unless it's the slp vectorizer. if (S == "z") - return false; + return isSlpVec; unsigned OptLevel = 0; if (S.getAsInteger(10, OptLevel)) @@ -2035,6 +2370,41 @@ static bool shouldEnableVectorizerAtOLevel(const ArgList &Args) { 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, @@ -2045,6 +2415,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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. @@ -2057,6 +2432,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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; @@ -2091,6 +2482,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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."); @@ -2120,8 +2513,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // The make clang go fast button. - CmdArgs.push_back("-disable-free"); + // 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 @@ -2151,7 +2547,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); - if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) + if (!IsWindowsMSVC) CmdArgs.push_back("-analyzer-checker=unix"); if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) @@ -2162,8 +2558,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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"); + // 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"); @@ -2194,6 +2591,54 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 @@ -2234,8 +2679,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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))) + 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; @@ -2281,6 +2727,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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()); @@ -2313,8 +2766,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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, true)) + 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)) @@ -2461,18 +2917,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 (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 IsVerboseAsmDefault = getToolChain().IsIntegratedAssemblerDefault(); + bool IsIntegratedAssemblerDefault = + getToolChain().IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, - IsVerboseAsmDefault) || + 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"); @@ -2500,10 +2962,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -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() && - !KernelOrKext); + 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"); @@ -2538,7 +3001,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Add the target features - getTargetFeatures(D, ETriple, Args, CmdArgs); + getTargetFeatures(D, ETriple, Args, CmdArgs, false); // Add target specific flags. switch(getToolChain().getArch()) { @@ -2546,10 +3009,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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: @@ -2558,6 +3030,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::sparc: + case llvm::Triple::sparcv9: AddSparcTargetArgs(Args, CmdArgs); break; @@ -2615,13 +3088,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.CCLogDiagnosticsFilename : "-"); } - // Use the last option from "-g" group. "-gline-tables-only" - // is preserved, all other debug options are substituted with "-g". + // 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)) + 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"); - else if (A->getOption().matches(options::OPT_gdwarf_2)) + // 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"); @@ -2629,9 +3109,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 and FreeBSD. + // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD. const llvm::Triple &Triple = getToolChain().getTriple(); - if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::FreeBSD) + if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD || + Triple.getOS() == llvm::Triple::FreeBSD) CmdArgs.push_back("-gdwarf-2"); else CmdArgs.push_back("-g"); @@ -2640,7 +3121,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now. Args.ClaimAllArgs(options::OPT_g_flags_Group); - if (Args.hasArg(options::OPT_gcolumn_info)) + 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. @@ -2660,13 +3142,44 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-generate-gnu-dwarf-pub-sections"); } - Args.AddAllArgs(CmdArgs, options::OPT_fdebug_types_section); + // -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"); + } - Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); - Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); + 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"); @@ -2772,7 +3285,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly); - Args.AddLastArg(CmdArgs, options::OPT_objcmt_white_list_dir_path); + 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 @@ -2798,10 +3312,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + // 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"); @@ -2836,7 +3358,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!types::isCXX(InputType)) Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=", /*Joined=*/true); - else if (getToolChain().getTriple().getOS() == llvm::Triple::Win32) + else if (IsWindowsMSVC) CmdArgs.push_back("-std=c++11"); Args.AddLastArg(CmdArgs, options::OPT_trigraphs); @@ -2852,9 +3374,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // behavior for now. FIXME: Directly diagnose uses of a string literal as // a non-const char* in C, rather than using this crude hack. if (!types::isCXX(InputType)) { - DiagnosticsEngine::Level DiagLevel = D.getDiags().getDiagnosticLevel( - diag::warn_deprecated_string_literal_conversion_c, SourceLocation()); - if (DiagLevel > DiagnosticsEngine::Ignored) + // 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"); } @@ -2875,9 +3401,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } - if (ShouldDisableCFI(Args, getToolChain())) - CmdArgs.push_back("-fno-dwarf2-cfi-asm"); - if (ShouldDisableDwarfDirectory(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf-directory-asm"); @@ -3014,8 +3537,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, true)) CmdArgs.push_back("-fno-sanitize-recover"); - if (Args.hasArg(options::OPT_fcatch_undefined_behavior) || - Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, + 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"); @@ -3038,10 +3560,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.getLastArg(options::OPT_fapple_kext)) CmdArgs.push_back("-fapple-kext"); - if (Args.hasFlag(options::OPT_frewrite_includes, - options::OPT_fno_rewrite_includes, false)) - CmdArgs.push_back("-frewrite-includes"); - 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); @@ -3083,11 +3601,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 = 1; + 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 = 2; + StackProtectorLevel = LangOptions::SSPReq; } else { StackProtectorLevel = getToolChain().GetDefaultStackProtectorLevel(KernelOrKext); @@ -3132,10 +3654,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_munaligned_access)) { if (A->getOption().matches(options::OPT_mno_unaligned_access)) { CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-strict-align"); + 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"); - CmdArgs.push_back("-arm-no-strict-align"); + 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"); } } } @@ -3149,6 +3683,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 @@ -3218,44 +3768,78 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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->claim(); + 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->claim(); + if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) A->render(Args, CmdArgs); - } - // If a module path was provided, pass it along. Otherwise, use a temporary - // directory. - if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) { - A->claim(); - if (HaveModules) { - 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"); } - } else if (HaveModules) { - SmallString<128> DefaultModuleCache; - llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, - DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); - llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); const char Arg[] = "-fmodules-cache-path="; - DefaultModuleCache.insert(DefaultModuleCache.begin(), - Arg, Arg + strlen(Arg)); - CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); + 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, @@ -3302,41 +3886,52 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-threadsafe-statics"); // -fuse-cxa-atexit is default. - if (!Args.hasFlag( - options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, - getToolChain().getTriple().getOS() != llvm::Triple::Cygwin && - getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 && - getToolChain().getArch() != llvm::Triple::hexagon && - getToolChain().getArch() != llvm::Triple::xcore) || + 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, - getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + IsWindowsMSVC)) CmdArgs.push_back("-fms-extensions"); // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, - (getToolChain().getTriple().getOS() == llvm::Triple::Win32 && - Args.hasFlag(options::OPT_fms_extensions, - options::OPT_fno_ms_extensions, - true)))) + (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, + true)))) CmdArgs.push_back("-fms-compatibility"); - // -fmsc-version=1700 is default. + // -fms-compatibility-version=17.00 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - getToolChain().getTriple().getOS() == llvm::Triple::Win32) || - Args.hasArg(options::OPT_fmsc_version)) { - StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); - if (msc_ver.empty()) - CmdArgs.push_back("-fmsc-version=1700"); + 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("-fmsc-version=" + msc_ver)); + 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)) @@ -3345,8 +3940,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -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, - getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + options::OPT_fno_delayed_template_parsing, IsWindowsMSVC)) CmdArgs.push_back("-fdelayed-template-parsing"); // -fgnu-keywords default varies depending on language; only pass if @@ -3369,9 +3963,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and - // legacy is the default. Next runtime is always legacy dispatch and - // -fno-objc-legacy-dispatch gets ignored silently. - if (objcRuntime.isNonFragile() && !objcRuntime.isNeXTFamily()) { + // 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( @@ -3447,9 +4042,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // Add exception args. - addExceptionArgs(Args, InputType, getToolChain().getTriple(), - KernelOrKext, objcRuntime, CmdArgs); + // 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"); @@ -3469,7 +4065,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fshort-wchar default varies depending on platform; only // pass if specified. - if (Arg *A = Args.getLastArg(options::OPT_fshort_wchar)) + 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. @@ -3512,6 +4109,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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)) @@ -3554,9 +4159,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Support both clang's -f[no-]color-diagnostics and gcc's // -f[no-]diagnostics-colors[=never|always|auto]. enum { Colors_On, Colors_Off, Colors_Auto } ShowColors = Colors_Auto; - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it) { - const Option &O = (*it)->getOption(); + 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) && @@ -3564,7 +4168,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !O.matches(options::OPT_fdiagnostics_color_EQ)) continue; - (*it)->claim(); + Arg->claim(); if (O.matches(options::OPT_fcolor_diagnostics) || O.matches(options::OPT_fdiagnostics_color)) { ShowColors = Colors_On; @@ -3573,7 +4177,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ShowColors = Colors_Off; } else { assert(O.matches(options::OPT_fdiagnostics_color_EQ)); - StringRef value((*it)->getValue()); + StringRef value(Arg->getValue()); if (value == "always") ShowColors = Colors_On; else if (value == "never") @@ -3614,16 +4218,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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); + 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 default. - if (Args.hasFlag(options::OPT_fslp_vectorize, - options::OPT_fno_slp_vectorize, true)) + // -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. @@ -3677,6 +4284,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } #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)) { @@ -3727,14 +4343,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, assert(Output.isNothing() && "Invalid output."); } - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - 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(II.getType())); + for (const auto &II : Inputs) { + addDashXForInput(Args, II, CmdArgs); + if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else @@ -3749,9 +4360,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) - (*it)->render(Args, OriginalArgs); + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); SmallString<256> Flags; Flags += Exec; @@ -3776,10 +4386,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Finally add the compile command to the compilation. - if (Args.hasArg(options::OPT__SLASH_fallback)) { - tools::visualstudio::Compile CL(getToolChain()); - Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args, - LinkingOutput); + 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)); @@ -3938,6 +4549,45 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, 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; @@ -3983,11 +4633,58 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // implemented in clang. CmdArgs.push_back("--dependent-lib=oldnames"); - // FIXME: Make this default for the win32 triple. - CmdArgs.push_back("-cxx-abi"); - CmdArgs.push_back("microsoft"); + // 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_show_includes)) + if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ)) A->render(Args, CmdArgs); if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) { @@ -3999,6 +4696,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { } } +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, @@ -4045,7 +4748,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Add the target features const Driver &D = getToolChain().getDriver(); - getTargetFeatures(D, Triple, Args, CmdArgs); + getTargetFeatures(D, Triple, Args, CmdArgs, true); // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); @@ -4066,6 +4769,13 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, 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); @@ -4079,9 +4789,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // analysis. if (getToolChain().UseDwarfDebugFlags()) { ArgStringList OriginalArgs; - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) - (*it)->render(Args, OriginalArgs); + for (const auto &Arg : Args) + Arg->render(Args, OriginalArgs); SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); @@ -4096,6 +4805,16 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // 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()); @@ -4128,9 +4847,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; - for (ArgList::const_iterator - it = Args.begin(), ie = Args.end(); it != ie; ++it) { - Arg *A = *it; + for (const auto &A : Args) { if (forwardToGCC(A->getOption())) { // Don't forward any -g arguments to assembly steps. if (isa<AssembleJobAction>(JA) && @@ -4199,10 +4916,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + 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) @@ -4255,11 +4969,6 @@ void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA, CmdArgs.push_back("-E"); } -void gcc::Precompile::RenderExtraToolArgs(const JobAction &JA, - ArgStringList &CmdArgs) const { - // The type is good enough. -} - void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -4277,11 +4986,6 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, } } -void gcc::Assemble::RenderExtraToolArgs(const JobAction &JA, - ArgStringList &CmdArgs) const { - CmdArgs.push_back("-c"); -} - void gcc::Link::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { // The types are (hopefully) good enough. @@ -4331,10 +5035,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; - + 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) @@ -4355,11 +5056,10 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } const char *GCCName = "hexagon-as"; - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + 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. @@ -4401,10 +5101,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- - for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), - e = ToolChain.ExtraOpts.end(); - i != e; ++i) - CmdArgs.push_back(i->c_str()); + 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)); @@ -4480,12 +5178,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, // Library Search Paths //---------------------------------------------------------------------------- const ToolChain::path_list &LibPaths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator - i = LibPaths.begin(), - e = LibPaths.end(); - i != e; - ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + for (const auto &LibPath : LibPaths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); //---------------------------------------------------------------------------- // @@ -4533,7 +5227,116 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Hexagon tools end. -llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { +/// 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. @@ -4556,8 +5359,9 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .Cases("x86_64", "x86_64h", llvm::Triple::x86_64) // This is derived from the driver driver. .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) - .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm) + .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) @@ -4566,6 +5370,18 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .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( @@ -4613,14 +5429,14 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, SourceAction = SourceAction->getInputs()[0]; } - // If -no_integrated_as is used add -Q to the darwin assember driver to make + // 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_no_integrated_as)) { - const llvm::Triple& t(getToolChain().getTriple()); - if (!(t.isMacOSX() && t.isMacOSXVersionLT(10, 7))) + 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"); } @@ -4634,7 +5450,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } // Derived from asm spec. - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); // Use -force_cpusubtype_ALL on x86 by default. if (getToolChain().getArch() == llvm::Triple::x86 || @@ -4645,8 +5461,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() != llvm::Triple::x86_64 && (((Args.hasArg(options::OPT_mkernel) || Args.hasArg(options::OPT_fapple_kext)) && - (!getDarwinToolChain().isTargetIPhoneOS() || - getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) || + getMachOToolChain().isKernelStatic()) || Args.hasArg(options::OPT_static))) CmdArgs.push_back("-static"); @@ -4667,11 +5482,11 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } -void darwin::DarwinTool::anchor() {} +void darwin::MachOTool::anchor() {} -void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, - ArgStringList &CmdArgs) const { - StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); +void darwin::MachOTool::AddMachOArch(const ArgList &Args, + ArgStringList &CmdArgs) const { + StringRef ArchName = getMachOToolChain().getMachOArchName(Args); // Derived from darwin_arch spec. CmdArgs.push_back("-arch"); @@ -4686,9 +5501,8 @@ 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 (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) - if (it->getType() != types::TY_Object) + for (const auto &Input : Inputs) + if (Input.getType() != types::TY_Object) return true; return false; @@ -4699,7 +5513,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, ArgStringList &CmdArgs, const InputInfoList &Inputs) const { const Driver &D = getToolChain().getDriver(); - const toolchains::Darwin &DarwinTC = getDarwinToolChain(); + const toolchains::MachO &MachOTC = getMachOToolChain(); unsigned Version[3] = { 0, 0, 0 }; if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { @@ -4711,27 +5525,10 @@ void darwin::Link::AddLinkArgs(Compilation &C, << A->getAsString(Args); } - // Newer linkers support -demangle, pass it if supported and not disabled by + // 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)) { - // Don't pass -demangle to ld_classic. - // - // FIXME: This is a temporary workaround, ld should be handling this. - bool UsesLdClassic = (getToolChain().getArch() == llvm::Triple::x86 && - Args.hasArg(options::OPT_static)); - if (getToolChain().getArch() == llvm::Triple::x86) { - for (arg_iterator it = Args.filtered_begin(options::OPT_Xlinker, - options::OPT_Wl_COMMA), - ie = Args.filtered_end(); it != ie; ++it) { - const Arg *A = *it; - for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - if (StringRef(A->getValue(i)) == "-kext") - UsesLdClassic = true; - } - } - if (!UsesLdClassic) - CmdArgs.push_back("-demangle"); - } + 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"); @@ -4757,7 +5554,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, } if (!Args.hasArg(options::OPT_dynamiclib)) { - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); // FIXME: Why do this only on this path? Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL); @@ -4793,7 +5590,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version, "-dylib_current_version"); - AddDarwinArch(Args, CmdArgs); + AddMachOArch(Args, CmdArgs); Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name, "-dylib_install_name"); @@ -4802,7 +5599,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_all__load); Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); - if (DarwinTC.isTargetIPhoneOS()) + 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); @@ -4816,22 +5613,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_init); // Add the deployment target. - VersionTuple TargetVersion = DarwinTC.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 (DarwinTC.isTargetIPhoneOS()) - CmdArgs.push_back("-iphoneos_version_min"); - else - CmdArgs.push_back("-macosx_version_min"); - CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); + MachOTC.addMinVersionArgs(Args, CmdArgs); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); @@ -4900,6 +5682,12 @@ void darwin::Link::AddLinkArgs(Compilation &C, 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, @@ -4915,8 +5703,8 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, /// 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 (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) - (*I)->claim(); + for (const auto &Arg : Args) + Arg->claim(); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); @@ -4946,120 +5734,42 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) { - // Derived from startfile spec. - if (Args.hasArg(options::OPT_dynamiclib)) { - // Derived from darwin_dylib1 spec. - if (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-ldylib1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-ldylib1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-ldylib1.o"); - else if (getDarwinToolChain().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 (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-lbundle1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-lbundle1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lbundle1.o"); - } - } - } else { - if (Args.hasArg(options::OPT_pg) && - getToolChain().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 (getDarwinToolChain().isTargetMacOS() && - !getDarwinToolChain().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 (getDarwinToolChain().isTargetIOSSimulator()) { - // The simulator doesn't have a versioned crt1 file. - CmdArgs.push_back("-lcrt1.o"); - } else if (getDarwinToolChain().isTargetIPhoneOS()) { - if (getDarwinToolChain().isIPhoneOSVersionLT(3, 1)) - CmdArgs.push_back("-lcrt1.o"); - else if (getDarwinToolChain().isIPhoneOSVersionLT(6, 0)) - CmdArgs.push_back("-lcrt1.3.1.o"); - } else { - if (getDarwinToolChain().isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lcrt1.o"); - else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lcrt1.10.5.o"); - else if (getDarwinToolChain().isMacosxVersionLT(10, 8)) - CmdArgs.push_back("-lcrt1.10.6.o"); - - // darwin_crt2 spec is empty. - } - } - } - } - } - - if (!getDarwinToolChain().isTargetIPhoneOS() && - Args.hasArg(options::OPT_shared_libgcc) && - getDarwinToolChain().isMacosxVersionLT(10, 5)) { - const char *Str = - Args.MakeArgString(getToolChain().GetFilePath("crt3.o")); - CmdArgs.push_back(Str); - } - } + !Args.hasArg(options::OPT_nostartfiles)) + getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_L); - if (Args.hasArg(options::OPT_fopenmp)) - // This is more complicated in gcc... + 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)) { - // Avoid linking compatibility stubs on i386 mac. - if (!getDarwinToolChain().isTargetMacOS() || - getDarwinToolChain().getArch() != llvm::Triple::x86) { - // If we don't have ARC or subscripting runtime support, link in the - // runtime stubs. We have to do this *before* adding any of the normal - // linker inputs so that its initializer gets run first. - ObjCRuntime runtime = - getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true); - // We use arclite library for both ARC and subscripting support. - if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) || - !runtime.hasSubscripting()) - getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); - } + // We use arclite library for both ARC and subscripting support. + getMachOToolChain().AddLinkARCArgs(Args, CmdArgs); + CmdArgs.push_back("-framework"); CmdArgs.push_back("Foundation"); // Link libobj. @@ -5083,7 +5793,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // link_ssp spec is empty. // Let the tool chain choose which runtime library to link. - getDarwinToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs); + getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs); } if (!Args.hasArg(options::OPT_nostdlib) && @@ -5095,7 +5805,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_F); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5112,14 +5822,12 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-output"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) { assert(II.isFilename() && "Unexpected lipo input."); CmdArgs.push_back(II.getFilename()); } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("lipo")); + + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5179,18 +5887,13 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + 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, @@ -5289,10 +5992,10 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o")); - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5309,14 +6012,10 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("gas")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5401,10 +6100,10 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().GetFilePath("crtend.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5414,19 +6113,36 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; + bool NeedsKPIC = false; - // When building 32-bit code on OpenBSD/amd64, we have to explicitly - // instruct as in the base system to assemble 32-bit code. - if (getToolChain().getArch() == llvm::Triple::x86) + 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"); - else if (getToolChain().getArch() == llvm::Triple::ppc) { + break; + + case llvm::Triple::ppc: CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); - } else if (getToolChain().getArch() == llvm::Triple::mips64 || - getToolChain().getArch() == llvm::Triple::mips64el) { + 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; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-mabi"); CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); @@ -5436,30 +6152,25 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-EL"); - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg && - (LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic) || - LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie))) { - CmdArgs.push_back("-KPIC"); - } + 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 (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); @@ -5594,7 +6305,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5611,14 +6322,10 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5734,7 +6441,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5757,7 +6464,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); @@ -5771,22 +6478,14 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-EL"); - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg && - (LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic) || - LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie))) { - CmdArgs.push_back("-KPIC"); - } + addAssemblerKPIC(Args, CmdArgs); } else if (getToolChain().getArch() == llvm::Triple::arm || - getToolChain().getArch() == llvm::Triple::thumb) { + getToolChain().getArch() == llvm::Triple::armeb || + getToolChain().getArch() == llvm::Triple::thumb || + getToolChain().getArch() == llvm::Triple::thumbeb) { const Driver &D = getToolChain().getDriver(); - llvm::Triple Triple = getToolChain().getTriple(); - StringRef FloatABI = getARMFloatABI(D, Args, Triple); + const llvm::Triple &Triple = getToolChain().getTriple(); + StringRef FloatABI = arm::getARMFloatABI(D, Args, Triple); if (FloatABI == "hard") { CmdArgs.push_back("-mfpu=vfp"); @@ -5811,17 +6510,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-Av9a"); - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg && - (LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic) || - LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie))) { - CmdArgs.push_back("-KPIC"); - } + addAssemblerKPIC(Args, CmdArgs); } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -5830,14 +6519,10 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5849,6 +6534,9 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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" @@ -5862,7 +6550,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); - if (Args.hasArg(options::OPT_pie)) + if (IsPIE) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_static)) { @@ -5908,11 +6596,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - const char *crt1 = NULL; + const char *crt1 = nullptr; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; - else if (Args.hasArg(options::OPT_pie)) + else if (IsPIE) crt1 = "Scrt1.o"; else crt1 = "crt1.o"; @@ -5922,10 +6610,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); - const char *crtbegin = NULL; + const char *crtbegin = nullptr; if (Args.hasArg(options::OPT_static)) crtbegin = "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + else if (Args.hasArg(options::OPT_shared) || IsPIE) crtbegin = "crtbeginS.o"; else crtbegin = "crtbegin.o"; @@ -5935,9 +6623,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); const ToolChain::path_list Paths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); - i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + 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); @@ -5945,25 +6632,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); - // Tell the linker to load the plugin. This has to come before AddLinkerInputs - // as gold requires -plugin to come before any -plugin-opt that -Wl might - // forward. - if (D.IsUsingLTO(Args)) { - CmdArgs.push_back("-plugin"); - std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; - CmdArgs.push_back(Args.MakeArgString(Plugin)); - - // Try to pass driver level flags relevant to LTO code generation down to - // the plugin. - - // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(Args, ToolChain.getTriple()); - if (!CPU.empty()) { - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=mcpu=") + - CPU)); - } - } + if (D.IsUsingLTO(Args)) + AddGoldPlugin(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); @@ -6023,17 +6693,19 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) + 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"))); } - addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple()); + addSanitizerRuntimes(getToolChain(), Args, CmdArgs); + + addProfileRT(ToolChain, Args, CmdArgs); const char *Exec = - Args.MakeArgString(ToolChain.GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6044,25 +6716,28 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; - // When building 32-bit code on NetBSD/amd64, we have to explicitly - // instruct as in the base system to assemble 32-bit code. - if (getToolChain().getArch() == llvm::Triple::x86) + // 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"); - - // Pass the target CPU to GNU as for ARM, since the source code might - // not have the correct .cpu annotation. - if (getToolChain().getArch() == llvm::Triple::arm) { - std::string MArch(getARMTargetCPU(Args, getToolChain().getTriple())); + 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; } - if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mipsel || - getToolChain().getArch() == llvm::Triple::mips64 || - getToolChain().getArch() == llvm::Triple::mips64el) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); + mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); @@ -6076,17 +6751,23 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-EL"); - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg && - (LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic) || - LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie))) { - CmdArgs.push_back("-KPIC"); - } + 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, @@ -6095,11 +6776,8 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + 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)); @@ -6116,12 +6794,12 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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"); - CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { @@ -6130,11 +6808,61 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } } - // When building 32-bit code on NetBSD/amd64, we have to explicitly - // instruct ld in the base system to link 32-bit code. - if (getToolChain().getArch() == llvm::Triple::x86) { + // 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()) { @@ -6174,10 +6902,19 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, unsigned Major, Minor, Micro; getToolChain().getTriple().getOSVersion(Major, Minor, Micro); bool useLibgcc = true; - if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) { - if (getToolChain().getArch() == llvm::Triple::x86 || - getToolChain().getArch() == llvm::Triple::x86_64) + 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) && @@ -6219,9 +6956,9 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, "crtn.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6238,7 +6975,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("--32"); } else if (getToolChain().getArch() == llvm::Triple::x86_64) { - CmdArgs.push_back("--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"); @@ -6249,8 +6989,9 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::ppc64le) { CmdArgs.push_back("-a64"); - CmdArgs.push_back("-mppc64le"); + 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"); @@ -6259,19 +7000,30 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-64"); CmdArgs.push_back("-Av9a"); NeedsKPIC = true; - } else if (getToolChain().getArch() == llvm::Triple::arm) { + } 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") + 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 = getARMFloatABI(getToolChain().getDriver(), Args, - getToolChain().getTriple()); + 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); - Args.AddLastArg(CmdArgs, options::OPT_mcpu_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 || @@ -6279,13 +7031,34 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getArch() == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; - getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, 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(getGnuCompatibleMipsABIName(ABIName).data()); + 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) @@ -6298,14 +7071,28 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-mnan=2008")); } - if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfp64)) { - if (A->getOption().matches(options::OPT_mfp32)) - CmdArgs.push_back(Args.MakeArgString("-mfp32")); - else - CmdArgs.push_back(Args.MakeArgString("-mfp64")); + // 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_mips16, options::OPT_mno_mips16); Args.AddLastArg(CmdArgs, options::OPT_mmicromips, options::OPT_mno_micromips); Args.AddLastArg(CmdArgs, options::OPT_mdsp, options::OPT_mno_dsp); @@ -6318,6 +7105,12 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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 @@ -6326,19 +7119,8 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); } - if (NeedsKPIC) { - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg && - (LastPICArg->getOption().matches(options::OPT_fPIC) || - LastPICArg->getOption().matches(options::OPT_fpic) || - LastPICArg->getOption().matches(options::OPT_fPIE) || - LastPICArg->getOption().matches(options::OPT_fpie))) { - CmdArgs.push_back("-KPIC"); - } - } + if (NeedsKPIC) + addAssemblerKPIC(Args, CmdArgs); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -6346,14 +7128,10 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + 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 @@ -6365,7 +7143,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, SplitDebugName(Args, Inputs)); } -static void AddLibgcc(llvm::Triple Triple, const Driver &D, +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) || @@ -6398,47 +7176,77 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D, CmdArgs.push_back("-ldl"); } -static bool hasMipsN32ABIArg(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef("n32")); -} - static StringRef getLinuxDynamicLinker(const ArgList &Args, const toolchains::Linux &ToolChain) { - if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) - return "/system/bin/linker"; - else if (ToolChain.getArch() == llvm::Triple::x86 || - ToolChain.getArch() == llvm::Triple::sparc) + 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) + 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) + 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 (hasMipsN32ABIArg(Args)) - return "/lib32/ld.so.1"; - else - return "/lib64/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::ppc64le || 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, @@ -6449,10 +7257,14 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = ToolChain.getDriver(); const bool isAndroid = ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; - const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && - (Args.hasArg(options::OPT_pie) || Sanitize.hasZeroBaseShadow()); + !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; @@ -6476,10 +7288,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); - for (std::vector<std::string>::const_iterator i = ToolChain.ExtraOpts.begin(), - e = ToolChain.ExtraOpts.end(); - i != e; ++i) - CmdArgs.push_back(i->c_str()); + for (const auto &Opt : ToolChain.ExtraOpts) + CmdArgs.push_back(Opt.c_str()); if (!Args.hasArg(options::OPT_static)) { CmdArgs.push_back("--eh-frame-hdr"); @@ -6488,15 +7298,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-m"); if (ToolChain.getArch() == llvm::Triple::x86) CmdArgs.push_back("elf_i386"); - else if (ToolChain.getArch() == llvm::Triple::aarch64) + 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) @@ -6506,37 +7325,41 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); else if (ToolChain.getArch() == llvm::Triple::mips64) { - if (hasMipsN32ABIArg(Args)) + if (mips::hasMipsAbiArg(Args, "n32")) CmdArgs.push_back("elf32btsmipn32"); else CmdArgs.push_back("elf64btsmip"); } else if (ToolChain.getArch() == llvm::Triple::mips64el) { - if (hasMipsN32ABIArg(Args)) + 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::thumb) + 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 (isAndroid) { - CmdArgs.push_back("-Bsymbolic"); - } } 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"); @@ -6550,7 +7373,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!isAndroid) { - const char *crt1 = NULL; + const char *crt1 = nullptr; if (!Args.hasArg(options::OPT_shared)){ if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; @@ -6581,57 +7404,24 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); const ToolChain::path_list Paths = ToolChain.getFilePaths(); - for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); - i != e; ++i) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); - - // Tell the linker to load the plugin. This has to come before AddLinkerInputs - // as gold requires -plugin to come before any -plugin-opt that -Wl might - // forward. - if (D.IsUsingLTO(Args)) { - CmdArgs.push_back("-plugin"); - std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; - CmdArgs.push_back(Args.MakeArgString(Plugin)); - - // Try to pass driver level flags relevant to LTO code generation down to - // the plugin. - - // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(Args, ToolChain.getTriple()); - if (!CPU.empty()) { - CmdArgs.push_back( - Args.MakeArgString(Twine("-plugin-opt=mcpu=") + - CPU)); - } - } + 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); - // Call these before we add the C++ ABI library. - if (Sanitize.needsUbsanRt()) - addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX(), - Sanitize.needsAsanRt() || Sanitize.needsTsanRt() || - Sanitize.needsMsanRt() || Sanitize.needsLsanRt()); - if (Sanitize.needsAsanRt()) - addAsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsTsanRt()) - addTsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsMsanRt()) - addMsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsLsanRt()) - addLsanRTLinux(getToolChain(), Args, CmdArgs); - if (Sanitize.needsDfsanRt()) - addDfsanRTLinux(getToolChain(), Args, CmdArgs); - + addSanitizerRuntimes(getToolChain(), Args, CmdArgs); // The profile runtime also needs access to system libraries. - addProfileRTLinux(getToolChain(), Args, CmdArgs); + addProfileRT(getToolChain(), Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && @@ -6651,19 +7441,37 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); - bool OpenMP = Args.hasArg(options::OPT_fopenmp); - if (OpenMP) { + 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 whith libgomp that doesn't require - // librt. Most modern Linux platfroms require it, but some may not. + // 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); - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); - - if (Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads) || OpenMP) + if ((Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) && + !isAndroid) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); @@ -6671,7 +7479,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); else - AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); } if (!Args.hasArg(options::OPT_nostartfiles)) { @@ -6699,20 +7507,15 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6745,7 +7548,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -6766,7 +7569,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6786,20 +7589,15 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("as")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6947,13 +7745,21 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().GetFilePath("crtn.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + addProfileRT(getToolChain(), Args, CmdArgs); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + 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, @@ -6976,6 +7782,10 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, 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) { @@ -6990,28 +7800,25 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); - SmallString<128> LibSanitizer(getToolChain().getDriver().ResourceDir); - llvm::sys::path::append(LibSanitizer, "lib", "windows"); + // FIXME: Handle 64-bit. if (DLL) { - llvm::sys::path::append(LibSanitizer, "clang_rt.asan_dll_thunk-i386.lib"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, + "asan_dll_thunk-i386"); } else { - llvm::sys::path::append(LibSanitizer, "clang_rt.asan-i386.lib"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386"); + addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386"); } - // FIXME: Handle 64-bit. - CmdArgs.push_back(Args.MakeArgString(LibSanitizer)); } Args.AddAllArgValues(CmdArgs, options::OPT_l); Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); // Add filenames immediately. - for (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - if (it->isFilename()) - CmdArgs.push_back(it->getFilename()); + for (const auto &Input : Inputs) + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); else - it->getInputArg().renderAsInput(Args, CmdArgs); - } + Input.getInputArg().renderAsInput(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); @@ -7036,14 +7843,9 @@ static std::string FindFallback(const char *FallbackName, if (!OptPath.hasValue()) return FallbackName; -#ifdef LLVM_ON_WIN32 - const StringRef PathSeparators = ";"; -#else - const StringRef PathSeparators = ":"; -#endif - + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; SmallVector<StringRef, 8> PathSegments; - llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators); + llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); for (size_t i = 0, e = PathSegments.size(); i != e; ++i) { const StringRef &PathSegment = PathSegments[i]; @@ -7093,19 +7895,31 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, // Flags for which clang-cl have an alias. // FIXME: How can we ensure this stays in sync with relevant clang-cl options? - if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti)) - CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR" - : "/GR-"); + if (Args.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 (size_t I = 0, E = Includes.size(); I != E; ++I) - CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Includes[I])); + 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, @@ -7131,7 +7945,6 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, const Driver &D = getToolChain().getDriver(); std::string Exec = FindFallback("cl.exe", D.getClangProgramPath()); - return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); } @@ -7151,21 +7964,24 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-c"); - if (Args.hasArg(options::OPT_g_Group)) { - CmdArgs.push_back("-g"); - } + 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 (InputInfoList::const_iterator - it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { - const InputInfo &II = *it; + for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("xcc")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -7183,9 +7999,15 @@ void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA, 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")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index d5b2848..4c89676 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -25,10 +25,15 @@ namespace driver { class Driver; namespace toolchains { - class Darwin; + class MachO; } namespace tools { + +namespace visualstudio { + class Compile; +} + using llvm::opt::ArgStringList; /// \brief Clang compiler tool. @@ -54,6 +59,8 @@ using llvm::opt::ArgStringList; 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, @@ -76,18 +83,21 @@ using llvm::opt::ArgStringList; 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) {} - virtual bool hasGoodDiagnostics() const { return true; } - virtual bool hasIntegratedAssembler() const { return true; } - virtual bool hasIntegratedCPP() const { return true; } + bool hasGoodDiagnostics() const override { return true; } + bool hasIntegratedAssembler() const override { return true; } + bool hasIntegratedCPP() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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. @@ -96,15 +106,14 @@ using llvm::opt::ArgStringList; ClangAs(const ToolChain &TC) : Tool("clang::as", "clang integrated assembler", TC) {} - virtual bool hasGoodDiagnostics() const { return true; } - virtual bool hasIntegratedAssembler() const { return false; } - virtual bool hasIntegratedCPP() const { return false; } + bool hasGoodDiagnostics() const override { return true; } + bool hasIntegratedAssembler() const override { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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. @@ -114,11 +123,11 @@ namespace gcc { Common(const char *Name, const char *ShortName, const ToolChain &TC) : Tool(Name, ShortName, TC) {} - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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. @@ -132,23 +141,11 @@ namespace gcc { Preprocess(const ToolChain &TC) : Common("gcc::Preprocess", "gcc preprocessor", TC) {} - virtual bool hasGoodDiagnostics() const { return true; } - virtual bool hasIntegratedCPP() const { return false; } + bool hasGoodDiagnostics() const override { return true; } + bool hasIntegratedCPP() const override { return false; } - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; - }; - - class LLVM_LIBRARY_VISIBILITY Precompile : public Common { - public: - Precompile(const ToolChain &TC) : Common("gcc::Precompile", - "gcc precompile", TC) {} - - virtual bool hasGoodDiagnostics() const { return true; } - virtual bool hasIntegratedCPP() const { return true; } - - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; + void RenderExtraToolArgs(const JobAction &JA, + llvm::opt::ArgStringList &CmdArgs) const override; }; class LLVM_LIBRARY_VISIBILITY Compile : public Common { @@ -156,22 +153,11 @@ namespace gcc { Compile(const ToolChain &TC) : Common("gcc::Compile", "gcc frontend", TC) {} - virtual bool hasGoodDiagnostics() const { return true; } - virtual bool hasIntegratedCPP() const { return true; } + bool hasGoodDiagnostics() const override { return true; } + bool hasIntegratedCPP() const override { return true; } - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; - }; - - class LLVM_LIBRARY_VISIBILITY Assemble : public Common { - public: - Assemble(const ToolChain &TC) : Common("gcc::Assemble", - "assembler (via gcc)", TC) {} - - virtual bool hasIntegratedCPP() const { return false; } - - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; + void RenderExtraToolArgs(const JobAction &JA, + llvm::opt::ArgStringList &CmdArgs) const override; }; class LLVM_LIBRARY_VISIBILITY Link : public Common { @@ -179,11 +165,11 @@ namespace gcc { Link(const ToolChain &TC) : Common("gcc::Link", "linker (via gcc)", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; + void RenderExtraToolArgs(const JobAction &JA, + llvm::opt::ArgStringList &CmdArgs) const override; }; } // end namespace gcc @@ -195,15 +181,14 @@ namespace hexagon { Assemble(const ToolChain &TC) : Tool("hexagon::Assemble", "hexagon-as", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void RenderExtraToolArgs(const JobAction &JA, - llvm::opt::ArgStringList &CmdArgs) const; - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 { @@ -211,111 +196,124 @@ namespace hexagon { Link(const ToolChain &TC) : Tool("hexagon::Link", "hexagon-ld", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } virtual void RenderExtraToolArgs(const JobAction &JA, llvm::opt::ArgStringList &CmdArgs) const; - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) 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 getArchTypeForDarwinArchName(StringRef Str); + llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); + void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); - class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool { + class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool { virtual void anchor(); protected: - void AddDarwinArch(const llvm::opt::ArgList &Args, + void AddMachOArch(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; - const toolchains::Darwin &getDarwinToolChain() const { - return reinterpret_cast<const toolchains::Darwin&>(getToolChain()); + const toolchains::MachO &getMachOToolChain() const { + return reinterpret_cast<const toolchains::MachO&>(getToolChain()); } public: - DarwinTool(const char *Name, const char *ShortName, + MachOTool(const char *Name, const char *ShortName, const ToolChain &TC) : Tool(Name, ShortName, TC) {} }; - class LLVM_LIBRARY_VISIBILITY Assemble : public DarwinTool { + class LLVM_LIBRARY_VISIBILITY Assemble : public MachOTool { public: - Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble", - "assembler", TC) {} + Assemble(const ToolChain &TC) : MachOTool("darwin::Assemble", + "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 DarwinTool { + 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) : DarwinTool("darwin::Link", "linker", TC) {} + Link(const ToolChain &TC) : MachOTool("darwin::Link", "linker", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 DarwinTool { + class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool { public: - Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", "lipo", TC) {} + Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 DarwinTool { + class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool { public: - Dsymutil(const ToolChain &TC) : DarwinTool("darwin::Dsymutil", - "dsymutil", TC) {} + Dsymutil(const ToolChain &TC) : MachOTool("darwin::Dsymutil", + "dsymutil", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isDsymutilJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isDsymutilJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 DarwinTool { + class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool { public: - VerifyDebug(const ToolChain &TC) : DarwinTool("darwin::VerifyDebug", - "dwarfdump", TC) {} + VerifyDebug(const ToolChain &TC) : MachOTool("darwin::VerifyDebug", + "dwarfdump", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; }; } @@ -327,26 +325,25 @@ namespace openbsd { Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -357,26 +354,24 @@ namespace bitrig { Assemble(const ToolChain &TC) : Tool("bitrig::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -387,26 +382,24 @@ namespace freebsd { Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -418,13 +411,12 @@ namespace netbsd { Assemble(const ToolChain &TC) : Tool("netbsd::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 { @@ -432,14 +424,13 @@ namespace netbsd { Link(const ToolChain &TC) : Tool("netbsd::Link", "linker", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -449,26 +440,26 @@ namespace gnutools { public: Assemble(const ToolChain &TC) : Tool("GNU::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -478,26 +469,26 @@ namespace minix { Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -508,26 +499,24 @@ namespace solaris { Assemble(const ToolChain &TC) : Tool("solaris::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -538,26 +527,24 @@ namespace auroraux { Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 @@ -568,58 +555,55 @@ namespace dragonfly { Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler", TC) {} - virtual bool hasIntegratedCPP() const { return false; } + bool hasIntegratedCPP() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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. +/// Visual studio tools. namespace visualstudio { class LLVM_LIBRARY_VISIBILITY Link : public Tool { public: Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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) {} - virtual bool hasIntegratedAssembler() const { return true; } - virtual bool hasIntegratedCPP() const { return true; } - virtual bool isLinkJob() const { return false; } + bool hasIntegratedAssembler() const override { return true; } + bool hasIntegratedCPP() const override { return true; } + bool isLinkJob() const override { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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, @@ -629,6 +613,10 @@ namespace visualstudio { }; } // 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. @@ -637,12 +625,11 @@ namespace XCore { Assemble(const ToolChain &TC) : Tool("XCore::Assemble", "XCore-as", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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 { @@ -650,13 +637,12 @@ namespace XCore { Link(const ToolChain &TC) : Tool("XCore::Link", "XCore-ld", TC) {} - virtual bool hasIntegratedCPP() const { return false; } - virtual bool isLinkJob() const { return true; } - virtual void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + 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. diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index d947ae7..3538dbc 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -174,6 +174,8 @@ types::ID types::lookupTypeForExtension(const char *Ext) { .Case("F95", TY_Fortran) .Case("mii", TY_PP_ObjCXX) .Case("pcm", TY_ModuleFile) + .Case("pch", TY_PCH) + .Case("gch", TY_PCH) .Default(TY_INVALID); } diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp index 2b6320a..913425a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp @@ -14,6 +14,7 @@ #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" @@ -21,11 +22,15 @@ // Include the necessary headers to interface with the Windows registry and // environment. -#ifdef _MSC_VER +#if defined(LLVM_ON_WIN32) +#define USE_WIN32 +#endif + +#ifdef USE_WIN32 #define WIN32_LEAN_AND_MEAN #define NOGDI #define NOMINMAX - #include <Windows.h> + #include <windows.h> #endif using namespace clang::driver; @@ -43,10 +48,10 @@ Tool *Windows::buildLinker() const { } Tool *Windows::buildAssembler() const { - if (getTriple().getEnvironment() == llvm::Triple::MachO) + if (getTriple().isOSBinFormatMachO()) return new tools::darwin::Assemble(*this); getDriver().Diag(clang::diag::err_no_external_assembler); - return NULL; + return nullptr; } bool Windows::IsIntegratedAssemblerDefault() const { @@ -54,7 +59,11 @@ bool Windows::IsIntegratedAssemblerDefault() const { } bool Windows::IsUnwindTablesDefault() const { - return getArch() == llvm::Triple::x86_64; + // 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 { @@ -69,9 +78,6 @@ bool Windows::isPICDefaultForced() const { return getArch() == llvm::Triple::x86_64; } -// FIXME: This probably should goto to some platform utils place. -#ifdef _MSC_VER - /// \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. @@ -82,6 +88,9 @@ bool Windows::isPICDefaultForced() const { /// 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; @@ -183,6 +192,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, } } return returnValue; +#endif // USE_WIN32 } /// \brief Get Windows SDK installation directory. @@ -202,7 +212,7 @@ static bool getWindowsSDKDir(std::string &path) { return false; } - // Get Visual Studio installation directory. +// 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"); @@ -244,25 +254,11 @@ static bool getVisualStudioDir(std::string &path) { const char *vs100comntools = getenv("VS100COMNTOOLS"); const char *vs90comntools = getenv("VS90COMNTOOLS"); const char *vs80comntools = getenv("VS80COMNTOOLS"); - const char *vscomntools = NULL; - // Try to find the version that we were compiled with - if(false) {} - #if (_MSC_VER >= 1600) // VC100 - else if(vs100comntools) { - vscomntools = vs100comntools; - } - #elif (_MSC_VER == 1500) // VC80 - else if(vs90comntools) { - vscomntools = vs90comntools; - } - #elif (_MSC_VER == 1400) // VC80 - else if(vs80comntools) { - vscomntools = vs80comntools; - } - #endif - // Otherwise find any version we can - else if (vs100comntools) + const char *vscomntools = nullptr; + + // Find any version we can + if (vs100comntools) vscomntools = vs100comntools; else if (vs90comntools) vscomntools = vs90comntools; @@ -277,8 +273,6 @@ static bool getVisualStudioDir(std::string &path) { return false; } -#endif // _MSC_VER - void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc)) @@ -293,21 +287,15 @@ void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; -#ifdef _MSC_VER // 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, ";"); - int n = 0; - for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end(); - I != E; ++I) { - StringRef d = *I; - if (d.size() == 0) - continue; - ++n; - addSystemInclude(DriverArgs, CC1Args, d); - } - if (n) return; + 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; @@ -316,17 +304,24 @@ void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // When built with access to the proper Windows APIs, try to actually find // the correct include paths first. if (getVisualStudioDir(VSDir)) { - addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); - if (getWindowsSDKDir(WindowsSDKDir)) - addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); - else - addSystemInclude(DriverArgs, CC1Args, - VSDir + "\\VC\\PlatformSDK\\Include"); + 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; } -#endif // _MSC_VER // 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", |