diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
18 files changed, 2857 insertions, 1919 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp index 86a48fd..360dbee 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp @@ -29,6 +29,7 @@ const char *Action::getClassName(ActionClass AC) { case AnalyzeJobClass: return "analyzer"; case MigrateJobClass: return "migrator"; case CompileJobClass: return "compiler"; + case BackendJobClass: return "backend"; case AssembleJobClass: return "assembler"; case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; @@ -48,15 +49,15 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type) void BindArchAction::anchor() {} -BindArchAction::BindArchAction(Action *Input, const char *_ArchName) - : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) { -} +BindArchAction::BindArchAction(std::unique_ptr<Action> Input, + const char *_ArchName) + : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {} void JobAction::anchor() {} -JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) - : Action(Kind, Input, Type) { -} +JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input, + types::ID Type) + : Action(Kind, std::move(Input), Type) {} JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) : Action(Kind, Inputs, Type) { @@ -64,39 +65,45 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) void PreprocessJobAction::anchor() {} -PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) - : JobAction(PreprocessJobClass, Input, OutputType) { -} +PreprocessJobAction::PreprocessJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(PreprocessJobClass, std::move(Input), OutputType) {} void PrecompileJobAction::anchor() {} -PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) - : JobAction(PrecompileJobClass, Input, OutputType) { -} +PrecompileJobAction::PrecompileJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(PrecompileJobClass, std::move(Input), OutputType) {} void AnalyzeJobAction::anchor() {} -AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) - : JobAction(AnalyzeJobClass, Input, OutputType) { -} +AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(AnalyzeJobClass, std::move(Input), OutputType) {} void MigrateJobAction::anchor() {} -MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) - : JobAction(MigrateJobClass, Input, OutputType) { -} +MigrateJobAction::MigrateJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(MigrateJobClass, std::move(Input), OutputType) {} void CompileJobAction::anchor() {} -CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) - : JobAction(CompileJobClass, Input, OutputType) { -} +CompileJobAction::CompileJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(CompileJobClass, std::move(Input), OutputType) {} + +void BackendJobAction::anchor() {} + +BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(BackendJobClass, std::move(Input), OutputType) {} void AssembleJobAction::anchor() {} -AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) - : JobAction(AssembleJobClass, Input, OutputType) { -} +AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input, + types::ID OutputType) + : JobAction(AssembleJobClass, std::move(Input), OutputType) {} void LinkJobAction::anchor() {} @@ -118,9 +125,9 @@ DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) void VerifyJobAction::anchor() {} -VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input, - types::ID Type) - : JobAction(Kind, Input, Type) { +VerifyJobAction::VerifyJobAction(ActionClass Kind, + std::unique_ptr<Action> Input, types::ID Type) + : JobAction(Kind, std::move(Input), Type) { assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && "ActionClass is not a valid VerifyJobAction"); } @@ -134,13 +141,12 @@ VerifyJobAction::VerifyJobAction(ActionClass Kind, ActionList &Inputs, void VerifyDebugInfoJobAction::anchor() {} -VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input, - types::ID Type) - : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) { -} +VerifyDebugInfoJobAction::VerifyDebugInfoJobAction( + std::unique_ptr<Action> Input, types::ID Type) + : VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {} void VerifyPCHJobAction::anchor() {} -VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type) - : VerifyJobAction(VerifyPCHJobClass, Input, Type) { -} +VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr<Action> Input, + types::ID Type) + : VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {} diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index 49b7edd..2bcbd5c 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -88,7 +88,7 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { // Failure is only failure if the file exists and is "regular". We checked // for it being regular before, and llvm::sys::fs::remove ignores ENOENT, // so we don't need to check again. - + if (IssueErrors) getDriver().Diag(clang::diag::err_drv_unable_to_remove_file) << EC.message(); @@ -131,13 +131,13 @@ int Compilation::ExecuteCommand(const Command &C, // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the // output stream. if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) { - std::string Error; - OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, Error, + std::error_code EC; + OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC, llvm::sys::fs::F_Append | llvm::sys::fs::F_Text); - if (!Error.empty()) { + if (EC) { getDriver().Diag(clang::diag::err_drv_cc_print_options_failure) - << Error; + << EC.message(); FailingCommand = &C; delete OS; return 1; @@ -202,9 +202,8 @@ void Compilation::ExecuteJob(const Job &J, FailingCommands.push_back(std::make_pair(Res, FailingCommand)); } else { const JobList *Jobs = cast<JobList>(&J); - for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end(); - it != ie; ++it) - ExecuteJob(**it, FailingCommands); + for (const auto &Job : *Jobs) + ExecuteJob(Job, FailingCommands); } } @@ -233,8 +232,8 @@ void Compilation::initCompilationForDiagnostics() { // Redirect stdout/stderr to /dev/null. Redirects = new const StringRef*[3](); Redirects[0] = nullptr; - Redirects[1] = new const StringRef(); - Redirects[2] = new const StringRef(); + Redirects[1] = new StringRef(); + Redirects[2] = new StringRef(); } StringRef Compilation::getSysRoot() const { diff --git a/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp new file mode 100644 index 0000000..03fe41b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Driver/CrossWindowsToolChain.cpp @@ -0,0 +1,117 @@ +//===--- CrossWindowsToolChain.cpp - Cross Windows Tool Chain -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ToolChains.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; + +CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, + const llvm::Triple &T, + const llvm::opt::ArgList &Args) + : Generic_GCC(D, T, Args) { + if (GetCXXStdlibType(Args) == ToolChain::CST_Libstdcxx) { + const std::string &SysRoot = D.SysRoot; + + // libstdc++ resides in /usr/lib, but depends on libgcc which is placed in + // /usr/lib/gcc. + getFilePaths().push_back(SysRoot + "/usr/lib"); + getFilePaths().push_back(SysRoot + "/usr/lib/gcc"); + } +} + +bool CrossWindowsToolChain::IsUnwindTablesDefault() const { + // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does + // not know how to emit them. + return getArch() == llvm::Triple::x86_64; +} + +bool CrossWindowsToolChain::isPICDefault() const { + return getArch() == llvm::Triple::x86_64; +} + +bool CrossWindowsToolChain::isPIEDefault() const { + return getArch() == llvm::Triple::x86_64; +} + +bool CrossWindowsToolChain::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64; +} + +void CrossWindowsToolChain:: +AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + const std::string &SysRoot = D.SysRoot; + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> ResourceDir(D.ResourceDir); + llvm::sys::path::append(ResourceDir, "include"); + addSystemInclude(DriverArgs, CC1Args, ResourceDir.str()); + } + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); +} + +void CrossWindowsToolChain:: +AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const llvm::Triple &Triple = getTriple(); + const std::string &SysRoot = getDriver().SysRoot; + + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: + addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1"); + break; + + case ToolChain::CST_Libstdcxx: + addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++"); + addSystemInclude(DriverArgs, CC1Args, + SysRoot + "/usr/include/c++/" + Triple.str()); + addSystemInclude(DriverArgs, CC1Args, + SysRoot + "/usr/include/c++/backwards"); + } +} + +void CrossWindowsToolChain:: +AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: + CC1Args.push_back("-lc++"); + break; + case ToolChain::CST_Libstdcxx: + CC1Args.push_back("-lstdc++"); + CC1Args.push_back("-lmingw32"); + CC1Args.push_back("-lmingwex"); + CC1Args.push_back("-lgcc"); + CC1Args.push_back("-lmoldname"); + CC1Args.push_back("-lmingw32"); + break; + } +} + +Tool *CrossWindowsToolChain::buildLinker() const { + return new tools::CrossWindows::Link(*this); +} + +Tool *CrossWindowsToolChain::buildAssembler() const { + return new tools::CrossWindows::Assemble(*this); +} + diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index ef26bfa..1664d0d 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -50,7 +50,6 @@ Driver::Driver(StringRef ClangExecutable, : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), - DefaultImageName("a.out"), DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), @@ -65,10 +64,13 @@ Driver::Driver(StringRef ClangExecutable, // Compute the path to the resource directory. StringRef ClangResourceDir(CLANG_RESOURCE_DIR); SmallString<128> P(Dir); - if (ClangResourceDir != "") + if (ClangResourceDir != "") { llvm::sys::path::append(P, ClangResourceDir); - else - llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING); + } else { + StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX); + llvm::sys::path::append(P, "..", Twine("lib") + ClangLibdirSuffix, "clang", + CLANG_VERSION_STRING); + } ResourceDir = P.str(); } @@ -83,6 +85,9 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) { getOpts().getOption(options::OPT_driver_mode).getPrefixedName(); for (size_t I = 0, E = Args.size(); I != E; ++I) { + // Ingore nullptrs, they are response file's EOL markers + if (Args[I] == nullptr) + continue; const StringRef Arg = Args[I]; if (!Arg.startswith(OptName)) continue; @@ -102,7 +107,7 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) { } } -InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { +InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned IncludedFlagsBitmask; @@ -111,7 +116,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { getIncludeExcludeOptionFlagMasks(); unsigned MissingArgIndex, MissingArgCount; - InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), + InputArgList *Args = getOpts().ParseArgs(ArgStrings.begin(), ArgStrings.end(), MissingArgIndex, MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask); @@ -122,9 +127,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { << Args->getArgString(MissingArgIndex) << MissingArgCount; // Check for unsupported options. - for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); - it != ie; ++it) { - Arg *A = *it; + for (const Arg *A : *Args) { if (A->getOption().hasFlag(options::Unsupported)) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; @@ -162,7 +165,7 @@ const { (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { FinalPhase = phases::Preprocess; - // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler. + // -{fsyntax-only,-analyze,emit-ast} 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)) || @@ -171,10 +174,13 @@ const { (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || (PhaseArg = DAL.getLastArg(options::OPT__analyze, options::OPT__analyze_auto)) || - (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || - (PhaseArg = DAL.getLastArg(options::OPT_S))) { + (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { FinalPhase = phases::Compile; + // -S only runs up to the backend. + } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) { + FinalPhase = phases::Backend; + // -c only runs up to the assembler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) { FinalPhase = phases::Assemble; @@ -202,10 +208,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); bool HasNostdlib = Args.hasArg(options::OPT_nostdlib); - for (ArgList::const_iterator it = Args.begin(), - ie = Args.end(); it != ie; ++it) { - const Arg *A = *it; - + for (Arg *A : Args) { // Unfortunately, we have to parse some forwarding options (-Xassembler, // -Xlinker, -Xpreprocessor) because we either integrate their functionality // (assembler and preprocessor), or bypass a previous driver ('collect2'). @@ -271,7 +274,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { continue; } - DAL->append(*it); + DAL->append(A); } // Add a default value of -mlinker-version=, if one was given and the user @@ -400,13 +403,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // preprocessed source file(s). Request that the developer attach the // diagnostic information to a bug report. void Driver::generateCompilationDiagnostics(Compilation &C, - const Command *FailingCommand) { + const Command &FailingCommand) { if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) return; // Don't try to generate diagnostics for link or dsymutil jobs. - if (FailingCommand && (FailingCommand->getCreator().isLinkJob() || - FailingCommand->getCreator().isDsymutilJob())) + if (FailingCommand.getCreator().isLinkJob() || + FailingCommand.getCreator().isDsymutilJob()) return; // Print the version of the compiler. @@ -421,15 +424,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, CCGenDiagnostics = true; // Save the original job command(s). - std::string Cmd; - llvm::raw_string_ostream OS(Cmd); - if (FailingCommand) - FailingCommand->Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true); - else - // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an - // associated FailingCommand, so just pass all jobs. - C.getJobs().Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true); - OS.flush(); + Command Cmd = FailingCommand; // Keep track of whether we produce any errors while trying to produce // preprocessed sources. @@ -473,9 +468,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // Don't attempt to generate preprocessed files if multiple -arch options are // used, unless they're all duplicates. llvm::StringSet<> ArchNames; - for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); - it != ie; ++it) { - Arg *A = *it; + for (const Arg *A : C.getArgs()) { if (A->getOption().matches(options::OPT_arch)) { StringRef ArchName = A->getValue(); ArchNames.insert(ArchName); @@ -509,70 +502,86 @@ void Driver::generateCompilationDiagnostics(Compilation &C, SmallVector<std::pair<int, const Command *>, 4> FailingCommands; C.ExecuteJob(C.getJobs(), FailingCommands); - // If the command succeeded, we are done. - if (FailingCommands.empty()) { + // If any of the preprocessing commands failed, clean up and exit. + if (!FailingCommands.empty()) { + if (!C.getArgs().hasArg(options::OPT_save_temps)) + C.CleanupFileList(C.getTempFiles(), true); + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s)."; + return; + } + + const ArgStringList &TempFiles = C.getTempFiles(); + if (TempFiles.empty()) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s)."; + return; + } + + Diag(clang::diag::note_drv_command_failed_diag_msg) << "\n********************\n\n" - "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" - "Preprocessed source(s) and associated run script(s) are located at:"; - ArgStringList Files = C.getTempFiles(); - for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end(); - it != ie; ++it) { - Diag(clang::diag::note_drv_command_failed_diag_msg) << *it; - std::string Script = StringRef(*it).rsplit('.').first; + "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n" + "Preprocessed source(s) and associated run script(s) are located at:"; + + SmallString<128> VFS; + for (const char *TempFile : TempFiles) { + Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile; + if (StringRef(TempFile).endswith(".cache")) { // In some cases (modules) we'll dump extra data to help with reproducing // the crash into a directory next to the output. - SmallString<128> VFS; - if (llvm::sys::fs::exists(Script + ".cache")) { - Diag(clang::diag::note_drv_command_failed_diag_msg) - << Script + ".cache"; - VFS = llvm::sys::path::filename(Script + ".cache"); - llvm::sys::path::append(VFS, "vfs", "vfs.yaml"); - } - - std::string Err; - Script += ".sh"; - llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err, llvm::sys::fs::F_Excl); - if (!Err.empty()) { - Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating run script: " + Script + " " + Err; - } else { - // Replace the original filename with the preprocessed one. - size_t I, E; - I = Cmd.find("-main-file-name "); - assert (I != std::string::npos && "Expected to find -main-file-name"); - I += 16; - E = Cmd.find(" ", I); - assert (E != std::string::npos && "-main-file-name missing argument?"); - StringRef OldFilename = StringRef(Cmd).slice(I, E); - StringRef NewFilename = llvm::sys::path::filename(*it); - I = StringRef(Cmd).rfind(OldFilename); - E = I + OldFilename.size(); - I = Cmd.rfind(" ", I) + 1; - Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size()); - if (!VFS.empty()) { - // Add the VFS overlay to the reproduction script. - I += NewFilename.size(); - Cmd.insert(I, std::string(" -ivfsoverlay ") + VFS.c_str()); - } - ScriptOS << Cmd; - Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; - } + VFS = llvm::sys::path::filename(TempFile); + llvm::sys::path::append(VFS, "vfs", "vfs.yaml"); } + } + + // Assume associated files are based off of the first temporary file. + CrashReportInfo CrashInfo(TempFiles[0], VFS); + + std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; + std::error_code EC; + llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::F_Excl); + if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) - << "\n\n********************"; + << "Error generating run script: " + Script + " " + EC.message(); } else { - // Failure, remove preprocessed files. - if (!C.getArgs().hasArg(options::OPT_save_temps)) - C.CleanupFileList(C.getTempFiles(), true); + Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); + Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; + } - Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating preprocessed source(s)."; + for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file, + options::OPT_frewrite_map_file_EQ)) + Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue(); + + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "\n\n********************"; +} + +void Driver::setUpResponseFiles(Compilation &C, Job &J) { + if (JobList *Jobs = dyn_cast<JobList>(&J)) { + for (auto &Job : *Jobs) + setUpResponseFiles(C, Job); + return; } + + Command *CurCommand = dyn_cast<Command>(&J); + if (!CurCommand) + return; + + // Since argumentsFitWithinSystemLimits() may underestimate system's capacity + // if the tool does not support response files, there is a chance/ that things + // will just work without a response file, so we silently just skip it. + if (CurCommand->getCreator().getResponseFilesSupport() == Tool::RF_None || + llvm::sys::argumentsFitWithinSystemLimits(CurCommand->getArguments())) + return; + + std::string TmpName = GetTemporaryPath("response", "txt"); + CurCommand->setResponseFile(C.addTempFile(C.getArgs().MakeArgString( + TmpName.c_str()))); } -int Driver::ExecuteCompilation(const Compilation &C, - SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const { +int Driver::ExecuteCompilation(Compilation &C, + SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) { // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.getJobs().Print(llvm::errs(), "\n", true); @@ -583,6 +592,9 @@ int Driver::ExecuteCompilation(const Compilation &C, if (Diags.hasErrorOccurred()) return 1; + // Set up response file names for each command, if necessary + setUpResponseFiles(C, C.getJobs()); + C.ExecuteJob(C.getJobs(), FailingCommands); // Remove temp files. @@ -653,9 +665,13 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { OS << "Target: " << TC.getTripleString() << '\n'; // Print the threading model. - // - // FIXME: Implement correctly. - OS << "Thread model: " << "posix" << '\n'; + if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) { + // Don't print if the ToolChain would have barfed on it already + if (TC.isThreadModelSupported(A->getValue())) + OS << "Thread model: " << A->getValue(); + } else + OS << "Thread model: " << TC.getThreadModel(); + OS << '\n'; } /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories @@ -836,7 +852,9 @@ void Driver::PrintActions(const Compilation &C) const { /// \brief Check whether the given input tree contains any compilation or /// assembly actions. static bool ContainsCompileOrAssembleAction(const Action *A) { - if (isa<CompileJobAction>(A) || isa<AssembleJobAction>(A)) + if (isa<CompileJobAction>(A) || + isa<BackendJobAction>(A) || + isa<AssembleJobAction>(A)) return true; for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it) @@ -855,10 +873,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, // be handled once (in the order seen). llvm::StringSet<> ArchNames; SmallVector<const char *, 4> Archs; - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it) { - Arg *A = *it; - + for (Arg *A : Args) { if (A->getOption().matches(options::OPT_arch)) { // Validate the option here; we don't save the type here because its // particular spelling may participate in other driver choices. @@ -871,7 +886,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC, } A->claim(); - if (ArchNames.insert(A->getValue())) + if (ArchNames.insert(A->getValue()).second) Archs.push_back(A->getValue()); } } @@ -901,7 +916,8 @@ void Driver::BuildUniversalActions(const ToolChain &TC, ActionList Inputs; for (unsigned i = 0, e = Archs.size(); i != e; ++i) { - Inputs.push_back(new BindArchAction(Act, Archs[i])); + Inputs.push_back( + new BindArchAction(std::unique_ptr<Action>(Act), Archs[i])); if (i != 0) Inputs.back()->setOwnsInputs(false); } @@ -932,9 +948,9 @@ void Driver::BuildUniversalActions(const ToolChain &TC, // Verify the debug info output. if (Args.hasArg(options::OPT_verify_debug_info)) { - Action *VerifyInput = Actions.back(); + std::unique_ptr<Action> VerifyInput(Actions.back()); Actions.pop_back(); - Actions.push_back(new VerifyDebugInfoJobAction(VerifyInput, + Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput), types::TY_Nothing)); } } @@ -981,8 +997,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, Arg *InputTypeArg = nullptr; // The last /TC or /TP option sets the input type to C or C++ globally. - if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC, - options::OPT__SLASH_TP)) { + if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC, + options::OPT__SLASH_TP)) { InputTypeArg = TCTP; InputType = TCTP->getOption().matches(options::OPT__SLASH_TC) ? types::TY_C : types::TY_CXX; @@ -1005,10 +1021,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed"); } - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it) { - Arg *A = *it; - + for (Arg *A : Args) { if (A->getOption().getKind() == Option::InputClass) { const char *Value = A->getValue(); types::ID Ty = types::TY_INVALID; @@ -1070,8 +1083,17 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } else { assert(InputTypeArg && "InputType set w/o InputTypeArg"); - InputTypeArg->claim(); - Ty = InputType; + if (!InputTypeArg->getOption().matches(options::OPT_x)) { + // If emulating cl.exe, make sure that /TC and /TP don't affect input + // object files. + const char *Ext = strrchr(Value, '.'); + if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object) + Ty = types::TY_Object; + } + if (Ty == types::TY_INVALID) { + Ty = InputType; + InputTypeArg->claim(); + } } if (DiagnoseInputExistence(*this, Args, Value)) @@ -1142,11 +1164,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, // Diagnose misuse of /Fo. if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { StringRef V = A->getValue(); - if (V.empty()) { - // It has to have a value. - Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; - Args.eraseArg(options::OPT__SLASH_Fo); - } else if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) { + if (Inputs.size() > 1 && !V.empty() && + !llvm::sys::path::is_separator(V.back())) { // Check whether /Fo tries to name an output file for multiple inputs. Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) << A->getSpelling() << V; @@ -1157,7 +1176,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, // Diagnose misuse of /Fa. if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { StringRef V = A->getValue(); - if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) { + if (Inputs.size() > 1 && !V.empty() && + !llvm::sys::path::is_separator(V.back())) { // Check whether /Fa tries to name an asm file for multiple inputs. Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) << A->getSpelling() << V; @@ -1165,12 +1185,12 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, } } - // Diagnose misuse of /Fe. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fe)) { + // Diagnose misuse of /o. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) { if (A->getValue()[0] == '\0') { // It has to have a value. Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; - Args.eraseArg(options::OPT__SLASH_Fe); + Args.eraseArg(options::OPT__SLASH_o); } } @@ -1244,7 +1264,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, continue; // Otherwise construct the appropriate action. - Current.reset(ConstructPhaseAction(Args, Phase, Current.release())); + Current = ConstructPhaseAction(Args, Phase, std::move(Current)); if (Current->getType() == types::TY_Nothing) break; } @@ -1269,8 +1289,9 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, Args.ClaimAllArgs(options::OPT_cl_ignored_Group); } -Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, - Action *Input) const { +std::unique_ptr<Action> +Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, + std::unique_ptr<Action> Input) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. switch (Phase) { @@ -1289,7 +1310,7 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, assert(OutputTy != types::TY_INVALID && "Cannot preprocess this input type!"); } - return new PreprocessJobAction(Input, OutputTy); + return llvm::make_unique<PreprocessJobAction>(std::move(Input), OutputTy); } case phases::Precompile: { types::ID OutputTy = types::TY_PCH; @@ -1297,39 +1318,53 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, // Syntax checks should not emit a PCH file OutputTy = types::TY_Nothing; } - return new PrecompileJobAction(Input, OutputTy); + return llvm::make_unique<PrecompileJobAction>(std::move(Input), OutputTy); } case phases::Compile: { - if (Args.hasArg(options::OPT_fsyntax_only)) { - return new CompileJobAction(Input, types::TY_Nothing); - } else if (Args.hasArg(options::OPT_rewrite_objc)) { - return new CompileJobAction(Input, types::TY_RewrittenObjC); - } else if (Args.hasArg(options::OPT_rewrite_legacy_objc)) { - return new CompileJobAction(Input, types::TY_RewrittenLegacyObjC); - } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) { - return new AnalyzeJobAction(Input, types::TY_Plist); - } else if (Args.hasArg(options::OPT__migrate)) { - return new MigrateJobAction(Input, types::TY_Remap); - } else if (Args.hasArg(options::OPT_emit_ast)) { - return new CompileJobAction(Input, types::TY_AST); - } else if (Args.hasArg(options::OPT_module_file_info)) { - return new CompileJobAction(Input, types::TY_ModuleFile); - } else if (Args.hasArg(options::OPT_verify_pch)) { - return new VerifyPCHJobAction(Input, types::TY_Nothing); - } else if (IsUsingLTO(Args)) { + if (Args.hasArg(options::OPT_fsyntax_only)) + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_Nothing); + if (Args.hasArg(options::OPT_rewrite_objc)) + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_RewrittenObjC); + if (Args.hasArg(options::OPT_rewrite_legacy_objc)) + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_RewrittenLegacyObjC); + if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) + return llvm::make_unique<AnalyzeJobAction>(std::move(Input), + types::TY_Plist); + if (Args.hasArg(options::OPT__migrate)) + return llvm::make_unique<MigrateJobAction>(std::move(Input), + types::TY_Remap); + if (Args.hasArg(options::OPT_emit_ast)) + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_AST); + if (Args.hasArg(options::OPT_module_file_info)) + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_ModuleFile); + if (Args.hasArg(options::OPT_verify_pch)) + return llvm::make_unique<VerifyPCHJobAction>(std::move(Input), + types::TY_Nothing); + return llvm::make_unique<CompileJobAction>(std::move(Input), + types::TY_LLVM_BC); + } + case phases::Backend: { + if (IsUsingLTO(Args)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; - return new CompileJobAction(Input, Output); - } else if (Args.hasArg(options::OPT_emit_llvm)) { + return llvm::make_unique<BackendJobAction>(std::move(Input), Output); + } + if (Args.hasArg(options::OPT_emit_llvm)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; - return new CompileJobAction(Input, Output); - } else { - return new CompileJobAction(Input, types::TY_PP_Asm); + return llvm::make_unique<BackendJobAction>(std::move(Input), Output); } + return llvm::make_unique<BackendJobAction>(std::move(Input), + types::TY_PP_Asm); } case phases::Assemble: - return new AssembleJobAction(Input, types::TY_Object); + return llvm::make_unique<AssembleJobAction>(std::move(Input), + types::TY_Object); } llvm_unreachable("invalid phase in ConstructPhaseAction"); @@ -1351,9 +1386,8 @@ void Driver::BuildJobs(Compilation &C) const { // files. if (FinalOutput) { unsigned NumOutputs = 0; - for (ActionList::const_iterator it = C.getActions().begin(), - ie = C.getActions().end(); it != ie; ++it) - if ((*it)->getType() != types::TY_Nothing) + for (const Action *A : C.getActions()) + if (A->getType() != types::TY_Nothing) ++NumOutputs; if (NumOutputs > 1) { @@ -1364,19 +1398,12 @@ void Driver::BuildJobs(Compilation &C) const { // Collect the list of architectures. llvm::StringSet<> ArchNames; - if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) { - for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); - it != ie; ++it) { - Arg *A = *it; + if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) + for (const Arg *A : C.getArgs()) if (A->getOption().matches(options::OPT_arch)) ArchNames.insert(A->getValue()); - } - } - - for (ActionList::const_iterator it = C.getActions().begin(), - ie = C.getActions().end(); it != ie; ++it) { - Action *A = *it; + for (Action *A : C.getActions()) { // If we are linking an image for multiple archs then the linker wants // -arch_multiple and -final_output <final image name>. Unfortunately, this // doesn't fit in cleanly because we have to pass this information down. @@ -1388,7 +1415,7 @@ void Driver::BuildJobs(Compilation &C) const { if (FinalOutput) LinkingOutput = FinalOutput->getValue(); else - LinkingOutput = DefaultImageName.c_str(); + LinkingOutput = getDefaultImageName(); } InputInfo II; @@ -1412,10 +1439,7 @@ void Driver::BuildJobs(Compilation &C) const { // Claim --driver-mode, it was handled earlier. (void) C.getArgs().hasArg(options::OPT_driver_mode); - for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); - it != ie; ++it) { - Arg *A = *it; - + for (Arg *A : C.getArgs()) { // FIXME: It would be nice to be able to send the argument to the // DiagnosticsEngine, so that extra values, position, and so on could be // printed. @@ -1462,12 +1486,34 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, !C.getArgs().hasArg(options::OPT__SLASH_FA) && !C.getArgs().hasArg(options::OPT__SLASH_Fa) && isa<AssembleJobAction>(JA) && - Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) { - const Tool *Compiler = - TC->SelectTool(cast<JobAction>(**Inputs->begin())); + Inputs->size() == 1 && isa<BackendJobAction>(*Inputs->begin())) { + // A BackendJob is always preceded by a CompileJob, and without + // -save-temps they will always get combined together, so instead of + // checking the backend tool, check if the tool for the CompileJob + // has an integrated assembler. + const ActionList *BackendInputs = &(*Inputs)[0]->getInputs(); + JobAction *CompileJA = cast<CompileJobAction>(*BackendInputs->begin()); + const Tool *Compiler = TC->SelectTool(*CompileJA); if (!Compiler) return nullptr; if (Compiler->hasIntegratedAssembler()) { + Inputs = &(*BackendInputs)[0]->getInputs(); + ToolForJob = Compiler; + } + } + + // A backend job should always be combined with the preceding compile job + // unless OPT_save_temps is enabled and the compiler is capable of emitting + // LLVM IR as an intermediate output. + if (isa<BackendJobAction>(JA)) { + // Check if the compiler supports emitting LLVM IR. + assert(Inputs->size() == 1); + JobAction *CompileJA = cast<CompileJobAction>(*Inputs->begin()); + const Tool *Compiler = TC->SelectTool(*CompileJA); + if (!Compiler) + return nullptr; + if (!Compiler->canEmitIR() || + !C.getArgs().hasArg(options::OPT_save_temps)) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = Compiler; } @@ -1537,8 +1583,7 @@ void Driver::BuildJobsForAction(Compilation &C, // Only use pipes when there is exactly one input. InputInfoList InputInfos; - for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end(); - it != ie; ++it) { + for (const Action *Input : *Inputs) { // Treat dsymutil and verify sub-jobs as being at the top-level too, they // shouldn't get temporary output names. // FIXME: Clean this up. @@ -1547,7 +1592,7 @@ void Driver::BuildJobsForAction(Compilation &C, SubJobAtTopLevel = true; InputInfo II; - BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, + BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput, II); InputInfos.push_back(II); } @@ -1583,6 +1628,11 @@ void Driver::BuildJobsForAction(Compilation &C, } } +const char *Driver::getDefaultImageName() const { + llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); + return Target.isOSWindows() ? "a.exe" : "a.out"; +} + /// \brief Create output filename based on ArgValue, which could either be a /// full filename, filename without extension, or a directory. If ArgValue /// does not provide a filename, then use BaseName, and use the extension @@ -1634,7 +1684,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, assert(AtTopLevel && isa<PreprocessJobAction>(JA)); StringRef BaseName = llvm::sys::path::filename(BaseInput); StringRef NameArg; - if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi)) + if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi, + options::OPT__SLASH_o)) NameArg = A->getValue(); return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C), &JA); @@ -1681,15 +1732,17 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const char *NamedOutput; if (JA.getType() == types::TY_Object && - C.getArgs().hasArg(options::OPT__SLASH_Fo)) { - // The /Fo flag decides the object filename. - StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue(); + C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) { + // The /Fo or /o flag decides the object filename. + StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo, + options::OPT__SLASH_o)->getValue(); NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object); } else if (JA.getType() == types::TY_Image && - C.getArgs().hasArg(options::OPT__SLASH_Fe)) { - // The /Fe flag names the linked file. - StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue(); + C.getArgs().hasArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)) { + // The /Fe or /o flag names the linked file. + StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe, + options::OPT__SLASH_o)->getValue(); NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image); } else if (JA.getType() == types::TY_Image) { @@ -1698,12 +1751,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image); } else if (MultipleArchs && BoundArch) { - SmallString<128> Output(DefaultImageName.c_str()); + SmallString<128> Output(getDefaultImageName()); Output += "-"; Output.append(BoundArch); NamedOutput = C.getArgs().MakeArgString(Output.c_str()); } else - NamedOutput = DefaultImageName.c_str(); + NamedOutput = getDefaultImageName(); } else { const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); assert(Suffix && "All types used for output should have a suffix."); @@ -1716,6 +1769,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, Suffixed += "-"; Suffixed.append(BoundArch); } + // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for + // the unoptimized bitcode so that it does not get overwritten by the ".bc" + // optimized bitcode output. + if (!AtTopLevel && C.getArgs().hasArg(options::OPT_emit_llvm) && + JA.getType() == types::TY_LLVM_BC) + Suffixed += ".tmp"; Suffixed += '.'; Suffixed += Suffix; NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); @@ -1793,51 +1852,56 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { return Name; } +void +Driver::generatePrefixedToolNames(const char *Tool, const ToolChain &TC, + SmallVectorImpl<std::string> &Names) const { + // FIXME: Needs a better variable than DefaultTargetTriple + Names.push_back(DefaultTargetTriple + "-" + Tool); + Names.push_back(Tool); +} + +static bool ScanDirForExecutable(SmallString<128> &Dir, + ArrayRef<std::string> Names) { + for (const auto &Name : Names) { + llvm::sys::path::append(Dir, Name); + if (llvm::sys::fs::can_execute(Twine(Dir))) + return true; + llvm::sys::path::remove_filename(Dir); + } + return false; +} + std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC) const { - // FIXME: Needs a better variable than DefaultTargetTriple - std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name); + SmallVector<std::string, 2> TargetSpecificExecutables; + generatePrefixedToolNames(Name, TC, TargetSpecificExecutables); + // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when looking for program paths. - for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), - ie = PrefixDirs.end(); it != ie; ++it) { - if (llvm::sys::fs::is_directory(*it)) { - SmallString<128> P(*it); - llvm::sys::path::append(P, TargetSpecificExecutable); - if (llvm::sys::fs::can_execute(Twine(P))) - return P.str(); - llvm::sys::path::remove_filename(P); - llvm::sys::path::append(P, Name); - if (llvm::sys::fs::can_execute(Twine(P))) + for (const auto &PrefixDir : PrefixDirs) { + if (llvm::sys::fs::is_directory(PrefixDir)) { + SmallString<128> P(PrefixDir); + if (ScanDirForExecutable(P, TargetSpecificExecutables)) return P.str(); } else { - SmallString<128> P(*it + Name); + SmallString<128> P(PrefixDir + Name); if (llvm::sys::fs::can_execute(Twine(P))) return P.str(); } } const ToolChain::path_list &List = TC.getProgramPaths(); - for (ToolChain::path_list::const_iterator - it = List.begin(), ie = List.end(); it != ie; ++it) { - SmallString<128> P(*it); - llvm::sys::path::append(P, TargetSpecificExecutable); - if (llvm::sys::fs::can_execute(Twine(P))) - return P.str(); - llvm::sys::path::remove_filename(P); - llvm::sys::path::append(P, Name); - if (llvm::sys::fs::can_execute(Twine(P))) + for (const auto &Path : List) { + SmallString<128> P(Path); + if (ScanDirForExecutable(P, TargetSpecificExecutables)) return P.str(); } // If all else failed, search the path. - std::string P(llvm::sys::FindProgramByName(TargetSpecificExecutable)); - if (!P.empty()) - return P; - - P = llvm::sys::FindProgramByName(Name); - if (!P.empty()) - return P; + for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) + if (llvm::ErrorOr<std::string> P = + llvm::sys::findProgramByName(TargetSpecificExecutable)) + return *P; return Name; } @@ -1893,8 +1957,6 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, 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); @@ -1902,15 +1964,11 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, Target.setArch(llvm::Triple::mips64); else if (Target.getArch() == llvm::Triple::aarch64) Target.setArch(llvm::Triple::aarch64_be); - else if (Target.getArch() == llvm::Triple::arm64) - Target.setArch(llvm::Triple::arm64_be); } } // Skip further flag support on OSes which don't support '-m32' or '-m64'. - if (Target.getArchName() == "tce" || - Target.getOS() == llvm::Triple::AuroraUX || - Target.getOS() == llvm::Triple::Minix) + if (Target.getArchName() == "tce" || Target.getOS() == llvm::Triple::Minix) return Target; // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'. @@ -1918,21 +1976,25 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, options::OPT_m32, options::OPT_m16)) { llvm::Triple::ArchType AT = llvm::Triple::UnknownArch; - if (A->getOption().matches(options::OPT_m64)) + if (A->getOption().matches(options::OPT_m64)) { AT = Target.get64BitArchVariant().getArch(); - else if (A->getOption().matches(options::OPT_mx32) && + if (Target.getEnvironment() == llvm::Triple::GNUX32) + Target.setEnvironment(llvm::Triple::GNU); + } 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)) + } else if (A->getOption().matches(options::OPT_m32)) { AT = Target.get32BitArchVariant().getArch(); - else if (A->getOption().matches(options::OPT_m16) && + if (Target.getEnvironment() == llvm::Triple::GNUX32) + Target.setEnvironment(llvm::Triple::GNU); + } 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) + if (AT != llvm::Triple::UnknownArch && AT != Target.getArch()) Target.setArch(AT); } @@ -1947,9 +2009,6 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, ToolChain *&TC = ToolChains[Target.str()]; if (!TC) { switch (Target.getOS()) { - case llvm::Triple::AuroraUX: - TC = new toolchains::AuroraUX(*this, Target, Args); - break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: @@ -2000,9 +2059,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = new toolchains::Generic_GCC(*this, Target, Args); break; + case llvm::Triple::Itanium: + TC = new toolchains::CrossWindowsToolChain(*this, Target, Args); + break; case llvm::Triple::MSVC: case llvm::Triple::UnknownEnvironment: - TC = new toolchains::Windows(*this, Target, Args); + TC = new toolchains::MSVCToolChain(*this, Target, Args); break; } break; @@ -2025,7 +2087,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = new toolchains::Generic_ELF(*this, Target, Args); break; } - if (Target.getObjectFormat() == llvm::Triple::MachO) { + if (Target.isOSBinFormatMachO()) { TC = new toolchains::MachO(*this, Target, Args); break; } @@ -2045,7 +2107,7 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const { // Otherwise make sure this is an action clang understands. if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && - !isa<CompileJobAction>(JA)) + !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) return false; return true; diff --git a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h index 4eedd22..b23ba57 100644 --- a/contrib/llvm/tools/clang/lib/Driver/InputInfo.h +++ b/contrib/llvm/tools/clang/lib/Driver/InputInfo.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LIB_DRIVER_INPUTINFO_H_ -#define CLANG_LIB_DRIVER_INPUTINFO_H_ +#ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H +#define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H #include "clang/Driver/Types.h" #include "llvm/Option/Arg.h" diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp index 42cc1bc..c5b3f5a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp @@ -12,8 +12,10 @@ #include "clang/Driver/Job.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" @@ -21,6 +23,7 @@ using namespace clang::driver; using llvm::raw_ostream; using llvm::StringRef; +using llvm::ArrayRef; Job::~Job() {} @@ -28,7 +31,8 @@ Command::Command(const Action &_Source, const Tool &_Creator, const char *_Executable, const ArgStringList &_Arguments) : Job(CommandClass), Source(_Source), Creator(_Creator), - Executable(_Executable), Arguments(_Arguments) {} + Executable(_Executable), Arguments(_Arguments), + ResponseFile(nullptr) {} static int skipArgs(const char *Flag) { // These flags are all of the form -Flag <Arg> and are treated as two @@ -69,12 +73,6 @@ static int skipArgs(const char *Flag) { return 0; } -static bool quoteNextArg(const char *flag) { - return llvm::StringSwitch<bool>(flag) - .Case("-D", true) - .Default(false); -} - static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) { const bool Escape = std::strpbrk(Arg, "\"\\$"); @@ -93,38 +91,162 @@ static void PrintArg(raw_ostream &OS, const char *Arg, bool Quote) { OS << '"'; } +void Command::writeResponseFile(raw_ostream &OS) const { + // In a file list, we only write the set of inputs to the response file + if (Creator.getResponseFilesSupport() == Tool::RF_FileList) { + for (const char *Arg : InputFileList) { + OS << Arg << '\n'; + } + return; + } + + // In regular response files, we send all arguments to the response file + for (const char *Arg : Arguments) { + OS << '"'; + + for (; *Arg != '\0'; Arg++) { + if (*Arg == '\"' || *Arg == '\\') { + OS << '\\'; + } + OS << *Arg; + } + + OS << "\" "; + } +} + +void Command::buildArgvForResponseFile( + llvm::SmallVectorImpl<const char *> &Out) const { + // When not a file list, all arguments are sent to the response file. + // This leaves us to set the argv to a single parameter, requesting the tool + // to read the response file. + if (Creator.getResponseFilesSupport() != Tool::RF_FileList) { + Out.push_back(Executable); + Out.push_back(ResponseFileFlag.c_str()); + return; + } + + llvm::StringSet<> Inputs; + for (const char *InputName : InputFileList) + Inputs.insert(InputName); + Out.push_back(Executable); + // In a file list, build args vector ignoring parameters that will go in the + // response file (elements of the InputFileList vector) + bool FirstInput = true; + for (const char *Arg : Arguments) { + if (Inputs.count(Arg) == 0) { + Out.push_back(Arg); + } else if (FirstInput) { + FirstInput = false; + Out.push_back(Creator.getResponseFileFlag()); + Out.push_back(ResponseFile); + } + } +} + void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport) const { - OS << " \"" << Executable << '"'; + CrashReportInfo *CrashInfo) const { + // Always quote the exe. + OS << ' '; + PrintArg(OS, Executable, /*Quote=*/true); + + llvm::ArrayRef<const char *> Args = Arguments; + llvm::SmallVector<const char *, 128> ArgsRespFile; + if (ResponseFile != nullptr) { + buildArgvForResponseFile(ArgsRespFile); + Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name + } - for (size_t i = 0, e = Arguments.size(); i < e; ++i) { - const char *const Arg = Arguments[i]; + StringRef MainFilename; + // We'll need the argument to -main-file-name to find the input file name. + if (CrashInfo) + for (size_t I = 0, E = Args.size(); I + 1 < E; ++I) + if (StringRef(Args[I]).equals("-main-file-name")) + MainFilename = Args[I + 1]; - if (CrashReport) { + for (size_t i = 0, e = Args.size(); i < e; ++i) { + const char *const Arg = Args[i]; + + if (CrashInfo) { if (int Skip = skipArgs(Arg)) { i += Skip - 1; continue; + } else if (llvm::sys::path::filename(Arg) == MainFilename && + (i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) { + // Replace the input file name with the crashinfo's file name. + OS << ' '; + StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename); + PrintArg(OS, ShortName.str().c_str(), Quote); + continue; } } OS << ' '; PrintArg(OS, Arg, Quote); + } - if (CrashReport && quoteNextArg(Arg) && i + 1 < e) { - OS << ' '; - PrintArg(OS, Arguments[++i], true); - } + if (CrashInfo && !CrashInfo->VFSPath.empty()) { + OS << ' '; + PrintArg(OS, "-ivfsoverlay", Quote); + OS << ' '; + PrintArg(OS, CrashInfo->VFSPath.str().c_str(), Quote); } + + if (ResponseFile != nullptr) { + OS << "\n Arguments passed via response file:\n"; + writeResponseFile(OS); + // Avoiding duplicated newline terminator, since FileLists are + // newline-separated. + if (Creator.getResponseFilesSupport() != Tool::RF_FileList) + OS << "\n"; + OS << " (end of response file)"; + } + OS << Terminator; } +void Command::setResponseFile(const char *FileName) { + ResponseFile = FileName; + ResponseFileFlag = Creator.getResponseFileFlag(); + ResponseFileFlag += FileName; +} + int Command::Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const { SmallVector<const char*, 128> Argv; - Argv.push_back(Executable); - for (size_t i = 0, e = Arguments.size(); i != e; ++i) - Argv.push_back(Arguments[i]); + + if (ResponseFile == nullptr) { + Argv.push_back(Executable); + for (size_t i = 0, e = Arguments.size(); i != e; ++i) + Argv.push_back(Arguments[i]); + Argv.push_back(nullptr); + + return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr, + Redirects, /*secondsToWait*/ 0, + /*memoryLimit*/ 0, ErrMsg, + ExecutionFailed); + } + + // We need to put arguments in a response file (command is too large) + // Open stream to store the response file contents + std::string RespContents; + llvm::raw_string_ostream SS(RespContents); + + // Write file contents and build the Argv vector + writeResponseFile(SS); + buildArgvForResponseFile(Argv); Argv.push_back(nullptr); + SS.flush(); + + // Save the response file in the appropriate encoding + if (std::error_code EC = writeFileWithEncoding( + ResponseFile, RespContents, Creator.getResponseFileEncoding())) { + if (ErrMsg) + *ErrMsg = EC.message(); + if (ExecutionFailed) + *ExecutionFailed = true; + return -1; + } return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr, Redirects, /*secondsToWait*/ 0, @@ -134,15 +256,15 @@ int Command::Execute(const StringRef **Redirects, std::string *ErrMsg, FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_, const char *Executable_, const ArgStringList &Arguments_, - Command *Fallback_) - : Command(Source_, Creator_, Executable_, Arguments_), Fallback(Fallback_) { -} + std::unique_ptr<Command> Fallback_) + : Command(Source_, Creator_, Executable_, Arguments_), + Fallback(std::move(Fallback_)) {} void FallbackCommand::Print(raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport) const { - Command::Print(OS, "", Quote, CrashReport); + bool Quote, CrashReportInfo *CrashInfo) const { + Command::Print(OS, "", Quote, CrashInfo); OS << " ||"; - Fallback->Print(OS, Terminator, Quote, CrashReport); + Fallback->Print(OS, Terminator, Quote, CrashInfo); } static bool ShouldFallback(int ExitCode) { @@ -173,17 +295,10 @@ int FallbackCommand::Execute(const StringRef **Redirects, std::string *ErrMsg, JobList::JobList() : Job(JobListClass) {} -JobList::~JobList() { - for (iterator it = begin(), ie = end(); it != ie; ++it) - delete *it; -} - void JobList::Print(raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport) const { - for (const_iterator it = begin(), ie = end(); it != ie; ++it) - (*it)->Print(OS, Terminator, Quote, CrashReport); + CrashReportInfo *CrashInfo) const { + for (const auto &Job : *this) + Job.Print(OS, Terminator, Quote, CrashInfo); } -void JobList::clear() { - DeleteContainerPointers(Jobs); -} +void JobList::clear() { Jobs.clear(); } diff --git a/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp new file mode 100644 index 0000000..d6bd5c3 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Driver/MSVCToolChain.cpp @@ -0,0 +1,496 @@ +//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/Version.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Process.h" + +// Include the necessary headers to interface with the Windows registry and +// environment. +#if defined(LLVM_ON_WIN32) +#define USE_WIN32 +#endif + +#ifdef USE_WIN32 + #define WIN32_LEAN_AND_MEAN + #define NOGDI + #ifndef NOMINMAX + #define NOMINMAX + #endif + #include <windows.h> +#endif + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +MSVCToolChain::MSVCToolChain(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); +} + +Tool *MSVCToolChain::buildLinker() const { + return new tools::visualstudio::Link(*this); +} + +Tool *MSVCToolChain::buildAssembler() const { + if (getTriple().isOSBinFormatMachO()) + return new tools::darwin::Assemble(*this); + getDriver().Diag(clang::diag::err_no_external_assembler); + return nullptr; +} + +bool MSVCToolChain::IsIntegratedAssemblerDefault() const { + return true; +} + +bool MSVCToolChain::IsUnwindTablesDefault() const { + // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms + // such as ARM and PPC actually require unwind tables, but LLVM doesn't know + // how to generate them yet. + return getArch() == llvm::Triple::x86_64; +} + +bool MSVCToolChain::isPICDefault() const { + return getArch() == llvm::Triple::x86_64; +} + +bool MSVCToolChain::isPIEDefault() const { + return false; +} + +bool MSVCToolChain::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64; +} + +#ifdef USE_WIN32 +static bool readFullStringValue(HKEY hkey, const char *valueName, + std::string &value) { + // FIXME: We should be using the W versions of the registry functions, but + // doing so requires UTF8 / UTF16 conversions similar to how we handle command + // line arguments. The UTF8 conversion functions are not exposed publicly + // from LLVM though, so in order to do this we will probably need to create + // a registry abstraction in LLVMSupport that is Windows only. + DWORD result = 0; + DWORD valueSize = 0; + DWORD type = 0; + // First just query for the required size. + result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize); + if (result != ERROR_SUCCESS || type != REG_SZ) + return false; + std::vector<BYTE> buffer(valueSize); + result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize); + if (result == ERROR_SUCCESS) + value.assign(reinterpret_cast<const char *>(buffer.data())); + return result; +} +#endif + +/// \brief Read registry string. +/// This also supports a means to look for high-versioned keys by use +/// of a $VERSION placeholder in the key path. +/// $VERSION in the key path is a placeholder for the version number, +/// causing the highest value path to be searched for and used. +/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". +/// There can be additional characters in the component. Only the numeric +/// characters are compared. This function only searches HKLM. +static bool getSystemRegistryString(const char *keyPath, const char *valueName, + std::string &value, std::string *phValue) { +#ifndef USE_WIN32 + return false; +#else + HKEY hRootKey = HKEY_LOCAL_MACHINE; + HKEY hKey = NULL; + long lResult; + bool returnValue = false; + + const char *placeHolder = strstr(keyPath, "$VERSION"); + std::string bestName; + // If we have a $VERSION placeholder, do the highest-version search. + if (placeHolder) { + const char *keyEnd = placeHolder - 1; + const char *nextKey = placeHolder; + // Find end of previous key. + while ((keyEnd > keyPath) && (*keyEnd != '\\')) + keyEnd--; + // Find end of key containing $VERSION. + while (*nextKey && (*nextKey != '\\')) + nextKey++; + size_t partialKeyLength = keyEnd - keyPath; + char partialKey[256]; + if (partialKeyLength > sizeof(partialKey)) + partialKeyLength = sizeof(partialKey); + strncpy(partialKey, keyPath, partialKeyLength); + partialKey[partialKeyLength] = '\0'; + HKEY hTopKey = NULL; + lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, + &hTopKey); + if (lResult == ERROR_SUCCESS) { + char keyName[256]; + double bestValue = 0.0; + DWORD index, size = sizeof(keyName) - 1; + for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, + NULL, NULL, NULL) == ERROR_SUCCESS; index++) { + const char *sp = keyName; + while (*sp && !isDigit(*sp)) + sp++; + if (!*sp) + continue; + const char *ep = sp + 1; + while (*ep && (isDigit(*ep) || (*ep == '.'))) + ep++; + char numBuf[32]; + strncpy(numBuf, sp, sizeof(numBuf) - 1); + numBuf[sizeof(numBuf) - 1] = '\0'; + double dvalue = strtod(numBuf, NULL); + if (dvalue > bestValue) { + // Test that InstallDir is indeed there before keeping this index. + // Open the chosen key path remainder. + bestName = keyName; + // Append rest of key. + bestName.append(nextKey); + lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0, + KEY_READ | KEY_WOW64_32KEY, &hKey); + if (lResult == ERROR_SUCCESS) { + lResult = readFullStringValue(hKey, valueName, value); + if (lResult == ERROR_SUCCESS) { + bestValue = dvalue; + if (phValue) + *phValue = bestName; + returnValue = true; + } + RegCloseKey(hKey); + } + } + size = sizeof(keyName) - 1; + } + RegCloseKey(hTopKey); + } + } else { + lResult = + RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); + if (lResult == ERROR_SUCCESS) { + lResult = readFullStringValue(hKey, valueName, value); + if (lResult == ERROR_SUCCESS) + returnValue = true; + if (phValue) + phValue->clear(); + RegCloseKey(hKey); + } + } + return returnValue; +#endif // USE_WIN32 +} + +/// \brief Get Windows SDK installation directory. +bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major, + int &minor) const { + std::string sdkVersion; + // Try the Windows registry. + bool hasSDKDir = getSystemRegistryString( + "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", + "InstallationFolder", path, &sdkVersion); + if (!sdkVersion.empty()) + ::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor); + return hasSDKDir && !path.empty(); +} + +// Gets the library path required to link against the Windows SDK. +bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const { + std::string sdkPath; + int sdkMajor = 0; + int sdkMinor = 0; + + path.clear(); + if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor)) + return false; + + llvm::SmallString<128> libPath(sdkPath); + llvm::sys::path::append(libPath, "Lib"); + if (sdkMajor <= 7) { + switch (getArch()) { + // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. + case llvm::Triple::x86: + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(libPath, "x64"); + break; + case llvm::Triple::arm: + // It is not necessary to link against Windows SDK 7.x when targeting ARM. + return false; + default: + return false; + } + } else { + // Windows SDK 8.x installs libraries in a folder whose names depend on the + // version of the OS you're targeting. By default choose the newest, which + // usually corresponds to the version of the OS you've installed the SDK on. + const char *tests[] = {"winv6.3", "win8", "win7"}; + bool found = false; + for (const char *test : tests) { + llvm::SmallString<128> testPath(libPath); + llvm::sys::path::append(testPath, test); + if (llvm::sys::fs::exists(testPath.c_str())) { + libPath = testPath; + found = true; + break; + } + } + + if (!found) + return false; + + llvm::sys::path::append(libPath, "um"); + switch (getArch()) { + case llvm::Triple::x86: + llvm::sys::path::append(libPath, "x86"); + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(libPath, "x64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(libPath, "arm"); + break; + default: + return false; + } + } + + path = libPath.str(); + return true; +} + +// Get the location to use for Visual Studio binaries. The location priority +// is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on +// system (as reported by the registry). +bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath, + std::string &path) const { + path.clear(); + + SmallString<128> BinDir; + + // First check the environment variables that vsvars32.bat sets. + llvm::Optional<std::string> VcInstallDir = + llvm::sys::Process::GetEnv("VCINSTALLDIR"); + if (VcInstallDir.hasValue()) { + BinDir = VcInstallDir.getValue(); + llvm::sys::path::append(BinDir, "bin"); + } else { + // Next walk the PATH, trying to find a cl.exe in the path. If we find one, + // use that. However, make sure it's not clang's cl.exe. + llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH"); + if (OptPath.hasValue()) { + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; + SmallVector<StringRef, 8> PathSegments; + llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); + + for (StringRef PathSegment : PathSegments) { + if (PathSegment.empty()) + continue; + + SmallString<128> FilePath(PathSegment); + llvm::sys::path::append(FilePath, "cl.exe"); + if (llvm::sys::fs::can_execute(FilePath.c_str()) && + !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) { + // If we found it on the PATH, use it exactly as is with no + // modifications. + path = PathSegment; + return true; + } + } + } + + std::string installDir; + // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the + // registry then we have no choice but to fail. + if (!getVisualStudioInstallDir(installDir)) + return false; + + // Regardless of what binary we're ultimately trying to find, we make sure + // that this is a Visual Studio directory by checking for cl.exe. We use + // cl.exe instead of other binaries like link.exe because programs such as + // GnuWin32 also have a utility called link.exe, so cl.exe is the least + // ambiguous. + BinDir = installDir; + llvm::sys::path::append(BinDir, "VC", "bin"); + SmallString<128> ClPath(BinDir); + llvm::sys::path::append(ClPath, "cl.exe"); + + if (!llvm::sys::fs::can_execute(ClPath.c_str())) + return false; + } + + if (BinDir.empty()) + return false; + + switch (getArch()) { + case llvm::Triple::x86: + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(BinDir, "amd64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(BinDir, "arm"); + break; + default: + // Whatever this is, Visual Studio doesn't have a toolchain for it. + return false; + } + path = BinDir.str(); + return true; +} + +// Get Visual Studio installation directory. +bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const { + // First check the environment variables that vsvars32.bat sets. + const char *vcinstalldir = getenv("VCINSTALLDIR"); + if (vcinstalldir) { + path = vcinstalldir; + path = path.substr(0, path.find("\\VC")); + return true; + } + + std::string vsIDEInstallDir; + std::string vsExpressIDEInstallDir; + // Then try the windows registry. + bool hasVCDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", + "InstallDir", vsIDEInstallDir, nullptr); + if (hasVCDir && !vsIDEInstallDir.empty()) { + path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE")); + return true; + } + + bool hasVCExpressDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION", + "InstallDir", vsExpressIDEInstallDir, nullptr); + if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) { + path = vsExpressIDEInstallDir.substr( + 0, vsIDEInstallDir.find("\\Common7\\IDE")); + return true; + } + + // Try the environment. + const char *vs120comntools = getenv("VS120COMNTOOLS"); + const char *vs100comntools = getenv("VS100COMNTOOLS"); + const char *vs90comntools = getenv("VS90COMNTOOLS"); + const char *vs80comntools = getenv("VS80COMNTOOLS"); + + const char *vscomntools = nullptr; + + // Find any version we can + if (vs120comntools) + vscomntools = vs120comntools; + else if (vs100comntools) + vscomntools = vs100comntools; + else if (vs90comntools) + vscomntools = vs90comntools; + else if (vs80comntools) + vscomntools = vs80comntools; + + if (vscomntools && *vscomntools) { + const char *p = strstr(vscomntools, "\\Common7\\Tools"); + path = p ? std::string(vscomntools, p) : vscomntools; + return true; + } + return false; +} + +void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const std::string &folder, + const char *subfolder) const { + llvm::SmallString<128> path(folder); + llvm::sys::path::append(path, subfolder); + addSystemInclude(DriverArgs, CC1Args, path.str()); +} + +void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(getDriver().ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. + if (const char *cl_include_dir = getenv("INCLUDE")) { + SmallVector<StringRef, 8> Dirs; + StringRef(cl_include_dir) + .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + for (StringRef Dir : Dirs) + addSystemInclude(DriverArgs, CC1Args, Dir); + if (!Dirs.empty()) + return; + } + + std::string VSDir; + + // When built with access to the proper Windows APIs, try to actually find + // the correct include paths first. + if (getVisualStudioInstallDir(VSDir)) { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); + + std::string WindowsSDKDir; + int major, minor; + if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { + if (major >= 8) { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\shared"); + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\um"); + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include\\winrt"); + } else { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, + "include"); + } + } else { + addSystemInclude(DriverArgs, CC1Args, VSDir); + } + return; + } + + // As a fallback, select default install paths. + // FIXME: Don't guess drives and paths like this on Windows. + const StringRef Paths[] = { + "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", + "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", + "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", + "C:/Program Files/Microsoft Visual Studio 8/VC/include", + "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" + }; + addSystemIncludes(DriverArgs, CC1Args, Paths); +} + +void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // FIXME: There should probably be logic here to find libc++ on Windows. +} diff --git a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp index 484ce16..1f5d62f 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Multilib.cpp @@ -37,7 +37,7 @@ static void normalizePathSegment(std::string &Segment) { // Prune trailing "/" or "./" while (1) { - StringRef last = *--path::end(seg); + StringRef last = path::filename(seg); if (last != ".") break; seg = path::parent_path(seg); diff --git a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp index 155e53b..7ae2708 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Phases.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Phases.cpp @@ -18,6 +18,7 @@ const char *phases::getPhaseName(ID Id) { case Preprocess: return "preprocessor"; case Precompile: return "precompiler"; case Compile: return "compiler"; + case Backend: return "backend"; case Assemble: return "assembler"; case Link: return "linker"; } diff --git a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp index b64f027..bd7bc21 100644 --- a/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp @@ -21,93 +21,263 @@ using namespace clang::driver; using namespace llvm::opt; +namespace { +/// Assign ordinals to possible values of -fsanitize= flag. +/// We use the ordinal values as bit positions within \c SanitizeKind. +enum SanitizeOrdinal { +#define SANITIZER(NAME, ID) SO_##ID, +#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group, +#include "clang/Basic/Sanitizers.def" + SO_Count +}; + +/// Represents a set of sanitizer kinds. It is also used to define: +/// 1) set of sanitizers each sanitizer group expands into. +/// 2) set of sanitizers sharing a specific property (e.g. +/// all sanitizers with zero-base shadow). +enum SanitizeKind { +#define SANITIZER(NAME, ID) ID = 1 << SO_##ID, +#define SANITIZER_GROUP(NAME, ID, ALIAS) \ +ID = ALIAS, ID##Group = 1 << SO_##ID##Group, +#include "clang/Basic/Sanitizers.def" + NeedsUbsanRt = Undefined | Integer, + NotAllowedWithTrap = Vptr, + RequiresPIE = Memory | DataFlow, + NeedsUnwindTables = Address | Thread | Memory | DataFlow, + SupportsCoverage = Address | Memory | Leak | Undefined | Integer, + RecoverableByDefault = Undefined | Integer, + Unrecoverable = Address | Unreachable | Return, + LegacyFsanitizeRecoverMask = Undefined | Integer +}; +} + +/// Returns true if set of \p Sanitizers contain at least one sanitizer from +/// \p Kinds. +static bool hasOneOf(const clang::SanitizerSet &Sanitizers, unsigned Kinds) { +#define SANITIZER(NAME, ID) \ + if (Sanitizers.has(clang::SanitizerKind::ID) && (Kinds & ID)) \ + return true; +#include "clang/Basic/Sanitizers.def" + return false; +} + +/// Adds all sanitizers from \p Kinds to \p Sanitizers. +static void addAllOf(clang::SanitizerSet &Sanitizers, unsigned Kinds) { +#define SANITIZER(NAME, ID) \ + if (Kinds & ID) \ + Sanitizers.set(clang::SanitizerKind::ID, true); +#include "clang/Basic/Sanitizers.def" +} + +static unsigned toSanitizeKind(clang::SanitizerKind K) { +#define SANITIZER(NAME, ID) \ + if (K == clang::SanitizerKind::ID) \ + return ID; +#include "clang/Basic/Sanitizers.def" + llvm_unreachable("Invalid SanitizerKind!"); +} + +/// Parse a single value from a -fsanitize= or -fno-sanitize= value list. +/// Returns a member of the \c SanitizeKind enumeration, or \c 0 +/// if \p Value is not known. +static unsigned parseValue(const char *Value); + +/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any +/// invalid components. Returns OR of members of \c SanitizeKind enumeration. +static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A, + bool DiagnoseErrors); + +/// Produce an argument string from ArgList \p Args, which shows how it +/// provides some sanitizer kind from \p Mask. For example, the argument list +/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt +/// would produce "-fsanitize=vptr". +static std::string lastArgumentForMask(const Driver &D, + const llvm::opt::ArgList &Args, + unsigned Mask); + +static std::string lastArgumentForKind(const Driver &D, + const llvm::opt::ArgList &Args, + clang::SanitizerKind K) { + return lastArgumentForMask(D, Args, toSanitizeKind(K)); +} + +/// Produce an argument string from argument \p A, which shows how it provides +/// a value in \p Mask. For instance, the argument +/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce +/// "-fsanitize=alignment". +static std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask); + +/// Produce a string containing comma-separated names of sanitizers in \p +/// Sanitizers set. +static std::string toString(const clang::SanitizerSet &Sanitizers); + +/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers +/// this group enables. +static unsigned expandGroups(unsigned Kinds); + +static unsigned getToolchainUnsupportedKinds(const ToolChain &TC) { + bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD; + bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux; + bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86; + bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64; + + unsigned Unsupported = 0; + if (!(IsLinux && IsX86_64)) { + Unsupported |= Memory | DataFlow; + } + if (!((IsLinux || IsFreeBSD) && IsX86_64)) { + Unsupported |= Thread; + } + if (!(IsLinux && (IsX86 || IsX86_64))) { + Unsupported |= Function; + } + return Unsupported; +} + +bool SanitizerArgs::needsUbsanRt() const { + return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt); +} + +bool SanitizerArgs::requiresPIE() const { + return AsanZeroBaseShadow || hasOneOf(Sanitizers, RequiresPIE); +} + +bool SanitizerArgs::needsUnwindTables() const { + return hasOneOf(Sanitizers, NeedsUnwindTables); +} + void SanitizerArgs::clear() { - Kind = 0; + Sanitizers.clear(); + RecoverableSanitizers.clear(); BlacklistFile = ""; + SanitizeCoverage = 0; MsanTrackOrigins = 0; + AsanFieldPadding = 0; AsanZeroBaseShadow = false; UbsanTrapOnError = false; AsanSharedRuntime = false; -} - -SanitizerArgs::SanitizerArgs() { - clear(); + LinkCXXRuntimes = false; } SanitizerArgs::SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args) { clear(); - unsigned AllAdd = 0; // All kinds of sanitizers that were turned on - // at least once (possibly, disabled further). unsigned AllRemove = 0; // During the loop below, the accumulated set of // sanitizers disabled by the current sanitizer // argument or any argument after it. unsigned DiagnosedKinds = 0; // All Kinds we have diagnosed up to now. // Used to deduplicate diagnostics. + unsigned Kinds = 0; + unsigned NotSupported = getToolchainUnsupportedKinds(TC); const Driver &D = TC.getDriver(); for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend(); I != E; ++I) { - unsigned Add, Remove; - if (!parse(D, Args, *I, Add, Remove, true)) - continue; - (*I)->claim(); - - AllAdd |= expandGroups(Add); - AllRemove |= expandGroups(Remove); - - // Avoid diagnosing any sanitizer which is disabled later. - Add &= ~AllRemove; - // At this point we have not expanded groups, so any unsupported sanitizers - // in Add are those which have been explicitly enabled. Diagnose them. - Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/true, - DiagnosedKinds); - Add = expandGroups(Add); - // Group expansion may have enabled a sanitizer which is disabled later. - Add &= ~AllRemove; - // Silently discard any unsupported sanitizers implicitly enabled through - // group expansion. - Add = filterUnsupportedKinds(TC, Add, Args, *I, /*DiagnoseErrors=*/false, - DiagnosedKinds); - - Kind |= Add; + const auto *Arg = *I; + if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { + Arg->claim(); + unsigned Add = parseArgValues(D, Arg, true); + + // Avoid diagnosing any sanitizer which is disabled later. + Add &= ~AllRemove; + // At this point we have not expanded groups, so any unsupported + // sanitizers in Add are those which have been explicitly enabled. + // Diagnose them. + if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) { + // Only diagnose the new kinds. + std::string Desc = describeSanitizeArg(*I, KindsToDiagnose); + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Desc << TC.getTriple().str(); + DiagnosedKinds |= KindsToDiagnose; + } + Add &= ~NotSupported; + + Add = expandGroups(Add); + // Group expansion may have enabled a sanitizer which is disabled later. + Add &= ~AllRemove; + // Silently discard any unsupported sanitizers implicitly enabled through + // group expansion. + Add &= ~NotSupported; + + Kinds |= Add; + } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { + Arg->claim(); + unsigned Remove = parseArgValues(D, Arg, true); + AllRemove |= expandGroups(Remove); + } + } + addAllOf(Sanitizers, Kinds); + + // Parse -f(no-)?sanitize-recover flags. + unsigned RecoverableKinds = RecoverableByDefault; + unsigned DiagnosedUnrecoverableKinds = 0; + for (const auto *Arg : Args) { + if (Arg->getOption().matches(options::OPT_fsanitize_recover)) { + // FIXME: Add deprecation notice, and then remove this flag. + RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask); + Arg->claim(); + } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) { + // FIXME: Add deprecation notice, and then remove this flag. + RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask); + Arg->claim(); + } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { + unsigned Add = parseArgValues(D, Arg, true); + // Report error if user explicitly tries to recover from unrecoverable + // sanitizer. + if (unsigned KindsToDiagnose = + Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) { + SanitizerSet SetToDiagnose; + addAllOf(SetToDiagnose, KindsToDiagnose); + D.Diag(diag::err_drv_unsupported_option_argument) + << Arg->getOption().getName() << toString(SetToDiagnose); + DiagnosedUnrecoverableKinds |= KindsToDiagnose; + } + RecoverableKinds |= expandGroups(Add); + Arg->claim(); + } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) { + RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true)); + Arg->claim(); + } } + RecoverableKinds &= Kinds; + RecoverableKinds &= ~Unrecoverable; + addAllOf(RecoverableSanitizers, RecoverableKinds); UbsanTrapOnError = Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, options::OPT_fno_sanitize_undefined_trap_on_error, false); // Warn about undefined sanitizer options that require runtime support. - if (UbsanTrapOnError && notAllowedWithTrap()) { - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NotAllowedWithTrap) + if (UbsanTrapOnError && hasOneOf(Sanitizers, NotAllowedWithTrap)) { + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForMask(D, Args, NotAllowedWithTrap) << "-fsanitize-undefined-trap-on-error"; } - // Only one runtime library can be used at once. - bool NeedsAsan = needsAsanRt(); - bool NeedsTsan = needsTsanRt(); - bool NeedsMsan = needsMsanRt(); - bool NeedsLsan = needsLeakDetection(); + // Check for incompatible sanitizers. + bool NeedsAsan = Sanitizers.has(SanitizerKind::Address); + bool NeedsTsan = Sanitizers.has(SanitizerKind::Thread); + bool NeedsMsan = Sanitizers.has(SanitizerKind::Memory); + bool NeedsLsan = Sanitizers.has(SanitizerKind::Leak); if (NeedsAsan && NeedsTsan) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NeedsAsanRt) - << lastArgumentForKind(D, Args, NeedsTsanRt); + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, SanitizerKind::Address) + << lastArgumentForKind(D, Args, SanitizerKind::Thread); if (NeedsAsan && NeedsMsan) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NeedsAsanRt) - << lastArgumentForKind(D, Args, NeedsMsanRt); + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, SanitizerKind::Address) + << lastArgumentForKind(D, Args, SanitizerKind::Memory); if (NeedsTsan && NeedsMsan) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NeedsTsanRt) - << lastArgumentForKind(D, Args, NeedsMsanRt); + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, SanitizerKind::Thread) + << lastArgumentForKind(D, Args, SanitizerKind::Memory); if (NeedsLsan && NeedsTsan) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NeedsLeakDetection) - << lastArgumentForKind(D, Args, NeedsTsanRt); + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, SanitizerKind::Leak) + << lastArgumentForKind(D, Args, SanitizerKind::Thread); if (NeedsLsan && NeedsMsan) - D.Diag(diag::err_drv_argument_not_allowed_with) - << lastArgumentForKind(D, Args, NeedsLeakDetection) - << lastArgumentForKind(D, Args, NeedsMsanRt); + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << lastArgumentForKind(D, Args, SanitizerKind::Leak) + << lastArgumentForKind(D, Args, SanitizerKind::Memory); // 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 @@ -124,19 +294,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, std::unique_ptr<llvm::SpecialCaseList> SCL( llvm::SpecialCaseList::create(BLPath, BLError)); if (!SCL.get()) - D.Diag(diag::err_drv_malformed_sanitizer_blacklist) << BLError; + D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError; else BlacklistFile = BLPath; } else { - D.Diag(diag::err_drv_no_such_file) << BLPath; + D.Diag(clang::diag::err_drv_no_such_file) << BLPath; } } } else { // If no -fsanitize-blacklist option is specified, try to look up for // blacklist in the resource directory. std::string BLPath; - if (getDefaultBlacklistForKind(D, Kind, BLPath) && - llvm::sys::fs::exists(BLPath)) + if (getDefaultBlacklist(D, BLPath) && llvm::sys::fs::exists(BLPath)) BlacklistFile = BLPath; } @@ -155,32 +324,85 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, StringRef S = A->getValue(); if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 || MsanTrackOrigins > 2) { - D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << S; + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; } } } } + // Parse -fsanitize-coverage=N. Currently one of asan/msan/lsan is required. + if (hasOneOf(Sanitizers, SupportsCoverage)) { + if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) { + StringRef S = A->getValue(); + // Legal values are 0..4. + if (S.getAsInteger(0, SanitizeCoverage) || SanitizeCoverage < 0 || + SanitizeCoverage > 4) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } + } + if (NeedsAsan) { AsanSharedRuntime = Args.hasArg(options::OPT_shared_libasan) || (TC.getTriple().getEnvironment() == llvm::Triple::Android); AsanZeroBaseShadow = (TC.getTriple().getEnvironment() == llvm::Triple::Android); + if (Arg *A = + Args.getLastArg(options::OPT_fsanitize_address_field_padding)) { + StringRef S = A->getValue(); + // Legal values are 0 and 1, 2, but in future we may add more levels. + if (S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 || + AsanFieldPadding > 2) { + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + } + } + + if (Arg *WindowsDebugRTArg = + Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT, + options::OPT__SLASH_MDd, options::OPT__SLASH_MD, + options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) { + switch (WindowsDebugRTArg->getOption().getID()) { + case options::OPT__SLASH_MTd: + case options::OPT__SLASH_MDd: + case options::OPT__SLASH_LDd: + D.Diag(clang::diag::err_drv_argument_not_allowed_with) + << WindowsDebugRTArg->getAsString(Args) + << lastArgumentForKind(D, Args, SanitizerKind::Address); + D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime); + } + } + } + + // Parse -link-cxx-sanitizer flag. + LinkCXXRuntimes = + Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX(); +} + +static std::string toString(const clang::SanitizerSet &Sanitizers) { + std::string Res; +#define SANITIZER(NAME, ID) \ + if (Sanitizers.has(clang::SanitizerKind::ID)) { \ + if (!Res.empty()) \ + Res += ","; \ + Res += NAME; \ } +#include "clang/Basic/Sanitizers.def" + return Res; } void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { - if (!Kind) + if (Sanitizers.empty()) return; - SmallString<256> SanitizeOpt("-fsanitize="); -#define SANITIZER(NAME, ID) \ - if (Kind & ID) \ - SanitizeOpt += NAME ","; -#include "clang/Basic/Sanitizers.def" - SanitizeOpt.pop_back(); - CmdArgs.push_back(Args.MakeArgString(SanitizeOpt)); + CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers))); + + if (!RecoverableSanitizers.empty()) + CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" + + toString(RecoverableSanitizers))); + + if (UbsanTrapOnError) + CmdArgs.push_back("-fsanitize-undefined-trap-on-error"); + if (!BlacklistFile.empty()) { SmallString<64> BlacklistOpt("-fsanitize-blacklist="); BlacklistOpt += BlacklistFile; @@ -190,13 +412,38 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args, if (MsanTrackOrigins) CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" + llvm::utostr(MsanTrackOrigins))); - + if (AsanFieldPadding) + CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" + + llvm::utostr(AsanFieldPadding))); + if (SanitizeCoverage) + CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage=" + + llvm::utostr(SanitizeCoverage))); // Workaround for PR16386. - if (needsMsanRt()) + if (Sanitizers.has(SanitizerKind::Memory)) CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new")); } -unsigned SanitizerArgs::parse(const char *Value) { +bool SanitizerArgs::getDefaultBlacklist(const Driver &D, std::string &BLPath) { + const char *BlacklistFile = nullptr; + if (Sanitizers.has(SanitizerKind::Address)) + BlacklistFile = "asan_blacklist.txt"; + else if (Sanitizers.has(SanitizerKind::Memory)) + BlacklistFile = "msan_blacklist.txt"; + else if (Sanitizers.has(SanitizerKind::Thread)) + BlacklistFile = "tsan_blacklist.txt"; + else if (Sanitizers.has(SanitizerKind::DataFlow)) + BlacklistFile = "dfsan_abilist.txt"; + + if (BlacklistFile) { + SmallString<64> Path(D.ResourceDir); + llvm::sys::path::append(Path, BlacklistFile); + BLPath = Path.str(); + return true; + } + return false; +} + +unsigned parseValue(const char *Value) { unsigned ParsedKind = llvm::StringSwitch<SanitizeKind>(Value) #define SANITIZER(NAME, ID) .Case(NAME, ID) #define SANITIZER_GROUP(NAME, ID, ALIAS) .Case(NAME, ID##Group) @@ -205,107 +452,65 @@ unsigned SanitizerArgs::parse(const char *Value) { return ParsedKind; } -unsigned SanitizerArgs::expandGroups(unsigned Kinds) { +unsigned expandGroups(unsigned Kinds) { #define SANITIZER(NAME, ID) #define SANITIZER_GROUP(NAME, ID, ALIAS) if (Kinds & ID##Group) Kinds |= ID; #include "clang/Basic/Sanitizers.def" return Kinds; } -void SanitizerArgs::filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds, - unsigned Mask, - const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - bool DiagnoseErrors, - unsigned &DiagnosedKinds) { - unsigned MaskedKinds = Kinds & Mask; - if (!MaskedKinds) - return; - Kinds &= ~Mask; - // Do we have new kinds to diagnose? - if (DiagnoseErrors && (DiagnosedKinds & MaskedKinds) != MaskedKinds) { - // Only diagnose the new kinds. - std::string Desc = - describeSanitizeArg(Args, A, MaskedKinds & ~DiagnosedKinds); - TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target) - << Desc << TC.getTriple().str(); - DiagnosedKinds |= MaskedKinds; - } -} - -unsigned SanitizerArgs::filterUnsupportedKinds(const ToolChain &TC, - unsigned Kinds, - const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - bool DiagnoseErrors, - unsigned &DiagnosedKinds) { - bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux; - bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86; - bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64; - if (!(IsLinux && IsX86_64)) { - filterUnsupportedMask(TC, Kinds, Thread | Memory | DataFlow, Args, A, - DiagnoseErrors, DiagnosedKinds); - } - if (!(IsLinux && (IsX86 || IsX86_64))) { - filterUnsupportedMask(TC, Kinds, Function, Args, A, DiagnoseErrors, - DiagnosedKinds); - } - return Kinds; -} - -unsigned SanitizerArgs::parse(const Driver &D, const llvm::opt::Arg *A, - bool DiagnoseErrors) { - unsigned Kind = 0; +unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A, + bool DiagnoseErrors) { + assert((A->getOption().matches(options::OPT_fsanitize_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_EQ) || + A->getOption().matches(options::OPT_fsanitize_recover_EQ) || + A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) && + "Invalid argument in parseArgValues!"); + unsigned Kinds = 0; for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) { - if (unsigned K = parse(A->getValue(I))) - Kind |= K; - else if (DiagnoseErrors) - D.Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(I); - } - return Kind; -} + const char *Value = A->getValue(I); + unsigned Kind; + // Special case: don't accept -fsanitize=all. + if (A->getOption().matches(options::OPT_fsanitize_EQ) && + 0 == strcmp("all", Value)) + Kind = 0; + else + Kind = parseValue(Value); -bool SanitizerArgs::parse(const Driver &D, const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, unsigned &Add, - unsigned &Remove, bool DiagnoseErrors) { - Add = 0; - Remove = 0; - if (A->getOption().matches(options::OPT_fsanitize_EQ)) { - Add = parse(D, A, DiagnoseErrors); - } else if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) { - Remove = parse(D, A, DiagnoseErrors); - } else { - // Flag is not relevant to sanitizers. - return false; + if (Kind) + Kinds |= Kind; + else if (DiagnoseErrors) + D.Diag(clang::diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Value; } - return true; + return Kinds; } -std::string SanitizerArgs::lastArgumentForKind(const Driver &D, - const llvm::opt::ArgList &Args, - unsigned Kind) { +std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, + unsigned Mask) { for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend(); I != E; ++I) { - unsigned Add, Remove; - if (parse(D, Args, *I, Add, Remove, false) && - (expandGroups(Add) & Kind)) - return describeSanitizeArg(Args, *I, Kind); - Kind &= ~Remove; + const auto *Arg = *I; + if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) { + unsigned AddKinds = expandGroups(parseArgValues(D, Arg, false)); + if (AddKinds & Mask) + return describeSanitizeArg(Arg, Mask); + } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) { + unsigned RemoveKinds = expandGroups(parseArgValues(D, Arg, false)); + Mask &= ~RemoveKinds; + } } llvm_unreachable("arg list didn't provide expected value"); } -std::string SanitizerArgs::describeSanitizeArg(const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - unsigned Mask) { - if (!A->getOption().matches(options::OPT_fsanitize_EQ)) - return A->getAsString(Args); +std::string describeSanitizeArg(const llvm::opt::Arg *A, unsigned Mask) { + assert(A->getOption().matches(options::OPT_fsanitize_EQ) + && "Invalid argument in describeSanitizerArg!"); std::string Sanitizers; for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) { - if (expandGroups(parse(A->getValue(I))) & Mask) { + if (expandGroups(parseValue(A->getValue(I))) & Mask) { if (!Sanitizers.empty()) Sanitizers += ","; Sanitizers += A->getValue(I); @@ -315,24 +520,3 @@ std::string SanitizerArgs::describeSanitizeArg(const llvm::opt::ArgList &Args, assert(!Sanitizers.empty() && "arg didn't provide expected value"); return "-fsanitize=" + Sanitizers; } - -bool SanitizerArgs::getDefaultBlacklistForKind(const Driver &D, unsigned Kind, - std::string &BLPath) { - const char *BlacklistFile = nullptr; - if (Kind & NeedsAsanRt) - BlacklistFile = "asan_blacklist.txt"; - else if (Kind & NeedsMsanRt) - BlacklistFile = "msan_blacklist.txt"; - else if (Kind & NeedsTsanRt) - BlacklistFile = "tsan_blacklist.txt"; - else if (Kind & NeedsDfsanRt) - BlacklistFile = "dfsan_abilist.txt"; - - if (BlacklistFile) { - SmallString<64> Path(D.ResourceDir); - llvm::sys::path::append(Path, BlacklistFile); - BLPath = Path.str(); - return true; - } - return false; -} diff --git a/contrib/llvm/tools/clang/lib/Driver/Tool.cpp b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp index b93864f..7142e82 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tool.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tool.cpp @@ -11,11 +11,13 @@ using namespace clang::driver; -Tool::Tool(const char *_Name, const char *_ShortName, - const ToolChain &TC) : Name(_Name), ShortName(_ShortName), - TheToolChain(TC) -{ -} +Tool::Tool(const char *_Name, const char *_ShortName, const ToolChain &TC, + ResponseFileSupport _ResponseSupport, + llvm::sys::WindowsEncodingMethod _ResponseEncoding, + const char *_ResponseFlag) + : Name(_Name), ShortName(_ShortName), TheToolChain(TC), + ResponseSupport(_ResponseSupport), ResponseEncoding(_ResponseEncoding), + ResponseFlag(_ResponseFlag) {} Tool::~Tool() { } diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 4f90d08..2bcfecf 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -27,8 +27,13 @@ using namespace clang; using namespace llvm::opt; ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, - const ArgList &A) - : D(D), Triple(T), Args(A) { + const ArgList &Args) + : D(D), Triple(T), Args(Args) { + if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) + if (!isThreadModelSupported(A->getValue())) + D.Diag(diag::err_drv_invalid_thread_model_for_target) + << A->getValue() + << A->getAsString(Args); } ToolChain::~ToolChain() { @@ -50,7 +55,7 @@ const SanitizerArgs& ToolChain::getSanitizerArgs() const { return *SanitizerArguments.get(); } -std::string ToolChain::getDefaultUniversalArchName() const { +StringRef ToolChain::getDefaultUniversalArchName() const { // In universal driver terms, the arch name accepted by -arch isn't exactly // the same as the ones that appear in the triple. Roughly speaking, this is // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the @@ -124,6 +129,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::AnalyzeJobClass: case Action::MigrateJobClass: case Action::VerifyPCHJobClass: + case Action::BackendJobClass: return getClang(); } @@ -201,6 +207,19 @@ ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { VersionTuple()); } +bool ToolChain::isThreadModelSupported(const StringRef Model) const { + if (Model == "single") { + // FIXME: 'single' is only supported on ARM so far. + return Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::armeb || + Triple.getArch() == llvm::Triple::thumb || + Triple.getArch() == llvm::Triple::thumbeb; + } else if (Model == "posix") + return true; + + return false; +} + std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, types::ID InputType) const { switch (getTriple().getArch()) { @@ -221,6 +240,17 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, } return Triple.getTriple(); } + case llvm::Triple::aarch64: { + llvm::Triple Triple = getTriple(); + if (!Triple.isOSBinFormatMachO()) + return getTripleString(); + + // FIXME: older versions of ld64 expect the "arm64" component in the actual + // triple string and query it to determine whether an LTO file can be + // handled. Remove this when we don't care any more. + Triple.setArchName("arm64"); + return Triple.getTriple(); + } case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index b46f69d..4d97ab3 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -133,11 +133,11 @@ 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", "cortex-a9-mp", "armv7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "armv7") + .Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "armv7") .Cases("cortex-r4", "cortex-r5", "armv7r") .Case("cortex-m3", "armv7m") - .Case("cortex-m4", "armv7em") + .Cases("cortex-m4", "cortex-m7", "armv7em") .Case("swift", "armv7s") .Default(nullptr); } @@ -147,7 +147,7 @@ static bool isSoftFloatABI(const ArgList &Args) { 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")); @@ -156,7 +156,10 @@ static bool isSoftFloatABI(const ArgList &Args) { StringRef MachO::getMachOArchName(const ArgList &Args) const { switch (getTriple().getArch()) { default: - return getArchName(); + return getDefaultUniversalArchName(); + + case llvm::Triple::aarch64: + return "arm64"; case llvm::Triple::thumb: case llvm::Triple::arm: { @@ -288,17 +291,37 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, } void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, - StringRef DarwinStaticLib, bool AlwaysLink, - bool IsEmbedded) const { - SmallString<128> P(getDriver().ResourceDir); - llvm::sys::path::append(P, "lib", IsEmbedded ? "macho_embedded" : "darwin", - DarwinStaticLib); + StringRef DarwinLibName, bool AlwaysLink, + bool IsEmbedded, bool AddRPath) const { + SmallString<128> Dir(getDriver().ResourceDir); + llvm::sys::path::append(Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin"); + + SmallString<128> P(Dir); + llvm::sys::path::append(P, DarwinLibName); // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build (unless // we explicitly force linking with this library). if (AlwaysLink || llvm::sys::fs::exists(P.str())) CmdArgs.push_back(Args.MakeArgString(P.str())); + + // Adding the rpaths might negatively interact when other rpaths are involved, + // so we should make sure we add the rpaths last, after all user-specified + // rpaths. This is currently true from this place, but we need to be + // careful if this function is ever called before user's rpaths are emitted. + if (AddRPath) { + assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library"); + + // Add @executable_path to rpath to support having the dylib copied with + // the executable. + CmdArgs.push_back("-rpath"); + CmdArgs.push_back("@executable_path"); + + // Add the path to the resource dir to rpath to support using the dylib + // from the default location without copying. + CmdArgs.push_back("-rpath"); + CmdArgs.push_back(Args.MakeArgString(Dir.str())); + } } void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, @@ -330,7 +353,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, } // If we are building profile support, link that library in. - if (Args.hasArg(options::OPT_fprofile_arcs) || + if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false) || Args.hasArg(options::OPT_fprofile_generate) || Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fcreate_profile) || @@ -375,12 +399,14 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, if (isTargetMacOS()) { AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_osx_dynamic.dylib", - true); + /*AlwaysLink*/ true, /*IsEmbedded*/ false, + /*AddRPath*/ true); } else { if (isTargetIOSSimulator()) { AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_iossim_dynamic.dylib", - true); + /*AlwaysLink*/ true, /*IsEmbedded*/ false, + /*AddRPath*/ true); } } } @@ -396,8 +422,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // it never went into the SDK. // Linking against libgcc_s.1 isn't needed for iOS 5.0+ if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() && - (getTriple().getArch() != llvm::Triple::arm64 && - getTriple().getArch() != llvm::Triple::aarch64)) + getTriple().getArch() != llvm::Triple::aarch64) CmdArgs.push_back("-lgcc_s.1"); // We currently always need a static runtime library for iOS. @@ -453,31 +478,21 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ); Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); - Arg *iOSSimVersion = Args.getLastArg( - options::OPT_mios_simulator_version_min_EQ); - if (OSXVersion && (iOSVersion || iOSSimVersion)) { + if (OSXVersion && iOSVersion) { getDriver().Diag(diag::err_drv_argument_not_allowed_with) << OSXVersion->getAsString(Args) - << (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args); - iOSVersion = iOSSimVersion = nullptr; - } else if (iOSVersion && iOSSimVersion) { - getDriver().Diag(diag::err_drv_argument_not_allowed_with) - << iOSVersion->getAsString(Args) - << iOSSimVersion->getAsString(Args); - iOSSimVersion = nullptr; - } else if (!OSXVersion && !iOSVersion && !iOSSimVersion) { + << iOSVersion->getAsString(Args); + iOSVersion = nullptr; + } else if (!OSXVersion && !iOSVersion) { // If no deployment target was specified on the command line, check for // environment defines. StringRef OSXTarget; StringRef iOSTarget; - StringRef iOSSimTarget; if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET")) OSXTarget = env; if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET")) iOSTarget = env; - if (char *env = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET")) - iOSSimTarget = env; // If no '-miphoneos-version-min' specified on the command line and // IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default @@ -500,23 +515,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { MachOArchName == "arm64")) iOSTarget = iOSVersionMin; - // Handle conflicting deployment targets - // - // FIXME: Don't hardcode default here. - - // Do not allow conflicts with the iOS simulator target. - if (!iOSSimTarget.empty() && (!OSXTarget.empty() || !iOSTarget.empty())) { - getDriver().Diag(diag::err_drv_conflicting_deployment_targets) - << "IOS_SIMULATOR_DEPLOYMENT_TARGET" - << (!OSXTarget.empty() ? "MACOSX_DEPLOYMENT_TARGET" : - "IPHONEOS_DEPLOYMENT_TARGET"); - } - // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. if (!OSXTarget.empty() && !iOSTarget.empty()) { if (getTriple().getArch() == llvm::Triple::arm || - getTriple().getArch() == llvm::Triple::arm64 || getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::thumb) OSXTarget = ""; @@ -532,11 +534,6 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget); Args.append(iOSVersion); - } else if (!iOSSimTarget.empty()) { - const Option O = Opts.getOption( - options::OPT_mios_simulator_version_min_EQ); - iOSSimVersion = Args.MakeJoinedArg(nullptr, O, iOSSimTarget); - Args.append(iOSSimVersion); } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && MachOArchName != "armv7em") { // Otherwise, assume we are targeting OS X. @@ -551,43 +548,30 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Platform = MacOS; else if (iOSVersion) Platform = IPhoneOS; - else if (iOSSimVersion) - Platform = IPhoneOSSimulator; else llvm_unreachable("Unable to infer Darwin variant"); - // Reject invalid architecture combinations. - if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 && - getTriple().getArch() != llvm::Triple::x86_64)) { - getDriver().Diag(diag::err_drv_invalid_arch_for_deployment_target) - << getTriple().getArchName() << iOSSimVersion->getAsString(Args); - } - // Set the tool chain target information. unsigned Major, Minor, Micro; bool HadExtra; if (Platform == MacOS) { - assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!"); + assert(!iOSVersion && "Unknown target platform!"); if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << OSXVersion->getAsString(Args); - } else if (Platform == IPhoneOS || Platform == IPhoneOSSimulator) { - const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion; - assert(Version && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor, + } else if (Platform == IPhoneOS) { + assert(iOSVersion && "Unknown target platform!"); + if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) - << Version->getAsString(Args); + << iOSVersion->getAsString(Args); } else llvm_unreachable("unknown kind of Darwin platform"); - // In GCC, the simulator historically was treated as being OS X in some - // contexts, like determining the link logic, despite generally being called - // with an iOS deployment target. For compatibility, we detect the - // simulator as iOS + x86, and treat it differently in a few contexts. + // Recognize iOS targets with an x86 architecture as the iOS simulator. if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64)) Platform = IPhoneOSSimulator; @@ -653,7 +637,6 @@ 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"); @@ -919,9 +902,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // FIXME: It would be far better to avoid inserting those -static arguments, // but we can't check the deployment target in the translation code until // it is set here. - if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0) && - getTriple().getArch() != llvm::Triple::arm64 && - getTriple().getArch() != llvm::Triple::aarch64) { + if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) { for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) { Arg *A = *it; ++it; @@ -988,7 +969,6 @@ bool MachO::isPIEDefault() const { bool MachO::isPICDefaultForced() const { return (getArch() == llvm::Triple::x86_64 || - getArch() == llvm::Triple::arm64 || getArch() == llvm::Triple::aarch64); } @@ -1001,14 +981,7 @@ 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)) + if (isTargetIOSSimulator()) CmdArgs.push_back("-ios_simulator_version_min"); else if (isTargetIOSBased()) CmdArgs.push_back("-iphoneos_version_min"); @@ -1078,8 +1051,7 @@ void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args, if (isTargetIOSSimulator()) { ; // iOS simulator does not need crt1.o. } else if (isTargetIPhoneOS()) { - if (getArch() == llvm::Triple::arm64 || - getArch() == llvm::Triple::aarch64) + if (getArch() == llvm::Triple::aarch64) ; // iOS does not need any crt1 files for arm64 else if (isIPhoneOSVersionLT(3, 1)) CmdArgs.push_back("-lcrt1.o"); @@ -1222,8 +1194,8 @@ Generic_GCC::GCCInstallationDetector::init( // The library directories which may contain GCC installations. SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs; // The compatible GCC triples for this particular architecture. - SmallVector<StringRef, 10> CandidateTripleAliases; - SmallVector<StringRef, 10> CandidateBiarchTripleAliases; + SmallVector<StringRef, 16> CandidateTripleAliases; + SmallVector<StringRef, 16> CandidateBiarchTripleAliases; CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs, CandidateTripleAliases, CandidateBiarchLibDirs, CandidateBiarchTripleAliases); @@ -1397,176 +1369,116 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { "s390x-suse-linux", "s390x-redhat-linux" }; + using std::begin; + using std::end; + switch (TargetTriple.getArch()) { - case llvm::Triple::arm64: case llvm::Triple::aarch64: - LibDirs.append(AArch64LibDirs, - AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs)); - TripleAliases.append(AArch64Triples, - AArch64Triples + llvm::array_lengthof(AArch64Triples)); - BiarchLibDirs.append(AArch64LibDirs, - AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs)); - BiarchTripleAliases.append( - AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples)); + LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs)); + TripleAliases.append(begin(AArch64Triples), end(AArch64Triples)); + BiarchLibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs)); + BiarchTripleAliases.append(begin(AArch64Triples), end(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)); + LibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs)); + TripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples)); + BiarchLibDirs.append(begin(AArch64beLibDirs), end(AArch64beLibDirs)); + BiarchTripleAliases.append(begin(AArch64beTriples), end(AArch64beTriples)); break; case llvm::Triple::arm: case llvm::Triple::thumb: - LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); + LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs)); if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { - TripleAliases.append(ARMHFTriples, - ARMHFTriples + llvm::array_lengthof(ARMHFTriples)); + TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples)); } else { - TripleAliases.append(ARMTriples, - ARMTriples + llvm::array_lengthof(ARMTriples)); + TripleAliases.append(begin(ARMTriples), end(ARMTriples)); } break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - LibDirs.append(ARMebLibDirs, ARMebLibDirs + llvm::array_lengthof(ARMebLibDirs)); + LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs)); if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { - TripleAliases.append(ARMebHFTriples, - ARMebHFTriples + llvm::array_lengthof(ARMebHFTriples)); + TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples)); } else { - TripleAliases.append(ARMebTriples, - ARMebTriples + llvm::array_lengthof(ARMebTriples)); + TripleAliases.append(begin(ARMebTriples), end(ARMebTriples)); } break; case llvm::Triple::x86_64: - LibDirs.append(X86_64LibDirs, - X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); - TripleAliases.append(X86_64Triples, - X86_64Triples + llvm::array_lengthof(X86_64Triples)); - // x32 is always available when x86_64 is available, so adding it as secondary - // arch with x86_64 triples + LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs)); + TripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); + // x32 is always available when x86_64 is available, so adding it as + // secondary arch with x86_64 triples if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32) { - BiarchLibDirs.append(X32LibDirs, - X32LibDirs + llvm::array_lengthof(X32LibDirs)); - BiarchTripleAliases.append(X86_64Triples, - X86_64Triples + llvm::array_lengthof(X86_64Triples)); + BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs)); + BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); } else { - BiarchLibDirs.append(X86LibDirs, - X86LibDirs + llvm::array_lengthof(X86LibDirs)); - BiarchTripleAliases.append(X86Triples, - X86Triples + llvm::array_lengthof(X86Triples)); + BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs)); + BiarchTripleAliases.append(begin(X86Triples), end(X86Triples)); } break; case llvm::Triple::x86: - LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); - TripleAliases.append(X86Triples, - X86Triples + llvm::array_lengthof(X86Triples)); - BiarchLibDirs.append(X86_64LibDirs, - X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); - BiarchTripleAliases.append( - X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples)); + LibDirs.append(begin(X86LibDirs), end(X86LibDirs)); + TripleAliases.append(begin(X86Triples), end(X86Triples)); + BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs)); + BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); break; case llvm::Triple::mips: - LibDirs.append(MIPSLibDirs, - MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs)); - TripleAliases.append(MIPSTriples, - MIPSTriples + llvm::array_lengthof(MIPSTriples)); - BiarchLibDirs.append(MIPS64LibDirs, - MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs)); - BiarchTripleAliases.append( - MIPS64Triples, MIPS64Triples + llvm::array_lengthof(MIPS64Triples)); + LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs)); + TripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); + BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs)); + BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples)); break; case llvm::Triple::mipsel: - LibDirs.append(MIPSELLibDirs, - MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs)); - TripleAliases.append(MIPSELTriples, - MIPSELTriples + llvm::array_lengthof(MIPSELTriples)); - TripleAliases.append(MIPSTriples, - MIPSTriples + llvm::array_lengthof(MIPSTriples)); - BiarchLibDirs.append( - MIPS64ELLibDirs, - MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs)); - BiarchTripleAliases.append( - MIPS64ELTriples, - MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples)); + LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs)); + TripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples)); + TripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); + BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs)); + BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples)); break; case llvm::Triple::mips64: - LibDirs.append(MIPS64LibDirs, - MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs)); - TripleAliases.append(MIPS64Triples, - MIPS64Triples + llvm::array_lengthof(MIPS64Triples)); - BiarchLibDirs.append(MIPSLibDirs, - MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs)); - BiarchTripleAliases.append(MIPSTriples, - MIPSTriples + llvm::array_lengthof(MIPSTriples)); + LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs)); + TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples)); + BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs)); + BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); break; case llvm::Triple::mips64el: - LibDirs.append(MIPS64ELLibDirs, - MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs)); - TripleAliases.append( - MIPS64ELTriples, - MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples)); - BiarchLibDirs.append(MIPSELLibDirs, - MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs)); - BiarchTripleAliases.append( - MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples)); - BiarchTripleAliases.append( - MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples)); + LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs)); + TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples)); + BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs)); + BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples)); + BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); break; case llvm::Triple::ppc: - LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); - TripleAliases.append(PPCTriples, - PPCTriples + llvm::array_lengthof(PPCTriples)); - BiarchLibDirs.append(PPC64LibDirs, - PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); - BiarchTripleAliases.append( - PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples)); + LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs)); + TripleAliases.append(begin(PPCTriples), end(PPCTriples)); + BiarchLibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs)); + BiarchTripleAliases.append(begin(PPC64Triples), end(PPC64Triples)); break; case llvm::Triple::ppc64: - LibDirs.append(PPC64LibDirs, - PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); - TripleAliases.append(PPC64Triples, - PPC64Triples + llvm::array_lengthof(PPC64Triples)); - BiarchLibDirs.append(PPCLibDirs, - PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); - BiarchTripleAliases.append(PPCTriples, - PPCTriples + llvm::array_lengthof(PPCTriples)); + LibDirs.append(begin(PPC64LibDirs), end(PPC64LibDirs)); + TripleAliases.append(begin(PPC64Triples), end(PPC64Triples)); + BiarchLibDirs.append(begin(PPCLibDirs), end(PPCLibDirs)); + BiarchTripleAliases.append(begin(PPCTriples), end(PPCTriples)); break; case llvm::Triple::ppc64le: - LibDirs.append(PPC64LELibDirs, - PPC64LELibDirs + llvm::array_lengthof(PPC64LELibDirs)); - TripleAliases.append(PPC64LETriples, - PPC64LETriples + llvm::array_lengthof(PPC64LETriples)); + LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs)); + TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples)); break; case llvm::Triple::sparc: - LibDirs.append(SPARCv8LibDirs, - SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs)); - TripleAliases.append(SPARCv8Triples, - SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples)); - BiarchLibDirs.append(SPARCv9LibDirs, - SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs)); - BiarchTripleAliases.append( - SPARCv9Triples, SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples)); + LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs)); + TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples)); + BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs)); + BiarchTripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples)); break; case llvm::Triple::sparcv9: - LibDirs.append(SPARCv9LibDirs, - SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs)); - TripleAliases.append(SPARCv9Triples, - SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples)); - BiarchLibDirs.append(SPARCv8LibDirs, - SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs)); - BiarchTripleAliases.append( - SPARCv8Triples, SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples)); + LibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs)); + TripleAliases.append(begin(SPARCv9Triples), end(SPARCv9Triples)); + BiarchLibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs)); + BiarchTripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples)); break; case llvm::Triple::systemz: - LibDirs.append(SystemZLibDirs, - SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs)); - TripleAliases.append(SystemZTriples, - SystemZTriples + llvm::array_lengthof(SystemZTriples)); + LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs)); + TripleAliases.append(begin(SystemZTriples), end(SystemZTriples)); break; default: @@ -1645,6 +1557,10 @@ struct DetectedMultilibs { llvm::Optional<Multilib> BiarchSibling; }; +static Multilib makeMultilib(StringRef commonSuffix) { + return Multilib(commonSuffix, commonSuffix, commonSuffix); +} + static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, const llvm::opt::ArgList &Args, DetectedMultilibs &Result) { @@ -1678,69 +1594,46 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, // Check for FSF toolchain multilibs MultilibSet FSFMipsMultilibs; { - Multilib MArchMips32 = Multilib() - .gccSuffix("/mips32") - .osSuffix("/mips32") - .includeSuffix("/mips32") + auto MArchMips32 = makeMultilib("/mips32") .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32"); - Multilib MArchMicroMips = Multilib() - .gccSuffix("/micromips") - .osSuffix("/micromips") - .includeSuffix("/micromips") + auto MArchMicroMips = makeMultilib("/micromips") .flag("+m32").flag("-m64").flag("+mmicromips"); - Multilib MArchMips64r2 = Multilib() - .gccSuffix("/mips64r2") - .osSuffix("/mips64r2") - .includeSuffix("/mips64r2") + auto MArchMips64r2 = makeMultilib("/mips64r2") .flag("-m32").flag("+m64").flag("+march=mips64r2"); - Multilib MArchMips64 = Multilib() - .gccSuffix("/mips64") - .osSuffix("/mips64") - .includeSuffix("/mips64") + auto MArchMips64 = makeMultilib("/mips64") .flag("-m32").flag("+m64").flag("-march=mips64r2"); - Multilib MArchDefault = Multilib() + auto MArchDefault = makeMultilib("") .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32r2"); - Multilib Mips16 = Multilib() - .gccSuffix("/mips16") - .osSuffix("/mips16") - .includeSuffix("/mips16") + auto Mips16 = makeMultilib("/mips16") .flag("+mips16"); - Multilib MAbi64 = Multilib() - .gccSuffix("/64") - .osSuffix("/64") - .includeSuffix("/64") + auto UCLibc = makeMultilib("/uclibc") + .flag("+muclibc"); + + auto MAbi64 = makeMultilib("/64") .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); - Multilib BigEndian = Multilib() + auto BigEndian = makeMultilib("") .flag("+EB").flag("-EL"); - Multilib LittleEndian = Multilib() - .gccSuffix("/el") - .osSuffix("/el") - .includeSuffix("/el") + auto LittleEndian = makeMultilib("/el") .flag("+EL").flag("-EB"); - Multilib SoftFloat = Multilib() - .gccSuffix("/sof") - .osSuffix("/sof") - .includeSuffix("/sof") + auto SoftFloat = makeMultilib("/sof") .flag("+msoft-float"); - Multilib Nan2008 = Multilib() - .gccSuffix("/nan2008") - .osSuffix("/nan2008") - .includeSuffix("/nan2008") + auto Nan2008 = makeMultilib("/nan2008") .flag("+mnan=2008"); FSFMipsMultilibs = MultilibSet() .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64, MArchDefault) + .Maybe(UCLibc) .Maybe(Mips16) .FilterOut("/mips64/mips16") .FilterOut("/mips64r2/mips16") @@ -1754,59 +1647,59 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, .Maybe(SoftFloat) .Maybe(Nan2008) .FilterOut(".*sof/nan2008") - .FilterOut(NonExistent); + .FilterOut(NonExistent) + .setIncludeDirsCallback([]( + StringRef InstallDir, StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + std::string SysRootInc = InstallDir.str() + "/../../../../sysroot"; + if (StringRef(M.includeSuffix()).startswith("/uclibc")) + Dirs.push_back(SysRootInc + "/uclibc/usr/include"); + else + Dirs.push_back(SysRootInc + "/usr/include"); + return Dirs; + }); } // Check for Code Sourcery toolchain multilibs MultilibSet CSMipsMultilibs; { - Multilib MArchMips16 = Multilib() - .gccSuffix("/mips16") - .osSuffix("/mips16") - .includeSuffix("/mips16") + auto MArchMips16 = makeMultilib("/mips16") .flag("+m32").flag("+mips16"); - Multilib MArchMicroMips = Multilib() - .gccSuffix("/micromips") - .osSuffix("/micromips") - .includeSuffix("/micromips") + auto MArchMicroMips = makeMultilib("/micromips") .flag("+m32").flag("+mmicromips"); - Multilib MArchDefault = Multilib() + auto MArchDefault = makeMultilib("") .flag("-mips16").flag("-mmicromips"); - Multilib SoftFloat = Multilib() - .gccSuffix("/soft-float") - .osSuffix("/soft-float") - .includeSuffix("/soft-float") + auto UCLibc = makeMultilib("/uclibc") + .flag("+muclibc"); + + auto SoftFloat = makeMultilib("/soft-float") .flag("+msoft-float"); - Multilib Nan2008 = Multilib() - .gccSuffix("/nan2008") - .osSuffix("/nan2008") - .includeSuffix("/nan2008") + auto Nan2008 = makeMultilib("/nan2008") .flag("+mnan=2008"); - Multilib DefaultFloat = Multilib() + auto DefaultFloat = makeMultilib("") .flag("-msoft-float").flag("-mnan=2008"); - Multilib BigEndian = Multilib() + auto BigEndian = makeMultilib("") .flag("+EB").flag("-EL"); - Multilib LittleEndian = Multilib() - .gccSuffix("/el") - .osSuffix("/el") - .includeSuffix("/el") + auto LittleEndian = makeMultilib("/el") .flag("+EL").flag("-EB"); // Note that this one's osSuffix is "" - Multilib MAbi64 = Multilib() + auto MAbi64 = makeMultilib("") .gccSuffix("/64") .includeSuffix("/64") .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); CSMipsMultilibs = MultilibSet() .Either(MArchMips16, MArchMicroMips, MArchDefault) + .Maybe(UCLibc) .Either(SoftFloat, Nan2008, DefaultFloat) .FilterOut("/micromips/nan2008") .FilterOut("/mips16/nan2008") @@ -1814,7 +1707,19 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, .Maybe(MAbi64) .FilterOut("/mips16.*/64") .FilterOut("/micromips.*/64") - .FilterOut(NonExistent); + .FilterOut(NonExistent) + .setIncludeDirsCallback([]( + StringRef InstallDir, StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + std::string SysRootInc = + InstallDir.str() + "/../../../../" + TripleStr.str(); + if (StringRef(M.includeSuffix()).startswith("/uclibc")) + Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include"); + else + Dirs.push_back(SysRootInc + "/libc/usr/include"); + return Dirs; + }); } MultilibSet AndroidMipsMultilibs = MultilibSet() @@ -1843,29 +1748,27 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, MultilibSet ImgMultilibs; { - Multilib Mips64r6 = Multilib() - .gccSuffix("/mips64r6") - .osSuffix("/mips64r6") - .includeSuffix("/mips64r6") + auto Mips64r6 = makeMultilib("/mips64r6") .flag("+m64").flag("-m32"); - Multilib LittleEndian = Multilib() - .gccSuffix("/el") - .osSuffix("/el") - .includeSuffix("/el") + auto LittleEndian = makeMultilib("/el") .flag("+EL").flag("-EB"); - Multilib MAbi64 = Multilib() - .gccSuffix("/64") - .osSuffix("/64") - .includeSuffix("/64") + auto MAbi64 = makeMultilib("/64") .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); ImgMultilibs = MultilibSet() .Maybe(Mips64r6) .Maybe(MAbi64) .Maybe(LittleEndian) - .FilterOut(NonExistent); + .FilterOut(NonExistent) + .setIncludeDirsCallback([]( + StringRef InstallDir, StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + Dirs.push_back((InstallDir + "/../../../../sysroot/usr/include").str()); + return Dirs; + }); } StringRef CPUName; @@ -1884,6 +1787,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, addMultilibFlag(CPUName == "mips64r2" || CPUName == "octeon", "march=mips64r2", Flags); addMultilibFlag(isMicroMips(Args), "mmicromips", Flags); + addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags); addMultilibFlag(tools::mips::isNaN2008(Args, TargetTriple), "mnan=2008", Flags); addMultilibFlag(ABIName == "n32", "mabi=n32", Flags); @@ -2159,12 +2063,16 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { 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; + getTriple().getArch() == llvm::Triple::thumbeb || + getTriple().getArch() == llvm::Triple::ppc || + getTriple().getArch() == llvm::Triple::ppc64 || + getTriple().getArch() == llvm::Triple::ppc64le || + getTriple().getArch() == llvm::Triple::sparc || + getTriple().getArch() == llvm::Triple::sparcv9 || + getTriple().getArch() == llvm::Triple::systemz; } void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, @@ -2173,8 +2081,6 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, bool UseInitArrayDefault = getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::aarch64_be || - getTriple().getArch() == llvm::Triple::arm64 || - getTriple().getArch() == llvm::Triple::arm64_be || (getTriple().getOS() == llvm::Triple::Linux && (!V.isOlderThan(4, 7, 0) || getTriple().getEnvironment() == llvm::Triple::Android)); @@ -2187,11 +2093,14 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, /// Hexagon Toolchain -std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir) { +std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir, + const ArgList &Args) { // Locate the rest of the toolchain ... - if (strlen(GCC_INSTALL_PREFIX)) - return std::string(GCC_INSTALL_PREFIX); + std::string GccToolchain = getGCCToolchainDir(Args); + + if (!GccToolchain.empty()) + return GccToolchain; std::string InstallRelDir = InstalledDir + "/../../gnu"; if (llvm::sys::fs::exists(InstallRelDir)) @@ -2206,8 +2115,8 @@ std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir) { static void GetHexagonLibraryPaths( const ArgList &Args, - const std::string Ver, - const std::string MarchString, + const std::string &Ver, + const std::string &MarchString, const std::string &InstalledDir, ToolChain::path_list *LibPaths) { @@ -2231,7 +2140,7 @@ static void GetHexagonLibraryPaths( const std::string MarchSuffix = "/" + MarchString; const std::string G0Suffix = "/G0"; const std::string MarchG0Suffix = MarchSuffix + G0Suffix; - const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir) + "/"; + const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir, Args) + "/"; // lib/gcc/hexagon/... std::string LibGCCHexagonDir = RootDir + "lib/gcc/hexagon/"; @@ -2259,7 +2168,7 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Linux(D, Triple, Args) { const std::string InstalledDir(getDriver().getInstalledDir()); - const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir); + const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir, Args); // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to // program paths @@ -2314,7 +2223,7 @@ void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, return; std::string Ver(GetGCCLibAndIncVersion()); - std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir); + std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs); std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver); addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include"); addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include-fixed"); @@ -2330,7 +2239,8 @@ void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, const Driver &D = getDriver(); std::string Ver(GetGCCLibAndIncVersion()); - SmallString<128> IncludeDir(Hexagon_TC::GetGnuDir(D.InstalledDir)); + SmallString<128> IncludeDir( + Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs)); llvm::sys::path::append(IncludeDir, "hexagon/include/c++/"); llvm::sys::path::append(IncludeDir, Ver); @@ -2599,7 +2509,7 @@ bool FreeBSD::HasNativeLLVMSupport() const { } bool FreeBSD::isPIEDefault() const { - return getSanitizerArgs().hasZeroBaseShadow(); + return getSanitizerArgs().requiresPIE(); } /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. @@ -2623,11 +2533,13 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) 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; + case llvm::Triple::EABIHF: + case llvm::Triple::GNUEABIHF: + getFilePaths().push_back("=/usr/lib/eabihf"); + break; default: getFilePaths().push_back("=/usr/lib/oabi"); break; @@ -2640,6 +2552,9 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) else if (tools::mips::hasMipsAbiArg(Args, "64")) getFilePaths().push_back("=/usr/lib/64"); break; + case llvm::Triple::ppc: + getFilePaths().push_back("=/usr/lib/powerpc"); + break; case llvm::Triple::sparc: getFilePaths().push_back("=/usr/lib/sparc"); break; @@ -2674,12 +2589,16 @@ NetBSD::GetCXXStdlibType(const ArgList &Args) const { unsigned Major, Minor, Micro; getTriple().getOSVersion(Major, Minor, Micro); - if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 40) || Major == 0) { + if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) { switch (getArch()) { + case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: case llvm::Triple::x86: case llvm::Triple::x86_64: return ToolChain::CST_Libcxx; @@ -2726,32 +2645,6 @@ Tool *Minix::buildLinker() const { return new tools::minix::Link(*this); } -/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly. - -AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple, - const ArgList &Args) - : Generic_GCC(D, Triple, Args) { - - getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); - - getFilePaths().push_back(getDriver().Dir + "/../lib"); - getFilePaths().push_back("/usr/lib"); - getFilePaths().push_back("/usr/sfw/lib"); - getFilePaths().push_back("/opt/gcc4/lib"); - getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4"); - -} - -Tool *AuroraUX::buildAssembler() const { - return new tools::auroraux::Assemble(*this); -} - -Tool *AuroraUX::buildLinker() const { - return new tools::auroraux::Link(*this); -} - /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. Solaris::Solaris(const Driver &D, const llvm::Triple& Triple, @@ -2825,7 +2718,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { llvm::MemoryBuffer::getFile("/etc/lsb-release"); if (File) { StringRef Data = File.get()->getBuffer(); - SmallVector<StringRef, 8> Lines; + SmallVector<StringRef, 16> Lines; Data.split(Lines, "\n"); Distro Version = UnknownDistro; for (unsigned i = 0, s = Lines.size(); i != s; ++i) @@ -2939,12 +2832,10 @@ static std::string getMultiarchTriple(const llvm::Triple &TargetTriple, 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"; @@ -3115,7 +3006,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // installation that is *not* within the system root to ensure two things: // // 1) Any DSOs that are linked in from this tree or from the install path - // above must be preasant on the system root and found via an + // above must be present on the system root and found via an // appropriate rpath. // 2) There must not be libraries installed into // <prefix>/<triple>/<libdir> unless they should be preferred over @@ -3272,20 +3163,16 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // Lacking those, try to detect the correct set of system includes for the // target triple. - // Sourcery CodeBench and modern FSF Mips toolchains put extern C - // system includes under three additional directories. - if (GCCInstallation.isValid() && isMipsArch(getTriple().getArch())) { - addExternCSystemIncludeIfExists( - DriverArgs, CC1Args, GCCInstallation.getInstallPath() + "/include"); - - addExternCSystemIncludeIfExists( - DriverArgs, CC1Args, - GCCInstallation.getInstallPath() + "/../../../../" + - GCCInstallation.getTriple().str() + "/libc/usr/include"); - - addExternCSystemIncludeIfExists( - DriverArgs, CC1Args, - GCCInstallation.getInstallPath() + "/../../../../sysroot/usr/include"); + // Add include directories specific to the selected multilib set and multilib. + if (GCCInstallation.isValid()) { + auto Callback = Multilibs.includeDirsCallback(); + if (Callback) { + const auto IncludePaths = Callback(GCCInstallation.getInstallPath(), + GCCInstallation.getTriple().str(), + GCCInstallation.getMultilib()); + for (const auto &Path : IncludePaths) + addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path); + } } // Implement generic Debian multiarch support. @@ -3344,9 +3231,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, } else if (getTriple().getArch() == llvm::Triple::x86) { MultiarchIncludeDirs = X86MultiarchIncludeDirs; } else if (getTriple().getArch() == llvm::Triple::aarch64 || - getTriple().getArch() == llvm::Triple::aarch64_be || - getTriple().getArch() == llvm::Triple::arm64 || - getTriple().getArch() == llvm::Triple::arm64_be) { + getTriple().getArch() == llvm::Triple::aarch64_be) { MultiarchIncludeDirs = AArch64MultiarchIncludeDirs; } else if (getTriple().getArch() == llvm::Triple::arm) { if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) @@ -3500,7 +3385,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } bool Linux::isPIEDefault() const { - return getSanitizerArgs().hasZeroBaseShadow(); + return getSanitizerArgs().requiresPIE(); } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. @@ -3586,7 +3471,8 @@ void XCore::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc) || - DriverArgs.hasArg(options::OPT_nostdlibinc)) + DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) return; if (const char *cl_include_dir = getenv("XCC_CPLUS_INCLUDE_PATH")) { SmallVector<StringRef, 4> Dirs; diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index b5df866..47fb10d 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LIB_DRIVER_TOOLCHAINS_H_ -#define CLANG_LIB_DRIVER_TOOLCHAINS_H_ +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_H #include "Tools.h" #include "clang/Basic/VersionTuple.h" @@ -234,9 +234,10 @@ public: void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, - StringRef DarwinStaticLib, + StringRef DarwinLibName, bool AlwaysLink = false, - bool IsEmbedded = false) const; + bool IsEmbedded = false, + bool AddRPath = false) const; /// } /// @name ToolChain Implementation @@ -255,7 +256,7 @@ public: bool IsBlocksDefault() const override { // Always allow blocks on Apple; users interested in versioning are - // expected to use /usr/include/Blocks.h. + // expected to use /usr/include/Block.h. return true; } bool IsIntegratedAssemblerDefault() const override { @@ -362,7 +363,7 @@ public: bool isKernelStatic() const override { return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0) || - getTriple().getArch() == llvm::Triple::arm64; + getTriple().getArch() == llvm::Triple::aarch64; } protected: @@ -487,7 +488,8 @@ public: AddCCKextLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; - virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const; + virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) + const override; void AddLinkARCArgs(const llvm::opt::ArgList &Args, @@ -506,16 +508,6 @@ public: llvm::opt::ArgStringList &CC1Args) const override; }; -class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { -public: - AuroraUX(const Driver &D, const llvm::Triple &Triple, - const llvm::opt::ArgList &Args); - -protected: - Tool *buildAssembler() const override; - Tool *buildLinker() const override; -}; - class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC { public: Solaris(const Driver &D, const llvm::Triple &Triple, @@ -542,14 +534,6 @@ public: return 2; } - virtual bool IsIntegratedAssemblerDefault() const override { - if (getTriple().getArch() == llvm::Triple::ppc || - getTriple().getArch() == llvm::Triple::sparc || - getTriple().getArch() == llvm::Triple::sparcv9) - return true; - return Generic_ELF::IsIntegratedAssemblerDefault(); - } - protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; @@ -591,12 +575,6 @@ public: void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - bool IsIntegratedAssemblerDefault() const override { - if (getTriple().getArch() == llvm::Triple::ppc || - getTriple().getArch() == llvm::Triple::ppc64) - return true; - return Generic_ELF::IsIntegratedAssemblerDefault(); - } bool UseSjLjExceptions() const override; bool isPIEDefault() const override; @@ -621,11 +599,6 @@ public: bool IsUnwindTablesDefault() const override { return true; } - bool IsIntegratedAssemblerDefault() const override { - if (getTriple().getArch() == llvm::Triple::ppc) - return true; - return Generic_ELF::IsIntegratedAssemblerDefault(); - } protected: Tool *buildAssembler() const override; @@ -709,7 +682,8 @@ public: StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; } - static std::string GetGnuDir(const std::string &InstalledDir); + static std::string GetGnuDir(const std::string &InstalledDir, + const llvm::opt::ArgList &Args); static StringRef GetTargetCPU(const llvm::opt::ArgList &Args); }; @@ -728,10 +702,10 @@ public: bool isPICDefaultForced() const override; }; -class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { +class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { public: - Windows(const Driver &D, const llvm::Triple &Triple, - const llvm::opt::ArgList &Args); + MSVCToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); bool IsIntegratedAssemblerDefault() const override; bool IsUnwindTablesDefault() const override; @@ -746,11 +720,50 @@ public: AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + bool getWindowsSDKDir(std::string &path, int &major, int &minor) const; + bool getWindowsSDKLibraryPath(std::string &path) const; + bool getVisualStudioInstallDir(std::string &path) const; + bool getVisualStudioBinariesFolder(const char *clangProgramPath, + std::string &path) const; + protected: + void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + const std::string &folder, + const char *subfolder) const; + Tool *buildLinker() const override; Tool *buildAssembler() const override; }; +class LLVM_LIBRARY_VISIBILITY CrossWindowsToolChain : public Generic_GCC { +public: + CrossWindowsToolChain(const Driver &D, const llvm::Triple &T, + const llvm::opt::ArgList &Args); + + bool IsIntegratedAssemblerDefault() const override { return true; } + bool IsUnwindTablesDefault() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; + + unsigned int GetDefaultStackProtectorLevel(bool KernelOrKext) const override { + return 0; + } + + void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) + const override; + void AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) + const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + +protected: + Tool *buildLinker() const override; + Tool *buildAssembler() const override; +}; class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain { public: diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 5acffb7..daa581e 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -83,6 +83,23 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { << A->getAsString(Args) << "-static"; } +// Add backslashes to escape spaces and other backslashes. +// This is used for the space-separated argument list specified with +// the -dwarf-debug-flags option. +static void EscapeSpacesAndBackslashes(const char *Arg, + SmallVectorImpl<char> &Res) { + for ( ; *Arg; ++Arg) { + switch (*Arg) { + default: break; + case ' ': + case '\\': + Res.push_back('\\'); + break; + } + Res.push_back(*Arg); + } +} + // Quote target names for inclusion in GNU Make dependency files. // Only the characters '$', '#', ' ', '\t' are quoted. static void QuoteTarget(StringRef Target, @@ -457,10 +474,10 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { 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: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: if (Triple.isOSDarwin() || Triple.isOSWindows()) return true; return false; @@ -508,7 +525,7 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A, } else D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } - + // Handle -mfpu=. // // FIXME: Centralize feature selection, defaulting shouldn't be also in the @@ -546,6 +563,18 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, Features.push_back("+d16"); Features.push_back("+fp-only-sp"); Features.push_back("-neon"); + } else if (FPU == "fp5-sp-d16" || FPU == "fpv5-sp-d16") { + Features.push_back("+fp-armv8"); + Features.push_back("+fp-only-sp"); + Features.push_back("+d16"); + Features.push_back("-neon"); + Features.push_back("-crypto"); + } else if (FPU == "fp5-dp-d16" || FPU == "fpv5-dp-d16" || + FPU == "fp5-d16" || FPU == "fpv5-d16") { + Features.push_back("+fp-armv8"); + Features.push_back("+d16"); + Features.push_back("-neon"); + Features.push_back("-crypto"); } else if (FPU == "fp-armv8") { Features.push_back("+fp-armv8"); Features.push_back("-neon"); @@ -560,6 +589,12 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, Features.push_back("+crypto"); } else if (FPU == "neon") { Features.push_back("+neon"); + } else if (FPU == "neon-vfpv3") { + Features.push_back("+vfp3"); + Features.push_back("+neon"); + } else if (FPU == "neon-vfpv4") { + Features.push_back("+neon"); + Features.push_back("+vfp4"); } else if (FPU == "none") { Features.push_back("-vfp2"); Features.push_back("-vfp3"); @@ -730,6 +765,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Select the ABI to use. // // FIXME: Support -meabi. + // FIXME: Parts of this are duplicated in the backend, unify this somehow. const char *ABIName = nullptr; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); @@ -737,8 +773,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // 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) || + Triple.getOS() == llvm::Triple::UnknownOS || StringRef(CPUName).startswith("cortex-m")) { ABIName = "aapcs"; } else { @@ -760,7 +795,11 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ABIName = "aapcs"; break; default: - ABIName = "apcs-gnu"; + if (Triple.getOS() == llvm::Triple::NetBSD) + ABIName = "apcs-gnu"; + else + ABIName = "aapcs"; + break; } } CmdArgs.push_back("-target-abi"); @@ -801,6 +840,21 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back("-arm-use-movt=0"); } + // -mkernel implies -mstrict-align; don't add the redundant option. + if (!KernelOrKext) { + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) { + CmdArgs.push_back("-backend-option"); + if (A->getOption().matches(options::OPT_mno_unaligned_access)) + CmdArgs.push_back("-arm-strict-align"); + else { + if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) + D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; + CmdArgs.push_back("-arm-no-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, @@ -875,9 +929,26 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); - if (Args.hasArg(options::OPT_mstrict_align)) { + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) { + CmdArgs.push_back("-backend-option"); + if (A->getOption().matches(options::OPT_mno_unaligned_access)) + CmdArgs.push_back("-aarch64-strict-align"); + else + CmdArgs.push_back("-aarch64-no-strict-align"); + } + + if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769, + options::OPT_mno_fix_cortex_a53_835769)) { + CmdArgs.push_back("-backend-option"); + if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769)) + CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); + else + CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0"); + } else if (Triple.getEnvironment() == llvm::Triple::Android) { + // Enabled A53 errata (835769) workaround by default on android CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-aarch64-strict-align"); + CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); } // Setting -mno-global-merge disables the codegen global merge pass. Setting @@ -911,6 +982,10 @@ void mips::getMipsCPUAndABI(const ArgList &Args, DefMips64CPU = "mips64r6"; } + // MIPS3 is the default for mips64*-unknown-openbsd. + if (Triple.getOS() == llvm::Triple::OpenBSD) + DefMips64CPU = "mips3"; + if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ)) CPUName = A->getValue(); @@ -957,6 +1032,8 @@ void mips::getMipsCPUAndABI(const ArgList &Args, .Cases("n32", "n64", DefMips64CPU) .Default(""); } + + // FIXME: Warn on inconsistent use of -march and -mabi. } // Convert ABI name to the GNU tools acceptable variant. @@ -1029,6 +1106,9 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-n64"); Features.push_back(Args.MakeArgString(ABIFeature)); + AddTargetFeature(Args, Features, options::OPT_mno_abicalls, + options::OPT_mabicalls, "noabicalls"); + StringRef FloatABI = getMipsFloatABI(D, Args); if (FloatABI == "soft") { // FIXME: Note, this is a hack. We need to pass the selected float @@ -1233,6 +1313,35 @@ static void getPPCTargetFeatures(const ArgList &Args, options::OPT_fno_altivec, "altivec"); } +void Clang::AddPPCTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Select the ABI to use. + const char *ABIName = nullptr; + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + ABIName = A->getValue(); + } else if (getToolChain().getTriple().isOSLinux()) + switch(getToolChain().getArch()) { + case llvm::Triple::ppc64: + ABIName = "elfv1"; + break; + case llvm::Triple::ppc64le: + ABIName = "elfv2"; + break; + default: + break; + } + + if (ABIName) { + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName); + } +} + +bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + /// Get the (LLVM) name of the R600 gpu we are targeting. static std::string getR600TargetGPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { @@ -1251,7 +1360,7 @@ static std::string getR600TargetGPU(const ArgList &Args) { } static void getSparcTargetFeatures(const ArgList &Args, - std::vector<const char *> Features) { + std::vector<const char *> &Features) { bool SoftFloatABI = true; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { @@ -1365,8 +1474,6 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - case llvm::Triple::arm64: - case llvm::Triple::arm64_be: return getAArch64TargetCPU(Args); case llvm::Triple::arm: @@ -1420,6 +1527,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { return getSystemZTargetCPU(Args); case llvm::Triple::r600: + case llvm::Triple::amdgcn: return getR600TargetGPU(Args); } } @@ -1593,7 +1701,7 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args, } // Decode AArch64 features from string like +[no]featureA+[no]featureB+... -static bool DecodeAArch64Features(const Driver &D, const StringRef &text, +static bool DecodeAArch64Features(const Driver &D, StringRef text, std::vector<const char *> &Features) { SmallVector<StringRef, 8> Split; text.split(Split, StringRef("+"), -1, false); @@ -1702,6 +1810,9 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + else if (Args.hasArg(options::OPT_arch)) + success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), Args, + Features); if (success && (A = Args.getLastArg(options::OPT_mtune_EQ))) success = @@ -1709,6 +1820,9 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + else if (Args.hasArg(options::OPT_arch)) + success = getAArch64MicroArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), + Args, Features); if (!success) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); @@ -1756,12 +1870,11 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, getPPCTargetFeatures(Args, Features); break; case llvm::Triple::sparc: + case llvm::Triple::sparcv9: 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: @@ -1809,43 +1922,15 @@ 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; - +static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) { if (Arg *A = Args.getLastArg(options::OPT_fexceptions, - options::OPT_fno_exceptions)) { + 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 true; - return ES; + return false; } /// addExceptionArgs - Adds exception related arguments to the driver command @@ -1870,8 +1955,8 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, return; } - // Gather the exception settings from the command line arguments. - ExceptionSettings ES = exceptionSettings(Args, Triple); + // Gather the exception settings from the command line arguments. + bool EH = exceptionSettings(Args, Triple); // Obj-C exceptions are enabled by default, regardless of -fexceptions. This // is not necessarily sensible, but follows GCC. @@ -1881,31 +1966,27 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, true)) { CmdArgs.push_back("-fobjc-exceptions"); - ES.ShouldUseExceptionTables |= - shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); + EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple); } if (types::isCXX(InputType)) { - bool CXXExceptionsEnabled = ES.ExceptionsEnabled; - + bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore; if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, options::OPT_fexceptions, - options::OPT_fno_exceptions)) { - if (A->getOption().matches(options::OPT_fcxx_exceptions)) - CXXExceptionsEnabled = true; - else if (A->getOption().matches(options::OPT_fno_cxx_exceptions)) - CXXExceptionsEnabled = false; - } + options::OPT_fno_exceptions)) + CXXExceptionsEnabled = + A->getOption().matches(options::OPT_fcxx_exceptions) || + A->getOption().matches(options::OPT_fexceptions); if (CXXExceptionsEnabled) { CmdArgs.push_back("-fcxx-exceptions"); - ES.ShouldUseExceptionTables = true; + EH = true; } } - if (ES.ShouldUseExceptionTables) + if (EH) CmdArgs.push_back("-fexceptions"); } @@ -1931,7 +2012,7 @@ static bool ShouldDisableDwarfDirectory(const ArgList &Args, /// \brief Check whether the given input tree contains any compilation actions. static bool ContainsCompileAction(const Action *A) { - if (isa<CompileJobAction>(A)) + if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A)) return true; for (const auto &Act : *A) @@ -1999,8 +2080,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } else if (Value == "-L") { CmdArgs.push_back("-msave-temp-labels"); } else if (Value == "--fatal-warnings") { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-fatal-assembler-warnings"); + CmdArgs.push_back("-massembler-fatal-warnings"); } else if (Value == "--noexecstack") { CmdArgs.push_back("-mnoexecstack"); } else if (Value == "-compress-debug-sections" || @@ -2033,11 +2113,13 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // 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) + // FIXME: handle 64-bit + if (TC.getTriple().isOSWindows() && + !TC.getTriple().isWindowsItaniumEnvironment()) + return "i386"; + if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb) return "arm"; - else - return TC.getArchName(); + return TC.getArchName(); } static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) { @@ -2045,209 +2127,167 @@ static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) { 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(); + StringRef OSLibName = + (Triple.getOS() == llvm::Triple::FreeBSD) ? "freebsd" : TC.getOS(); llvm::sys::path::append(Res, "lib", OSLibName); return Res; } +static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component, + bool Shared = false, + const char *Env = "") { + bool IsOSWindows = TC.getTriple().isOSWindows(); + StringRef Arch = getArchNameForCompilerRTLib(TC); + const char *Prefix = IsOSWindows ? "" : "lib"; + const char *Suffix = + Shared ? (IsOSWindows ? ".dll" : ".so") : (IsOSWindows ? ".lib" : ".a"); + + SmallString<128> Path = getCompilerRTLibDir(TC); + llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" + + Arch + Env + Suffix); + + return Path; +} + // 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 addClangRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "builtins"))); + + if (!TC.getTriple().isOSWindows()) { + // FIXME: why do we link against gcc when we are using compiler-rt? + 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) || +static void addProfileRT(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false) || Args.hasArg(options::OPT_fprofile_generate) || Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fcreate_profile) || Args.hasArg(options::OPT_coverage))) return; - // -fprofile-instr-generate requires position-independent code to build with - // shared objects. Link against the right archive. - const char *Lib = "libclang_rt.profile-"; - if (Args.hasArg(options::OPT_fprofile_instr_generate) && - Args.hasArg(options::OPT_shared)) - Lib = "libclang_rt.profile-pic-"; - - SmallString<128> LibProfile = getCompilerRTLibDir(TC); - llvm::sys::path::append(LibProfile, - Twine(Lib) + getArchNameForCompilerRTLib(TC) + ".a"); - - CmdArgs.push_back(Args.MakeArgString(LibProfile)); + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile"))); } -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 addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, StringRef Sanitizer, + bool IsShared) { + const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android + ? "-android" + : ""; + + // Static runtimes must be forced into executable, so we wrap them in + // whole-archive. + if (!IsShared) + CmdArgs.push_back("-whole-archive"); + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared, + Env))); + if (!IsShared) + CmdArgs.push_back("-no-whole-archive"); } -static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args, +// Tries to use a file with the list of dynamic symbols that need to be exported +// from the runtime library. Returns true if the file was found. +static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, - const StringRef Sanitizer, - bool BeforeLibStdCXX, - bool ExportSymbols = true, - bool LinkDeps = true) { - SmallString<128> LibSanitizer = - getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false); - - // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a, - // etc.) so that the linker picks custom versions of the global 'operator - // new' and 'operator delete' symbols. We take the extreme (but simple) - // strategy of inserting it at the front of the link command. It also - // needs to be forced to end up in the executable, so wrap it in - // whole-archive. - SmallVector<const char *, 3> LibSanitizerArgs; - LibSanitizerArgs.push_back("-whole-archive"); - LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer)); - LibSanitizerArgs.push_back("-no-whole-archive"); - - CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(), - LibSanitizerArgs.begin(), LibSanitizerArgs.end()); - - if (LinkDeps) { - // Link sanitizer dependencies explicitly - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-lrt"); - CmdArgs.push_back("-lm"); - // There's no libdl on FreeBSD. - if (TC.getTriple().getOS() != llvm::Triple::FreeBSD) - CmdArgs.push_back("-ldl"); + StringRef Sanitizer) { + SmallString<128> SanRT = getCompilerRT(TC, Sanitizer); + if (llvm::sys::fs::exists(SanRT + ".syms")) { + CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms")); + return true; } + return false; +} - // If possible, use a dynamic symbols file to export the symbols from the - // runtime library. If we can't do so, use -export-dynamic instead to export - // all symbols from the binary. - if (ExportSymbols) { - if (llvm::sys::fs::exists(LibSanitizer + ".syms")) - CmdArgs.push_back( - Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms")); - else - CmdArgs.push_back("-export-dynamic"); - } +static void linkSanitizerRuntimeDeps(const ToolChain &TC, + ArgStringList &CmdArgs) { + // Force linking against the system libraries sanitizers depends on + // (see PR15823 why this is necessary). + CmdArgs.push_back("--no-as-needed"); + 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 AddressSanitizer is enabled, add appropriate linker flags (Linux). -/// This needs to be called before we add the C run-time (malloc, etc). -static void addAsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, bool Shared, bool IsCXX) { - if (Shared) { - // Link dynamic runtime if necessary. - SmallString<128> LibSanitizer = - getSanitizerRTLibName(TC, "asan", Shared); - CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer)); +static void +collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, + SmallVectorImpl<StringRef> &SharedRuntimes, + SmallVectorImpl<StringRef> &StaticRuntimes, + SmallVectorImpl<StringRef> &HelperStaticRuntimes) { + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + // Collect shared runtimes. + if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) { + SharedRuntimes.push_back("asan"); } - // Do not link static runtime to DSOs or if compiling for Android. + // Collect static runtimes. if (Args.hasArg(options::OPT_shared) || - (TC.getTriple().getEnvironment() == llvm::Triple::Android)) + (TC.getTriple().getEnvironment() == llvm::Triple::Android)) { + // Don't link static runtimes into DSOs or if compiling for Android. return; - - if (Shared) { - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit", - /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false, - /*LinkDeps*/ false); - } else { - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true); - if (IsCXX) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true); } -} - -/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux). -/// This needs to be called before we add the C run-time (malloc, etc). -static void addTsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true); -} - -/// If MemorySanitizer is enabled, add appropriate linker flags (Linux). -/// This needs to be called before we add the C run-time (malloc, etc). -static void addMsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true); -} - -/// If LeakSanitizer is enabled, add appropriate linker flags (Linux). -/// This needs to be called before we add the C run-time (malloc, etc). -static void addLsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true); -} - -/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags -/// (Linux). -static void addUbsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, bool IsCXX, - bool HasOtherSanitizerRt) { - // Do not link runtime into shared libraries. - if (Args.hasArg(options::OPT_shared)) - return; - - // Need a copy of sanitizer_common. This could come from another sanitizer - // runtime; if we're not including one, include our own copy. - if (!HasOtherSanitizerRt) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false); - - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true); - - // Only include the bits of the runtime which need a C++ ABI library if - // we're linking in C++ mode. - if (IsCXX) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true); -} - -static void addDfsanRT(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - if (!Args.hasArg(options::OPT_shared)) - addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true); -} - -// Should be called before we add C++ ABI library. -static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, + if (SanArgs.needsAsanRt()) { + if (SanArgs.needsSharedAsanRt()) { + HelperStaticRuntimes.push_back("asan-preinit"); + } else { + StaticRuntimes.push_back("asan"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("asan_cxx"); + } + } + if (SanArgs.needsDfsanRt()) + StaticRuntimes.push_back("dfsan"); + if (SanArgs.needsLsanRt()) + StaticRuntimes.push_back("lsan"); + if (SanArgs.needsMsanRt()) + StaticRuntimes.push_back("msan"); + if (SanArgs.needsTsanRt()) + StaticRuntimes.push_back("tsan"); + // WARNING: UBSan should always go last. + if (SanArgs.needsUbsanRt()) { + // If UBSan is not combined with another sanitizer, we need to pull in + // sanitizer_common explicitly. + if (StaticRuntimes.empty()) + HelperStaticRuntimes.push_back("san"); + StaticRuntimes.push_back("ubsan"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("ubsan_cxx"); + } +} + +// Should be called before we add system libraries (C++ ABI, libstdc++/libc++, +// C runtime, etc). Returns true if sanitizer system deps need to be linked in. +static bool 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); + SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes, + HelperStaticRuntimes; + collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, + HelperStaticRuntimes); + for (auto RT : SharedRuntimes) + addSanitizerRuntime(TC, Args, CmdArgs, RT, true); + for (auto RT : HelperStaticRuntimes) + addSanitizerRuntime(TC, Args, CmdArgs, RT, false); + bool AddExportDynamic = false; + for (auto RT : StaticRuntimes) { + addSanitizerRuntime(TC, Args, CmdArgs, RT, false); + AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT); + } + // If there is a static runtime with no dynamic list, force all the symbols + // to be dynamic to be sure we export sanitizer interface functions. + if (AddExportDynamic) + CmdArgs.push_back("-export-dynamic"); + return !StaticRuntimes.empty(); } static bool shouldUseFramePointerForTarget(const ArgList &Args, @@ -2337,10 +2377,10 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, Args.MakeArgString(TC.GetProgramPath("objcopy")); // First extract the dwo sections. - C.addCommand(new Command(JA, T, Exec, ExtractArgs)); + C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs)); // Then remove them from the original .o file. - C.addCommand(new Command(JA, T, Exec, StripArgs)); + C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs)); } /// \brief Vectorize at all optimization levels greater than 1 except for -Oz. @@ -2410,6 +2450,16 @@ static std::string getMSCompatibilityVersion(const char *VersionStr) { llvm::utostr_32(Build); } +// Claim options we don't want to warn if they are unused. We do this for +// options that build systems might add but are unused when assembling or only +// running the preprocessor for example. +static void claimNoWarnArgs(const ArgList &Args) { + // Don't warn about unused -f(no-)?lto. This can happen when we're + // preprocessing, precompiling or assembling. + Args.ClaimAllArgs(options::OPT_flto); + Args.ClaimAllArgs(options::OPT_fno_lto); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2490,7 +2540,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (isa<VerifyPCHJobAction>(JA)) { CmdArgs.push_back("-verify-pch"); } else { - assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool."); + assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && + "Invalid action for clang tool."); if (JA.getType() == types::TY_Nothing) { CmdArgs.push_back("-fsyntax-only"); @@ -2604,7 +2655,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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: @@ -2684,9 +2734,7 @@ 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) || - Triple.getArch() == llvm::Triple::arm64 || - Triple.getArch() == llvm::Triple::aarch64)) + if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6))) PIC = PIE = false; if (Args.hasArg(options::OPT_static)) PIC = PIE = false; @@ -2726,12 +2774,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + CmdArgs.push_back("-mthread-model"); + if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) + CmdArgs.push_back(A->getValue()); + else + CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel())); + if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) CmdArgs.push_back("-fno-merge-all-constants"); // LLVM Code Generator Options. + if (Args.hasArg(options::OPT_frewrite_map_file) || + Args.hasArg(options::OPT_frewrite_map_file_EQ)) { + for (arg_iterator + MFI = Args.filtered_begin(options::OPT_frewrite_map_file, + options::OPT_frewrite_map_file_EQ), + MFE = Args.filtered_end(); + MFI != MFE; ++MFI) { + CmdArgs.push_back("-frewrite-map-file"); + CmdArgs.push_back((*MFI)->getValue()); + (*MFI)->claim(); + } + } + if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) { StringRef v = A->getValue(); CmdArgs.push_back("-mllvm"); @@ -3022,8 +3089,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - case llvm::Triple::arm64: - case llvm::Triple::arm64_be: AddAArch64TargetArgs(Args, CmdArgs); break; @@ -3034,6 +3099,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AddMIPSTargetArgs(Args, CmdArgs); break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + AddPPCTargetArgs(Args, CmdArgs); + break; + case llvm::Triple::sparc: case llvm::Triple::sparcv9: AddSparcTargetArgs(Args, CmdArgs); @@ -3097,14 +3168,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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) || + A->getOption().matches(options::OPT_g1)) { // FIXME: we should support specifying dwarf version with // -gline-tables-only. CmdArgs.push_back("-gline-tables-only"); - // Default is dwarf-2 for Darwin, OpenBSD and FreeBSD. + // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris. const llvm::Triple &Triple = getToolChain().getTriple(); if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD || - Triple.getOS() == llvm::Triple::FreeBSD) + Triple.getOS() == llvm::Triple::FreeBSD || + Triple.getOS() == llvm::Triple::Solaris) CmdArgs.push_back("-gdwarf-2"); } else if (A->getOption().matches(options::OPT_gdwarf_2)) CmdArgs.push_back("-gdwarf-2"); @@ -3114,10 +3187,11 @@ 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, OpenBSD and FreeBSD. + // Default is dwarf-2 for Darwin, OpenBSD, FreeBSD and Solaris. const llvm::Triple &Triple = getToolChain().getTriple(); if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::OpenBSD || - Triple.getOS() == llvm::Triple::FreeBSD) + Triple.getOS() == llvm::Triple::FreeBSD || + Triple.getOS() == llvm::Triple::Solaris) CmdArgs.push_back("-gdwarf-2"); else CmdArgs.push_back("-g"); @@ -3188,15 +3262,29 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_ftest_coverage) || Args.hasArg(options::OPT_coverage)) CmdArgs.push_back("-femit-coverage-notes"); - if (Args.hasArg(options::OPT_fprofile_arcs) || + if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, + false) || Args.hasArg(options::OPT_coverage)) CmdArgs.push_back("-femit-coverage-data"); + if (Args.hasArg(options::OPT_fcoverage_mapping) && + !Args.hasArg(options::OPT_fprofile_instr_generate)) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-fcoverage-mapping" << "-fprofile-instr-generate"; + + if (Args.hasArg(options::OPT_fcoverage_mapping)) + CmdArgs.push_back("-fcoverage-mapping"); + if (C.getArgs().hasArg(options::OPT_c) || C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { CmdArgs.push_back("-coverage-file"); - SmallString<128> CoverageFilename(Output.getFilename()); + SmallString<128> CoverageFilename; + if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) { + CoverageFilename = FinalOutput->getValue(); + } else { + CoverageFilename = llvm::sys::path::filename(Output.getBaseInput()); + } if (llvm::sys::path::is_relative(CoverageFilename.str())) { SmallString<128> Pwd; if (!llvm::sys::fs::current_path(Pwd)) { @@ -3324,9 +3412,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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); + claimNoWarnArgs(Args); Args.AddAllArgs(CmdArgs, options::OPT_R_Group); Args.AddAllArgs(CmdArgs, options::OPT_W_Group); @@ -3349,8 +3435,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else Std->render(Args, CmdArgs); + // If -f(no-)trigraphs appears after the language standard flag, honor it. if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi, - options::OPT_trigraphs)) + options::OPT_ftrigraphs, + options::OPT_fno_trigraphs)) if (A != Std) A->render(Args, CmdArgs); } else { @@ -3366,7 +3454,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else if (IsWindowsMSVC) CmdArgs.push_back("-std=c++11"); - Args.AddLastArg(CmdArgs, options::OPT_trigraphs); + Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs, + options::OPT_fno_trigraphs); } // GCC's behavior for -Wwrite-strings is a bit strange: @@ -3485,6 +3574,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } + if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) { + CmdArgs.push_back("-fspell-checking-limit"); + CmdArgs.push_back(A->getValue()); + } + // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) { @@ -3522,7 +3616,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -f (flag) options which we can pass directly. Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); - Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug); Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug); @@ -3537,15 +3630,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(Args, CmdArgs); - if (!Args.hasFlag(options::OPT_fsanitize_recover, - options::OPT_fno_sanitize_recover, - true)) - CmdArgs.push_back("-fno-sanitize-recover"); - - if (Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error, - options::OPT_fno_sanitize_undefined_trap_on_error, false)) - CmdArgs.push_back("-fsanitize-undefined-trap-on-error"); - // Report an error for -faltivec on anything other than PowerPC. if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) if (!(getToolChain().getArch() == llvm::Triple::ppc || @@ -3653,31 +3737,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } - // -mkernel implies -mstrict-align; don't add the redundant option. - if (!KernelOrKext) { - if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { - if (A->getOption().matches(options::OPT_mno_unaligned_access)) { - CmdArgs.push_back("-backend-option"); - if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || - getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be || - getToolChain().getTriple().getArch() == llvm::Triple::arm64 || - getToolChain().getTriple().getArch() == llvm::Triple::arm64_be) - CmdArgs.push_back("-aarch64-strict-align"); - else - CmdArgs.push_back("-arm-strict-align"); - } else { - CmdArgs.push_back("-backend-option"); - if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || - getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be || - getToolChain().getTriple().getArch() == llvm::Triple::arm64 || - getToolChain().getTriple().getArch() == llvm::Triple::arm64_be) - CmdArgs.push_back("-aarch64-no-strict-align"); - else - CmdArgs.push_back("-arm-no-strict-align"); - } - } - } + + if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || + getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be) + CmdArgs.push_back("-fallow-half-arguments-and-returns"); if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it, options::OPT_mno_restrict_it)) { @@ -3744,14 +3807,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fblocks-runtime-optional"); } - // -fmodules enables modules (off by default). However, for C++/Objective-C++, - // users must also pass -fcxx-modules. The latter flag will disappear once the - // modules implementation is solid for C++/Objective-C++ programs as well. + // -fmodules enables modules (off by default). + // Users can pass -fno-cxx-modules to turn off modules support for + // C++/Objective-C++ programs, which is a little less mature. bool HaveModules = false; if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, options::OPT_fno_cxx_modules, - false); + true); if (AllowedInCXX || !types::isCXX(InputType)) { CmdArgs.push_back("-fmodules"); HaveModules = true; @@ -3783,15 +3846,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). - if (Arg *A = Args.getLastArg(options::OPT_fmodule_name)) - A->render(Args, CmdArgs); + Args.AddLastArg(CmdArgs, options::OPT_fmodule_name); - // -fmodule-map-file can be used to specify a file containing module + // -fmodule-map-file can be used to specify files containing module // definitions. - if (Arg *A = Args.getLastArg(options::OPT_fmodule_map_file)) - A->render(Args, CmdArgs); + Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file); + + // -fmodule-file can be used to specify files containing precompiled modules. + Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file); - // -fmodule-cache-path specifies where our module files should be written. + // -fmodule-cache-path specifies where our implicitly-built module files + // should be written. SmallString<128> ModuleCachePath; if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) ModuleCachePath = A->getValue(); @@ -3819,14 +3884,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (HaveModules && C.isForDiagnostics()) { SmallString<128> VFSDir(Output.getFilename()); llvm::sys::path::replace_extension(VFSDir, ".cache"); + // Add the cache directory as a temp so the crash diagnostics pick it up. + C.addTempFile(Args.MakeArgString(VFSDir)); + 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); + if (HaveModules) + Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path); // Pass through all -fmodules-ignore-macro arguments. Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro); @@ -3835,8 +3902,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp); + if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) { + if (Args.hasArg(options::OPT_fbuild_session_timestamp)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "-fbuild-session-timestamp"; + + llvm::sys::fs::file_status Status; + if (llvm::sys::fs::status(A->getValue(), Status)) + D.Diag(diag::err_drv_no_such_file) << A->getValue(); + char TimeStamp[48]; + snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64, + (uint64_t)Status.getLastModificationTime().toEpochTime()); + CmdArgs.push_back(Args.MakeArgString(TimeStamp)); + } + if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) { - if (!Args.getLastArg(options::OPT_fbuild_session_timestamp)) + if (!Args.getLastArg(options::OPT_fbuild_session_timestamp, + options::OPT_fbuild_session_file)) D.Diag(diag::err_drv_modules_validate_once_requires_timestamp); Args.AddLastArg(CmdArgs, @@ -4091,6 +4173,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fpack-struct=1"); } + // Handle -fmax-type-align=N and -fno-type-align + bool SkipMaxTypeAlign = Args.hasArg(options::OPT_fno_max_type_align); + if (Arg *A = Args.getLastArg(options::OPT_fmax_type_align_EQ)) { + if (!SkipMaxTypeAlign) { + std::string MaxTypeAlignStr = "-fmax-type-align="; + MaxTypeAlignStr += A->getValue(); + CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr)); + } + } else if (getToolChain().getTriple().isOSDarwin()) { + if (!SkipMaxTypeAlign) { + std::string MaxTypeAlignStr = "-fmax-type-align=16"; + CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr)); + } + } + if (KernelOrKext || isNoCommonDefault(getToolChain().getTriple())) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); @@ -4122,6 +4219,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args) << value; } + // -fexec_charset=UTF-8 is default. Reject others + if (Arg *execCharset = Args.getLastArg( + options::OPT_fexec_charset_EQ)) { + StringRef value = execCharset->getValue(); + if (value != "UTF-8") + D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args) << value; + } + // -fcaret-diagnostics is default. if (!Args.hasFlag(options::OPT_fcaret_diagnostics, options::OPT_fno_caret_diagnostics, true)) @@ -4327,18 +4432,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); + bool OptDisabled = false; for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm), ie = Args.filtered_end(); it != ie; ++it) { (*it)->claim(); // We translate this by hand to the -cc1 argument, since nightly test uses // it and developers have been trained to spell it with -mllvm. - if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") + if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") { CmdArgs.push_back("-disable-llvm-optzns"); - else + OptDisabled = true; + } else (*it)->render(Args, CmdArgs); } + // With -save-temps, we want to save the unoptimized bitcode output from the + // CompileJobAction, so disable optimizations if they are not already + // disabled. + if (Args.hasArg(options::OPT_save_temps) && !OptDisabled && + isa<CompileJobAction>(JA)) + CmdArgs.push_back("-disable-llvm-optzns"); + if (Output.getType() == types::TY_Dependencies) { // Handled with other dependency code. } else if (Output.isFilename()) { @@ -4371,8 +4485,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, SmallString<256> Flags; Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { + SmallString<128> EscapedArg; + EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg); Flags += " "; - Flags += OriginalArgs[i]; + Flags += EscapedArg; } CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(Args.MakeArgString(Flags.str())); @@ -4382,7 +4498,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // can propagate it to the backend. bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux() && - (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA)); + (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) || + isa<BackendJobAction>(JA)); const char *SplitDwarfOut; if (SplitDwarf) { CmdArgs.push_back("-split-dwarf-file"); @@ -4394,18 +4511,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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)); + auto CLCommand = + getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); + C.addCommand(llvm::make_unique<FallbackCommand>(JA, *this, Exec, CmdArgs, + std::move(CLCommand))); } else { - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } // Handle the debug info splitting at object creation time if we're // creating an object. // TODO: Currently only works on linux with newer objcopy. - if (SplitDwarf && !isa<CompileJobAction>(JA)) + if (SplitDwarf && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut); if (Arg *A = Args.getLastArg(options::OPT_pg)) @@ -4722,6 +4840,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // and "clang -emit-llvm -c foo.s" Args.ClaimAllArgs(options::OPT_emit_llvm); + claimNoWarnArgs(Args); + // Invoke ourselves in -cc1as mode. // // FIXME: Implement custom jobs for internal actions. @@ -4801,8 +4921,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = getToolChain().getDriver().getClangProgramPath(); Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { + SmallString<128> EscapedArg; + EscapeSpacesAndBackslashes(OriginalArgs[i], EscapedArg); Flags += " "; - Flags += OriginalArgs[i]; + Flags += EscapedArg; } CmdArgs.push_back("-dwarf-debug-flags"); CmdArgs.push_back(Args.MakeArgString(Flags.str())); @@ -4833,7 +4955,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); // Handle the debug info splitting at object creation time if we're // creating an object. @@ -4844,6 +4966,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, SplitDebugName(Args, Inputs)); } +void GnuTool::anchor() {} + void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4876,19 +5000,10 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, RenderExtraToolArgs(JA, CmdArgs); // If using a driver driver, force the arch. - llvm::Triple::ArchType Arch = getToolChain().getArch(); if (getToolChain().getTriple().isOSDarwin()) { CmdArgs.push_back("-arch"); - - // FIXME: Remove these special cases. - if (Arch == llvm::Triple::ppc) - CmdArgs.push_back("ppc"); - else if (Arch == llvm::Triple::ppc64) - CmdArgs.push_back("ppc64"); - else if (Arch == llvm::Triple::ppc64le) - CmdArgs.push_back("ppc64le"); - else - CmdArgs.push_back(Args.MakeArgString(getToolChain().getArchName())); + CmdArgs.push_back( + Args.MakeArgString(getToolChain().getDefaultUniversalArchName())); } // Try to force gcc to match the tool chain we want, if we recognize @@ -4896,6 +5011,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: The triple class should directly provide the information we want // here. + llvm::Triple::ArchType Arch = getToolChain().getArch(); if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) CmdArgs.push_back("-m32"); else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 || @@ -4966,7 +5082,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA, @@ -5006,6 +5122,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; @@ -5062,7 +5179,7 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *GCCName = "hexagon-as"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, @@ -5139,8 +5256,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, const std::string MarchSuffix = "/" + MarchString; const std::string G0Suffix = "/G0"; const std::string MarchG0Suffix = MarchSuffix + G0Suffix; - const std::string RootDir = toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir) - + "/"; + const std::string RootDir = + toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/"; const std::string StartFilesDir = RootDir + "hexagon/lib" + (buildingLib @@ -5228,7 +5345,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, } std::string Linker = ToolChain.GetProgramPath("hexagon-ld"); - C.addCommand(new Command(JA, *this, Args.MakeArgString(Linker), CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + CmdArgs)); } // Hexagon tools end. @@ -5293,12 +5411,12 @@ const char *arm::getLLVMArchSuffixForARM(StringRef CPU) { .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-a5", "cortex-a7", "cortex-a8", "v7") + .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7") .Cases("cortex-r4", "cortex-r5", "v7r") .Case("cortex-m0", "v6m") .Case("cortex-m3", "v7m") - .Case("cortex-m4", "v7em") + .Cases("cortex-m4", "cortex-m7", "v7em") .Case("swift", "v7s") .Case("cyclone", "v8") .Cases("cortex-a53", "cortex-a57", "v8") @@ -5310,6 +5428,11 @@ bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { return A && (A->getValue() == StringRef(Value)); } +bool mips::isUCLibc(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_m_libc_Group); + return A && A->getOption().matches(options::OPT_muclibc); +} + 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()) @@ -5366,8 +5489,9 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm) .Cases("armv7s", "xscale", llvm::Triple::arm) - .Case("arm64", llvm::Triple::arm64) + .Case("arm64", llvm::Triple::aarch64) .Case("r600", llvm::Triple::r600) + .Case("amdgcn", llvm::Triple::amdgcn) .Case("nvptx", llvm::Triple::nvptx) .Case("nvptx64", llvm::Triple::nvptx64) .Case("amdil", llvm::Triple::amdil) @@ -5484,7 +5608,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void darwin::MachOTool::anchor() {} @@ -5700,6 +5824,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { assert(Output.getType() == types::TY_Image && "Invalid linker output type."); + // If the number of arguments surpasses the system limits, we will encode the + // input files in a separate file, shortening the command line. To this end, + // build a list of input file names that can be passed via a file with the + // -filelist linker option. + llvm::opt::ArgStringList InputFileList; + // The logic here is derived from gcc's behavior; most of which // comes from specs (starting with link_command). Consult gcc for // more information. @@ -5713,7 +5843,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); return; } @@ -5768,7 +5898,23 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - + // Build the input file for -filelist (list of linker input files) in case we + // need it later + for (const auto &II : Inputs) { + if (!II.isFilename()) { + // This is a linker input argument. + // We cannot mix input arguments and file names in a -filelist input, thus + // we prematurely stop our list (remaining files shall be passed as + // arguments). + if (InputFileList.size() > 0) + break; + + continue; + } + + InputFileList.push_back(II.getFilename()); + } + if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -5811,7 +5957,10 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + std::unique_ptr<Command> Cmd = + llvm::make_unique<Command>(JA, *this, Exec, CmdArgs); + Cmd->setInputFileList(std::move(InputFileList)); + C.addCommand(std::move(Cmd)); } void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, @@ -5833,7 +5982,7 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, @@ -5853,7 +6002,7 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, @@ -5876,7 +6025,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -5884,6 +6033,7 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -5896,7 +6046,7 @@ void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -6001,115 +6151,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); -} - -void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { - ArgStringList CmdArgs; - - Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, - options::OPT_Xassembler); - - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); - - for (const auto &II : Inputs) - CmdArgs.push_back(II.getFilename()); - - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("gas")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); -} - -void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { - ArgStringList CmdArgs; - - if ((!Args.hasArg(options::OPT_nostdlib)) && - (!Args.hasArg(options::OPT_shared))) { - CmdArgs.push_back("-e"); - CmdArgs.push_back("_start"); - } - - if (Args.hasArg(options::OPT_static)) { - CmdArgs.push_back("-Bstatic"); - CmdArgs.push_back("-dn"); - } else { -// CmdArgs.push_back("--eh-frame-hdr"); - CmdArgs.push_back("-Bdynamic"); - if (Args.hasArg(options::OPT_shared)) { - CmdArgs.push_back("-shared"); - } else { - CmdArgs.push_back("--dynamic-linker"); - CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1 - } - } - - if (Output.isFilename()) { - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); - } else { - assert(Output.isNothing() && "Invalid output."); - } - - if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) { - if (!Args.hasArg(options::OPT_shared)) { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crt1.o"))); - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crti.o"))); - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crtbegin.o"))); - } else { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crti.o"))); - } - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crtn.o"))); - } - - CmdArgs.push_back(Args.MakeArgString("-L/opt/gcc4/lib/gcc/" - + getToolChain().getTripleString() - + "/4.2.4")); - - Args.AddAllArgs(CmdArgs, options::OPT_L); - Args.AddAllArgs(CmdArgs, options::OPT_T_Group); - Args.AddAllArgs(CmdArgs, options::OPT_e); - - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - - if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nodefaultlibs)) { - // FIXME: For some reason GCC passes -lgcc before adding - // the default system libraries. Just mimic this for now. - CmdArgs.push_back("-lgcc"); - - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-pthread"); - if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back("-lc"); - CmdArgs.push_back("-lgcc"); - } - - if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) { - if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crtend.o"))); - } - - addProfileRT(getToolChain(), Args, CmdArgs); - - const char *Exec = - Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -6117,6 +6159,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; bool NeedsKPIC = false; @@ -6179,7 +6222,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -6311,7 +6354,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -6319,6 +6362,7 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, @@ -6331,7 +6375,7 @@ void bitrig::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -6447,7 +6491,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -6455,6 +6499,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; // When building 32-bit code on FreeBSD/amd64, we have to explicitly @@ -6528,7 +6573,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -6638,7 +6683,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddAllArgs(CmdArgs, options::OPT_L); - const ToolChain::path_list Paths = ToolChain.getFilePaths(); + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); for (const auto &Path : Paths) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); @@ -6651,6 +6696,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (D.IsUsingLTO(Args)) AddGoldPlugin(ToolChain, Args, CmdArgs); + bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib) && @@ -6662,6 +6708,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("-lm"); } + if (NeedsSanitizerDeps) + linkSanitizerRuntimeDeps(ToolChain, CmdArgs); // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. if (Args.hasArg(options::OPT_pg)) @@ -6716,13 +6764,11 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - addSanitizerRuntimes(getToolChain(), Args, CmdArgs); - addProfileRT(ToolChain, Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -6730,6 +6776,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; // GNU as needs different flags for creating the correct output format @@ -6796,7 +6843,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -6832,9 +6879,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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: @@ -6850,6 +6895,23 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, break; } break; + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + CmdArgs.push_back("-m"); + switch (getToolChain().getTriple().getEnvironment()) { + case llvm::Triple::EABI: + case llvm::Triple::GNUEABI: + CmdArgs.push_back("armelfb_nbsd_eabi"); + break; + case llvm::Triple::EABIHF: + case llvm::Triple::GNUEABIHF: + CmdArgs.push_back("armelfb_nbsd_eabihf"); + break; + default: + CmdArgs.push_back("armelfb_nbsd"); + break; + } + break; case llvm::Triple::mips64: case llvm::Triple::mips64el: if (mips::hasMipsAbiArg(Args, "32")) { @@ -6866,6 +6928,16 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf64ltsmip"); } break; + case llvm::Triple::ppc: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32ppc_nbsd"); + break; + + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64ppc"); + break; case llvm::Triple::sparc: CmdArgs.push_back("-m"); @@ -6918,12 +6990,16 @@ 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 >= 40) || Major == 0) { + if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) { switch(getToolChain().getArch()) { + case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: case llvm::Triple::x86: case llvm::Triple::x86_64: useLibgcc = false; @@ -6975,7 +7051,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -6983,6 +7059,8 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); + ArgStringList CmdArgs; bool NeedsKPIC = false; @@ -7148,7 +7226,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); // Handle the debug info splitting at object creation time if we're // creating an object. @@ -7192,8 +7270,8 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, CmdArgs.push_back("-ldl"); } -static StringRef getLinuxDynamicLinker(const ArgList &Args, - const toolchains::Linux &ToolChain) { +static std::string getLinuxDynamicLinker(const ArgList &Args, + const toolchains::Linux &ToolChain) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) { if (ToolChain.getTriple().isArch64Bit()) return "/system/bin/linker64"; @@ -7202,11 +7280,9 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args, } else if (ToolChain.getArch() == llvm::Triple::x86 || ToolChain.getArch() == llvm::Triple::sparc) return "/lib/ld-linux.so.2"; - else if (ToolChain.getArch() == llvm::Triple::aarch64 || - ToolChain.getArch() == llvm::Triple::arm64) + else if (ToolChain.getArch() == llvm::Triple::aarch64) return "/lib/ld-linux-aarch64.so.1"; - else if (ToolChain.getArch() == llvm::Triple::aarch64_be || - ToolChain.getArch() == llvm::Triple::arm64_be) + else if (ToolChain.getArch() == llvm::Triple::aarch64_be) return "/lib/ld-linux-aarch64_be.so.1"; else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) { @@ -7221,24 +7297,38 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args, else return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */ } else if (ToolChain.getArch() == llvm::Triple::mips || - ToolChain.getArch() == llvm::Triple::mipsel) { - if (mips::isNaN2008(Args, ToolChain.getTriple())) - return "/lib/ld-linux-mipsn8.so.1"; - return "/lib/ld.so.1"; - } else if (ToolChain.getArch() == llvm::Triple::mips64 || + ToolChain.getArch() == llvm::Triple::mipsel || + 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"; + StringRef CPUName; + StringRef ABIName; + mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName); + bool IsNaN2008 = mips::isNaN2008(Args, ToolChain.getTriple()); + + StringRef LibDir = llvm::StringSwitch<llvm::StringRef>(ABIName) + .Case("o32", "/lib") + .Case("n32", "/lib32") + .Case("n64", "/lib64") + .Default("/lib"); + StringRef LibName; + if (mips::isUCLibc(Args)) + LibName = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0"; + else + LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1"; + + return (LibDir + "/" + LibName).str(); } else if (ToolChain.getArch() == llvm::Triple::ppc) return "/lib/ld.so.1"; - else if (ToolChain.getArch() == llvm::Triple::ppc64 || - ToolChain.getArch() == llvm::Triple::systemz) + else if (ToolChain.getArch() == llvm::Triple::ppc64) { + if (ppc::hasPPCAbiArg(Args, "elfv2")) + return "/lib64/ld64.so.2"; return "/lib64/ld64.so.1"; - else if (ToolChain.getArch() == llvm::Triple::ppc64le) + } else if (ToolChain.getArch() == llvm::Triple::ppc64le) { + if (ppc::hasPPCAbiArg(Args, "elfv1")) + return "/lib64/ld64.so.1"; return "/lib64/ld64.so.2"; + } else if (ToolChain.getArch() == llvm::Triple::systemz) + return "/lib64/ld64.so.1"; else if (ToolChain.getArch() == llvm::Triple::sparcv9) return "/lib64/ld-linux.so.2"; else if (ToolChain.getArch() == llvm::Triple::x86_64 && @@ -7249,13 +7339,19 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args, } static void AddRunTimeLibs(const ToolChain &TC, const Driver &D, - ArgStringList &CmdArgs, const ArgList &Args) { + ArgStringList &CmdArgs, const ArgList &Args) { // Make use of compiler-rt if --rtlib option is used ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args); - switch(RLT) { + switch (RLT) { case ToolChain::RLT_CompilerRT: - addClangRTLinux(TC, Args, CmdArgs); + switch (TC.getTriple().getOS()) { + default: llvm_unreachable("unsupported OS"); + case llvm::Triple::Win32: + case llvm::Triple::Linux: + addClangRT(TC, Args, CmdArgs); + break; + } break; case ToolChain::RLT_Libgcc: AddLibgcc(TC.getTriple(), D, CmdArgs, Args); @@ -7263,6 +7359,53 @@ static void AddRunTimeLibs(const ToolChain &TC, const Driver &D, } } +static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { + switch (T.getArch()) { + case llvm::Triple::x86: + return "elf_i386"; + case llvm::Triple::aarch64: + return "aarch64linux"; + case llvm::Triple::aarch64_be: + return "aarch64_be_linux"; + case llvm::Triple::arm: + case llvm::Triple::thumb: + return "armelf_linux_eabi"; + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + return "armebelf_linux_eabi"; /* TODO: check which NAME. */ + case llvm::Triple::ppc: + return "elf32ppclinux"; + case llvm::Triple::ppc64: + return "elf64ppc"; + case llvm::Triple::ppc64le: + return "elf64lppc"; + case llvm::Triple::sparc: + return "elf32_sparc"; + case llvm::Triple::sparcv9: + return "elf64_sparc"; + case llvm::Triple::mips: + return "elf32btsmip"; + case llvm::Triple::mipsel: + return "elf32ltsmip"; + case llvm::Triple::mips64: + if (mips::hasMipsAbiArg(Args, "n32")) + return "elf32btsmipn32"; + return "elf64btsmip"; + case llvm::Triple::mips64el: + if (mips::hasMipsAbiArg(Args, "n32")) + return "elf32ltsmipn32"; + return "elf64ltsmip"; + case llvm::Triple::systemz: + return "elf64_s390"; + case llvm::Triple::x86_64: + if (T.getEnvironment() == llvm::Triple::GNUX32) + return "elf32_x86_64"; + return "elf_x86_64"; + default: + llvm_unreachable("Unexpected arch"); + } +} + void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -7312,53 +7455,7 @@ 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 || - ToolChain.getArch() == llvm::Triple::arm64) - CmdArgs.push_back("aarch64linux"); - else if (ToolChain.getArch() == llvm::Triple::aarch64_be || - ToolChain.getArch() == llvm::Triple::arm64_be) - CmdArgs.push_back("aarch64_be_linux"); - else if (ToolChain.getArch() == llvm::Triple::arm - || ToolChain.getArch() == llvm::Triple::thumb) - CmdArgs.push_back("armelf_linux_eabi"); - else if (ToolChain.getArch() == llvm::Triple::armeb - || ToolChain.getArch() == llvm::Triple::thumbeb) - CmdArgs.push_back("armebelf_linux_eabi"); /* TODO: check which NAME. */ - else if (ToolChain.getArch() == llvm::Triple::ppc) - CmdArgs.push_back("elf32ppclinux"); - else if (ToolChain.getArch() == llvm::Triple::ppc64) - CmdArgs.push_back("elf64ppc"); - else if (ToolChain.getArch() == llvm::Triple::ppc64le) - CmdArgs.push_back("elf64lppc"); - else if (ToolChain.getArch() == llvm::Triple::sparc) - CmdArgs.push_back("elf32_sparc"); - else if (ToolChain.getArch() == llvm::Triple::sparcv9) - CmdArgs.push_back("elf64_sparc"); - else if (ToolChain.getArch() == llvm::Triple::mips) - CmdArgs.push_back("elf32btsmip"); - else if (ToolChain.getArch() == llvm::Triple::mipsel) - CmdArgs.push_back("elf32ltsmip"); - else if (ToolChain.getArch() == llvm::Triple::mips64) { - if (mips::hasMipsAbiArg(Args, "n32")) - CmdArgs.push_back("elf32btsmipn32"); - else - CmdArgs.push_back("elf64btsmip"); - } - else if (ToolChain.getArch() == llvm::Triple::mips64el) { - if (mips::hasMipsAbiArg(Args, "n32")) - CmdArgs.push_back("elf32ltsmipn32"); - else - CmdArgs.push_back("elf64ltsmip"); - } - else if (ToolChain.getArch() == llvm::Triple::systemz) - CmdArgs.push_back("elf64_s390"); - else if (ToolChain.getArch() == llvm::Triple::x86_64 && - ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32) - CmdArgs.push_back("elf32_x86_64"); - else - CmdArgs.push_back("elf_x86_64"); + CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args)); if (Args.hasArg(options::OPT_static)) { if (ToolChain.getArch() == llvm::Triple::arm || @@ -7422,7 +7519,7 @@ 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(); + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); for (const auto &Path : Paths) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); @@ -7433,9 +7530,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); + bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); - - addSanitizerRuntimes(getToolChain(), Args, CmdArgs); // The profile runtime also needs access to system libraries. addProfileRT(getToolChain(), Args, CmdArgs); @@ -7457,6 +7553,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); + if (NeedsSanitizerDeps) + linkSanitizerRuntimeDeps(ToolChain, CmdArgs); + LibOpenMP UsedOpenMPLib = LibUnknown; if (Args.hasArg(options::OPT_fopenmp)) { UsedOpenMPLib = LibGOMP; @@ -7513,7 +7612,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, } } - C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); + C.addCommand( + llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -7521,6 +7621,7 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -7532,7 +7633,7 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -7586,7 +7687,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } /// DragonFly Tools @@ -7598,6 +7699,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; // When building 32-bit code on DragonFly/pc64, we have to explicitly @@ -7614,7 +7716,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -7622,12 +7724,9 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - bool UseGCC47 = false; const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; - - if (llvm::sys::fs::exists("/usr/lib/gcc47", UseGCC47)) - UseGCC47 = false; + bool UseGCC47 = llvm::sys::fs::exists("/usr/lib/gcc47"); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); @@ -7764,16 +7863,27 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); -} + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); +} + +// Try to find Exe from a Visual Studio distribution. This first tries to find +// an installed copy of Visual Studio and, failing that, looks in the PATH, +// making sure that whatever executable that's found is not a same-named exe +// from clang itself to prevent clang from falling back to itself. +static std::string FindVisualStudioExecutable(const ToolChain &TC, + const char *Exe, + const char *ClangProgramPath) { + const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); + std::string visualStudioBinDir; + if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath, + visualStudioBinDir)) { + SmallString<128> FilePath(visualStudioBinDir); + llvm::sys::path::append(FilePath, Exe); + if (llvm::sys::fs::can_execute(FilePath.c_str())) + return FilePath.str(); + } -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)); + return Exe; } void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -7782,28 +7892,56 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; + const ToolChain &TC = getToolChain(); - if (Output.isFilename()) { + assert((Output.isFilename() || Output.isNothing()) && "invalid output"); + if (Output.isFilename()) CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + Output.getFilename())); - } else { - assert(Output.isNothing() && "Invalid output."); - } if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles) && - !C.getDriver().IsCLMode()) { + !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode()) CmdArgs.push_back("-defaultlib:libcmt"); + + if (!llvm::sys::Process::GetEnv("LIB")) { + // If the VC environment hasn't been configured (perhaps because the user + // did not run vcvarsall), try to build a consistent link environment. If + // the environment variable is set however, assume the user knows what he's + // doing. + std::string VisualStudioDir; + const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); + if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) { + SmallString<128> LibDir(VisualStudioDir); + llvm::sys::path::append(LibDir, "VC", "lib"); + switch (MSVC.getArch()) { + case llvm::Triple::x86: + // x86 just puts the libraries directly in lib + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(LibDir, "amd64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(LibDir, "arm"); + break; + default: + break; + } + CmdArgs.push_back( + Args.MakeArgString(std::string("-libpath:") + LibDir.c_str())); + } + + std::string WindowsSdkLibPath; + if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + WindowsSdkLibPath.c_str())); } CmdArgs.push_back("-nologo"); - if (Args.hasArg(options::OPT_g_Group)) { + if (Args.hasArg(options::OPT_g_Group)) CmdArgs.push_back("-debug"); - } bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd); - if (DLL) { CmdArgs.push_back(Args.MakeArgString("-dll")); @@ -7813,32 +7951,81 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, ImplibName.str())); } - if (getToolChain().getSanitizerArgs().needsAsanRt()) { + if (TC.getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); - // FIXME: Handle 64-bit. - if (DLL) { - addSanitizerRTWindows(getToolChain(), Args, CmdArgs, - "asan_dll_thunk-i386"); + if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { + static const char *CompilerRTComponents[] = { + "asan_dynamic", + "asan_dynamic_runtime_thunk", + }; + for (const auto &Component : CompilerRTComponents) + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component))); + // Make sure the dynamic runtime thunk is not optimized out at link time + // to ensure proper SEH handling. + CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor")); + } else if (DLL) { + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk"))); } else { - addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386"); - addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386"); + static const char *CompilerRTComponents[] = { + "asan", + "asan_cxx", + }; + for (const auto &Component : CompilerRTComponents) + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component))); } } - Args.AddAllArgValues(CmdArgs, options::OPT_l); Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); - // Add filenames immediately. - for (const auto &Input : Inputs) - if (Input.isFilename()) + // Add filenames, libraries, and other linker inputs. + for (const auto &Input : Inputs) { + if (Input.isFilename()) { CmdArgs.push_back(Input.getFilename()); - else - Input.getInputArg().renderAsInput(Args, CmdArgs); + continue; + } - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + const Arg &A = Input.getInputArg(); + + // Render -l options differently for the MSVC linker. + if (A.getOption().matches(options::OPT_l)) { + StringRef Lib = A.getValue(); + const char *LinkLibArg; + if (Lib.endswith(".lib")) + LinkLibArg = Args.MakeArgString(Lib); + else + LinkLibArg = Args.MakeArgString(Lib + ".lib"); + CmdArgs.push_back(LinkLibArg); + continue; + } + + // Otherwise, this is some other kind of linker input option like -Wl, -z, + // or -L. Render it, even if MSVC doesn't understand it. + A.renderAsInput(Args, CmdArgs); + } + + // We need to special case some linker paths. In the case of lld, we need to + // translate 'lld' into 'lld-link', and in the case of the regular msvc + // linker, we need to use a special search algorithm. + llvm::SmallString<128> linkPath; + StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link"); + if (Linker.equals_lower("lld")) + Linker = "lld-link"; + + if (Linker.equals_lower("link")) { + // If we're using the MSVC linker, it's not sufficient to just use link + // from the program PATH, because other environments like GnuWin32 install + // their own link.exe which may come first. + linkPath = FindVisualStudioExecutable(TC, "link.exe", + C.getDriver().getClangProgramPath()); + } else { + linkPath = Linker; + llvm::sys::path::replace_extension(linkPath, "exe"); + linkPath = TC.GetProgramPath(linkPath.c_str()); + } + + const char *Exec = Args.MakeArgString(linkPath); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA, @@ -7849,40 +8036,10 @@ void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput)); } -// Try to find FallbackName on PATH that is not identical to ClangProgramPath. -// If one cannot be found, return FallbackName. -// We do this special search to prevent clang-cl from falling back onto itself -// if it's available as cl.exe on the path. -static std::string FindFallback(const char *FallbackName, - const char *ClangProgramPath) { - llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH"); - if (!OptPath.hasValue()) - return FallbackName; - - const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; - SmallVector<StringRef, 8> PathSegments; - llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); - - for (size_t i = 0, e = PathSegments.size(); i != e; ++i) { - const StringRef &PathSegment = PathSegments[i]; - if (PathSegment.empty()) - continue; - - SmallString<128> FilePath(PathSegment); - llvm::sys::path::append(FilePath, FallbackName); - if (llvm::sys::fs::can_execute(Twine(FilePath)) && - !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath)) - return FilePath.str(); - } - - return FallbackName; -} - -Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { +std::unique_ptr<Command> visualstudio::Compile::GetCommand( + Compilation &C, const JobAction &JA, const InputInfo &Output, + const InputInfoList &Inputs, const ArgList &Args, + const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("/nologo"); CmdArgs.push_back("/c"); // Compile only. @@ -7960,8 +8117,10 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, CmdArgs.push_back(Fo); const Driver &D = getToolChain().getDriver(); - std::string Exec = FindFallback("cl.exe", D.getClangProgramPath()); - return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); + std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe", + D.getClangProgramPath()); + return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + CmdArgs); } @@ -7973,6 +8132,7 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + claimNoWarnArgs(Args); ArgStringList CmdArgs; CmdArgs.push_back("-o"); @@ -7998,7 +8158,7 @@ void XCore::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); } void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -8018,12 +8178,189 @@ void XCore::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_v)) CmdArgs.push_back("-v"); - ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple()); - if (EH.ShouldUseExceptionTables) + if (exceptionSettings(Args, getToolChain().getTriple())) CmdArgs.push_back("-fexceptions"); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); +} + +void CrossWindows::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + claimNoWarnArgs(Args); + const auto &TC = + static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain()); + ArgStringList CmdArgs; + const char *Exec; + + switch (TC.getArch()) { + default: llvm_unreachable("unsupported architecture"); + case llvm::Triple::arm: + case llvm::Triple::thumb: + break; + case llvm::Triple::x86: + CmdArgs.push_back("--32"); + break; + case llvm::Triple::x86_64: + CmdArgs.push_back("--64"); + break; + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + for (const auto &Input : Inputs) + CmdArgs.push_back(Input.getFilename()); + + const std::string Assembler = TC.GetProgramPath("as"); + Exec = Args.MakeArgString(Assembler); + + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); +} + +void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const auto &TC = + static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain()); + const llvm::Triple &T = TC.getTriple(); + const Driver &D = TC.getDriver(); + SmallString<128> EntryPoint; + ArgStringList CmdArgs; + const char *Exec; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo" + Args.ClaimAllArgs(options::OPT_w); + // Other warning options are already handled somewhere else. + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("--strip-all"); + + CmdArgs.push_back("-m"); + switch (TC.getArch()) { + default: llvm_unreachable("unsupported architecture"); + case llvm::Triple::arm: + case llvm::Triple::thumb: + // FIXME: this is incorrect for WinCE + CmdArgs.push_back("thumb2pe"); + break; + case llvm::Triple::x86: + CmdArgs.push_back("i386pe"); + EntryPoint.append("_"); + break; + case llvm::Triple::x86_64: + CmdArgs.push_back("i386pep"); + break; + } + + if (Args.hasArg(options::OPT_shared)) { + switch (T.getArch()) { + default: llvm_unreachable("unsupported architecture"); + case llvm::Triple::arm: + case llvm::Triple::thumb: + case llvm::Triple::x86_64: + EntryPoint.append("_DllMainCRTStartup"); + break; + case llvm::Triple::x86: + EntryPoint.append("_DllMainCRTStartup@12"); + break; + } + + CmdArgs.push_back("-shared"); + CmdArgs.push_back("-Bdynamic"); + + CmdArgs.push_back("--enable-auto-image-base"); + + CmdArgs.push_back("--entry"); + CmdArgs.push_back(Args.MakeArgString(EntryPoint)); + } else { + EntryPoint.append("mainCRTStartup"); + + CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic" + : "-Bdynamic"); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back("--entry"); + CmdArgs.push_back(Args.MakeArgString(EntryPoint)); + } + + // FIXME: handle subsystem + } + + // NOTE: deal with multiple definitions on Windows (e.g. COMDAT) + CmdArgs.push_back("--allow-multiple-definition"); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) { + SmallString<261> ImpLib(Output.getFilename()); + llvm::sys::path::replace_extension(ImpLib, ".lib"); + + CmdArgs.push_back("--out-implib"); + CmdArgs.push_back(Args.MakeArgString(ImpLib)); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + const std::string CRTPath(D.SysRoot + "/usr/lib/"); + const char *CRTBegin; + + CRTBegin = + Args.hasArg(options::OPT_shared) ? "crtbeginS.obj" : "crtbegin.obj"; + CmdArgs.push_back(Args.MakeArgString(CRTPath + CRTBegin)); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + + const auto &Paths = TC.getFilePaths(); + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs); + + if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (StaticCXX) + CmdArgs.push_back("-Bstatic"); + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + if (StaticCXX) + CmdArgs.push_back("-Bdynamic"); + } + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + // TODO handle /MT[d] /MD[d] + CmdArgs.push_back("-lmsvcrt"); + AddRunTimeLibs(TC, D, CmdArgs, Args); + } + } + + const std::string Linker = TC.GetProgramPath("ld"); + Exec = Args.MakeArgString(Linker); + + C.addCommand(llvm::make_unique<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 4c89676..6647f39 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LIB_DRIVER_TOOLS_H_ -#define CLANG_LIB_DRIVER_TOOLS_H_ +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLS_H #include "clang/Driver/Tool.h" #include "clang/Driver/Types.h" @@ -63,6 +63,8 @@ using llvm::opt::ArgStringList; llvm::opt::ArgStringList &CmdArgs) const; void AddMIPSTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + void AddPPCTargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; void AddR600TargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; void AddSparcTargetArgs(const llvm::opt::ArgList &Args, @@ -88,11 +90,12 @@ using llvm::opt::ArgStringList; mutable std::unique_ptr<visualstudio::Compile> CLFallback; public: - Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {} + Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC, RF_Full) {} bool hasGoodDiagnostics() const override { return true; } bool hasIntegratedAssembler() const override { return true; } bool hasIntegratedCPP() const override { return true; } + bool canEmitIR() const override { return true; } void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -104,7 +107,8 @@ using llvm::opt::ArgStringList; class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool { public: ClangAs(const ToolChain &TC) : Tool("clang::as", - "clang integrated assembler", TC) {} + "clang integrated assembler", TC, + RF_Full) {} bool hasGoodDiagnostics() const override { return true; } bool hasIntegratedAssembler() const override { return false; } @@ -116,12 +120,22 @@ using llvm::opt::ArgStringList; const char *LinkingOutput) const override; }; + /// \brief Base class for all GNU tools that provide the same behavior when + /// it comes to response files support + class GnuTool : public Tool { + virtual void anchor(); + + public: + GnuTool(const char *Name, const char *ShortName, const ToolChain &TC) + : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {} + }; + /// gcc - Generic GCC tool implementations. namespace gcc { - class LLVM_LIBRARY_VISIBILITY Common : public Tool { + class LLVM_LIBRARY_VISIBILITY Common : public GnuTool { public: Common(const char *Name, const char *ShortName, - const ToolChain &TC) : Tool(Name, ShortName, TC) {} + const ToolChain &TC) : GnuTool(Name, ShortName, TC) {} void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -176,9 +190,9 @@ namespace gcc { namespace hexagon { // For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile and Compile. // We simply use "clang -cc1" for those actions. - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("hexagon::Assemble", + Assemble(const ToolChain &TC) : GnuTool("hexagon::Assemble", "hexagon-as", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -191,9 +205,9 @@ namespace hexagon { const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("hexagon::Link", + Link(const ToolChain &TC) : GnuTool("hexagon::Link", "hexagon-ld", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -221,11 +235,16 @@ namespace mips { const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName); bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); + bool isUCLibc(const llvm::opt::ArgList &Args); bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName); } +namespace ppc { + bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value); +} + namespace darwin { llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); @@ -241,8 +260,13 @@ namespace darwin { } public: - MachOTool(const char *Name, const char *ShortName, - const ToolChain &TC) : Tool(Name, ShortName, TC) {} + MachOTool( + const char *Name, const char *ShortName, const ToolChain &TC, + ResponseFileSupport ResponseSupport = RF_None, + llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8, + const char *ResponseFlag = "@") + : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding, + ResponseFlag) {} }; class LLVM_LIBRARY_VISIBILITY Assemble : public MachOTool { @@ -265,7 +289,9 @@ namespace darwin { const InputInfoList &Inputs) const; public: - Link(const ToolChain &TC) : MachOTool("darwin::Link", "linker", TC) {} + Link(const ToolChain &TC) : MachOTool("darwin::Link", "linker", TC, + RF_FileList, llvm::sys::WEM_UTF8, + "-filelist") {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -320,9 +346,9 @@ namespace darwin { /// openbsd -- Directly call GNU Binutils assembler and linker namespace openbsd { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler", + Assemble(const ToolChain &TC) : GnuTool("openbsd::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -333,9 +359,9 @@ namespace openbsd { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("openbsd::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -349,9 +375,9 @@ namespace openbsd { /// bitrig -- Directly call GNU Binutils assembler and linker namespace bitrig { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("bitrig::Assemble", "assembler", + Assemble(const ToolChain &TC) : GnuTool("bitrig::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -361,9 +387,9 @@ namespace bitrig { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("bitrig::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("bitrig::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -377,9 +403,9 @@ namespace bitrig { /// freebsd -- Directly call GNU Binutils assembler and linker namespace freebsd { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler", + Assemble(const ToolChain &TC) : GnuTool("freebsd::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -389,9 +415,9 @@ namespace freebsd { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("freebsd::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -405,11 +431,11 @@ namespace freebsd { /// netbsd -- Directly call GNU Binutils assembler and linker namespace netbsd { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: Assemble(const ToolChain &TC) - : Tool("netbsd::Assemble", "assembler", TC) {} + : GnuTool("netbsd::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -418,11 +444,11 @@ namespace netbsd { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: Link(const ToolChain &TC) - : Tool("netbsd::Link", "linker", TC) {} + : GnuTool("netbsd::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -436,9 +462,9 @@ namespace netbsd { /// Directly call GNU Binutils' assembler and linker. namespace gnutools { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("GNU::Assemble", "assembler", TC) {} + Assemble(const ToolChain &TC) : GnuTool("GNU::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -448,9 +474,9 @@ namespace gnutools { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("GNU::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("GNU::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -464,9 +490,9 @@ namespace gnutools { } /// minix -- Directly call GNU Binutils assembler and linker namespace minix { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler", + Assemble(const ToolChain &TC) : GnuTool("minix::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -477,9 +503,9 @@ namespace minix { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("minix::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("minix::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -520,39 +546,11 @@ namespace solaris { }; } // end namespace solaris - /// auroraux -- Directly call GNU Binutils assembler and linker -namespace auroraux { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { - public: - Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler", - TC) {} - - bool hasIntegratedCPP() const override { return false; } - - void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const override; - }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { - public: - Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", TC) {} - - bool hasIntegratedCPP() const override { return false; } - bool isLinkJob() const override { return true; } - - void ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const override; - }; -} // end namespace auroraux - /// dragonfly -- Directly call GNU Binutils assembler and linker namespace dragonfly { - class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + class LLVM_LIBRARY_VISIBILITY Assemble : public GnuTool { public: - Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler", + Assemble(const ToolChain &TC) : GnuTool("dragonfly::Assemble", "assembler", TC) {} bool hasIntegratedCPP() const override { return false; } @@ -562,9 +560,9 @@ namespace dragonfly { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; - class LLVM_LIBRARY_VISIBILITY Link : public Tool { + class LLVM_LIBRARY_VISIBILITY Link : public GnuTool { public: - Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", TC) {} + Link(const ToolChain &TC) : GnuTool("dragonfly::Link", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -581,7 +579,8 @@ namespace dragonfly { namespace visualstudio { class LLVM_LIBRARY_VISIBILITY Link : public Tool { public: - Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {} + Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC, + RF_Full, llvm::sys::WEM_UTF16) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -594,7 +593,8 @@ namespace visualstudio { class LLVM_LIBRARY_VISIBILITY Compile : public Tool { public: - Compile(const ToolChain &TC) : Tool("visualstudio::Compile", "compiler", TC) {} + Compile(const ToolChain &TC) : Tool("visualstudio::Compile", "compiler", TC, + RF_Full, llvm::sys::WEM_UTF16) {} bool hasIntegratedAssembler() const override { return true; } bool hasIntegratedCPP() const override { return true; } @@ -605,11 +605,11 @@ namespace visualstudio { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; - Command *GetCommand(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, - const char *LinkingOutput) const; + std::unique_ptr<Command> GetCommand(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const; }; } // end namespace visualstudio @@ -646,9 +646,35 @@ namespace XCore { }; } // end namespace XCore. +namespace CrossWindows { +class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { +public: + Assemble(const ToolChain &TC) : Tool("CrossWindows::Assemble", "as", TC) { } + + bool hasIntegratedCPP() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + +class LLVM_LIBRARY_VISIBILITY Link : public Tool { +public: + Link(const ToolChain &TC) : Tool("CrossWindows::Link", "ld", TC, RF_Full) {} + + 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 toolchains } // end namespace driver } // end namespace clang -#endif // CLANG_LIB_DRIVER_TOOLS_H_ +#endif diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index 3538dbc..6ee764c 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -143,6 +143,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) { .Case("S", TY_Asm) .Case("o", TY_Object) .Case("obj", TY_Object) + .Case("lib", TY_Object) .Case("ii", TY_PP_CXX) .Case("mi", TY_PP_ObjC) .Case("mm", TY_ObjCXX) @@ -202,6 +203,7 @@ void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) { } else { if (!onlyAssembleType(Id)) { P.push_back(phases::Compile); + P.push_back(phases::Backend); } P.push_back(phases::Assemble); } diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp deleted file mode 100644 index 913425a..0000000 --- a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp +++ /dev/null @@ -1,338 +0,0 @@ -//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ToolChains.h" -#include "clang/Basic/CharInfo.h" -#include "clang/Basic/Version.h" -#include "clang/Driver/Compilation.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/Options.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/Option/Arg.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Path.h" - -// Include the necessary headers to interface with the Windows registry and -// environment. -#if defined(LLVM_ON_WIN32) -#define USE_WIN32 -#endif - -#ifdef USE_WIN32 - #define WIN32_LEAN_AND_MEAN - #define NOGDI - #define NOMINMAX - #include <windows.h> -#endif - -using namespace clang::driver; -using namespace clang::driver::toolchains; -using namespace clang; -using namespace llvm::opt; - -Windows::Windows(const Driver &D, const llvm::Triple& Triple, - const ArgList &Args) - : ToolChain(D, Triple, Args) { -} - -Tool *Windows::buildLinker() const { - return new tools::visualstudio::Link(*this); -} - -Tool *Windows::buildAssembler() const { - if (getTriple().isOSBinFormatMachO()) - return new tools::darwin::Assemble(*this); - getDriver().Diag(clang::diag::err_no_external_assembler); - return nullptr; -} - -bool Windows::IsIntegratedAssemblerDefault() const { - return true; -} - -bool Windows::IsUnwindTablesDefault() const { - // FIXME: LLVM's lowering of Win64 data is broken right now. MSVC's linker - // says that our object files provide invalid .pdata contributions. Until - // that is fixed, don't ask for unwind tables. - return false; - //return getArch() == llvm::Triple::x86_64; -} - -bool Windows::isPICDefault() const { - return getArch() == llvm::Triple::x86_64; -} - -bool Windows::isPIEDefault() const { - return false; -} - -bool Windows::isPICDefaultForced() const { - return getArch() == llvm::Triple::x86_64; -} - -/// \brief Read registry string. -/// This also supports a means to look for high-versioned keys by use -/// of a $VERSION placeholder in the key path. -/// $VERSION in the key path is a placeholder for the version number, -/// causing the highest value path to be searched for and used. -/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". -/// There can be additional characters in the component. Only the numberic -/// characters are compared. -static bool getSystemRegistryString(const char *keyPath, const char *valueName, - char *value, size_t maxLength) { -#ifndef USE_WIN32 - return false; -#else - HKEY hRootKey = NULL; - HKEY hKey = NULL; - const char* subKey = NULL; - DWORD valueType; - DWORD valueSize = maxLength - 1; - long lResult; - bool returnValue = false; - - if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { - hRootKey = HKEY_CLASSES_ROOT; - subKey = keyPath + 18; - } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { - hRootKey = HKEY_USERS; - subKey = keyPath + 11; - } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { - hRootKey = HKEY_LOCAL_MACHINE; - subKey = keyPath + 19; - } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { - hRootKey = HKEY_CURRENT_USER; - subKey = keyPath + 18; - } else { - return false; - } - - const char *placeHolder = strstr(subKey, "$VERSION"); - char bestName[256]; - bestName[0] = '\0'; - // If we have a $VERSION placeholder, do the highest-version search. - if (placeHolder) { - const char *keyEnd = placeHolder - 1; - const char *nextKey = placeHolder; - // Find end of previous key. - while ((keyEnd > subKey) && (*keyEnd != '\\')) - keyEnd--; - // Find end of key containing $VERSION. - while (*nextKey && (*nextKey != '\\')) - nextKey++; - size_t partialKeyLength = keyEnd - subKey; - char partialKey[256]; - if (partialKeyLength > sizeof(partialKey)) - partialKeyLength = sizeof(partialKey); - strncpy(partialKey, subKey, partialKeyLength); - partialKey[partialKeyLength] = '\0'; - HKEY hTopKey = NULL; - lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, - &hTopKey); - if (lResult == ERROR_SUCCESS) { - char keyName[256]; - int bestIndex = -1; - double bestValue = 0.0; - DWORD index, size = sizeof(keyName) - 1; - for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, - NULL, NULL, NULL) == ERROR_SUCCESS; index++) { - const char *sp = keyName; - while (*sp && !isDigit(*sp)) - sp++; - if (!*sp) - continue; - const char *ep = sp + 1; - while (*ep && (isDigit(*ep) || (*ep == '.'))) - ep++; - char numBuf[32]; - strncpy(numBuf, sp, sizeof(numBuf) - 1); - numBuf[sizeof(numBuf) - 1] = '\0'; - double dvalue = strtod(numBuf, NULL); - if (dvalue > bestValue) { - // Test that InstallDir is indeed there before keeping this index. - // Open the chosen key path remainder. - strcpy(bestName, keyName); - // Append rest of key. - strncat(bestName, nextKey, sizeof(bestName) - 1); - bestName[sizeof(bestName) - 1] = '\0'; - lResult = RegOpenKeyEx(hTopKey, bestName, 0, - KEY_READ | KEY_WOW64_32KEY, &hKey); - if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); - if (lResult == ERROR_SUCCESS) { - bestIndex = (int)index; - bestValue = dvalue; - returnValue = true; - } - RegCloseKey(hKey); - } - } - size = sizeof(keyName) - 1; - } - RegCloseKey(hTopKey); - } - } else { - lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY, - &hKey); - if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); - if (lResult == ERROR_SUCCESS) - returnValue = true; - RegCloseKey(hKey); - } - } - return returnValue; -#endif // USE_WIN32 -} - -/// \brief Get Windows SDK installation directory. -static bool getWindowsSDKDir(std::string &path) { - char windowsSDKInstallDir[256]; - // Try the Windows registry. - bool hasSDKDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", - "InstallationFolder", - windowsSDKInstallDir, - sizeof(windowsSDKInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasSDKDir && windowsSDKInstallDir[0]) { - path = windowsSDKInstallDir; - return true; - } - return false; -} - -// Get Visual Studio installation directory. -static bool getVisualStudioDir(std::string &path) { - // First check the environment variables that vsvars32.bat sets. - const char* vcinstalldir = getenv("VCINSTALLDIR"); - if (vcinstalldir) { - char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); - if (p) - *p = '\0'; - path = vcinstalldir; - return true; - } - - char vsIDEInstallDir[256]; - char vsExpressIDEInstallDir[256]; - // Then try the windows registry. - bool hasVCDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", - "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); - bool hasVCExpressDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", - "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasVCDir && vsIDEInstallDir[0]) { - char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsIDEInstallDir; - return true; - } - - if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { - char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsExpressIDEInstallDir; - return true; - } - - // Try the environment. - const char *vs100comntools = getenv("VS100COMNTOOLS"); - const char *vs90comntools = getenv("VS90COMNTOOLS"); - const char *vs80comntools = getenv("VS80COMNTOOLS"); - - const char *vscomntools = nullptr; - - // Find any version we can - if (vs100comntools) - vscomntools = vs100comntools; - else if (vs90comntools) - vscomntools = vs90comntools; - else if (vs80comntools) - vscomntools = vs80comntools; - - if (vscomntools && *vscomntools) { - const char *p = strstr(vscomntools, "\\Common7\\Tools"); - path = p ? std::string(vscomntools, p) : vscomntools; - return true; - } - return false; -} - -void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - if (DriverArgs.hasArg(options::OPT_nostdinc)) - return; - - if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { - SmallString<128> P(getDriver().ResourceDir); - llvm::sys::path::append(P, "include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - } - - if (DriverArgs.hasArg(options::OPT_nostdlibinc)) - return; - - // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. - if (const char *cl_include_dir = getenv("INCLUDE")) { - SmallVector<StringRef, 8> Dirs; - StringRef(cl_include_dir) - .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - for (StringRef Dir : Dirs) - addSystemInclude(DriverArgs, CC1Args, Dir); - if (!Dirs.empty()) - return; - } - - std::string VSDir; - std::string WindowsSDKDir; - - // When built with access to the proper Windows APIs, try to actually find - // the correct include paths first. - if (getVisualStudioDir(VSDir)) { - SmallString<128> P; - P = VSDir; - llvm::sys::path::append(P, "VC\\include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - if (getWindowsSDKDir(WindowsSDKDir)) { - P = WindowsSDKDir; - llvm::sys::path::append(P, "include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - } else { - P = VSDir; - llvm::sys::path::append(P, "VC\\PlatformSDK\\Include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - } - return; - } - - // As a fallback, select default install paths. - // FIXME: Don't guess drives and paths like this on Windows. - const StringRef Paths[] = { - "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", - "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", - "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", - "C:/Program Files/Microsoft Visual Studio 8/VC/include", - "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" - }; - addSystemIncludes(DriverArgs, CC1Args, Paths); -} - -void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - // FIXME: There should probably be logic here to find libc++ on Windows. -} |