diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-21 19:57:54 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-21 19:57:54 +0000 | 
| commit | e123fc8fd8677e4dc86f274cffd069e5d56f4a01 (patch) | |
| tree | 806fb806ca9ace304565efd09b494e81ac2aff6f /contrib/llvm/tools/clang/lib/Driver/Driver.cpp | |
| parent | 54db30ce18663e6c2991958f3b5d18362e8e93c4 (diff) | |
| parent | 2298981669bf3bd63335a4be179bc0f96823a8f4 (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Driver.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 215 | 
1 files changed, 145 insertions, 70 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index a784e218f139..396ddf4dd816 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -1,9 +1,8 @@  //===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //  //===----------------------------------------------------------------------===// @@ -39,6 +38,7 @@  #include "ToolChains/NetBSD.h"  #include "ToolChains/OpenBSD.h"  #include "ToolChains/PS4CPU.h" +#include "ToolChains/PPCLinux.h"  #include "ToolChains/RISCVToolchain.h"  #include "ToolChains/Solaris.h"  #include "ToolChains/TCE.h" @@ -90,6 +90,33 @@ using namespace clang::driver;  using namespace clang;  using namespace llvm::opt; +// static +std::string Driver::GetResourcesPath(StringRef BinaryPath, +                                     StringRef CustomResourceDir) { +  // Since the resource directory is embedded in the module hash, it's important +  // that all places that need it call this function, so that they get the +  // exact same string ("a/../b/" and "b/" get different hashes, for example). + +  // Dir is bin/ or lib/, depending on where BinaryPath is. +  std::string Dir = llvm::sys::path::parent_path(BinaryPath); + +  SmallString<128> P(Dir); +  if (CustomResourceDir != "") { +    llvm::sys::path::append(P, CustomResourceDir); +  } else { +    // On Windows, libclang.dll is in bin/. +    // On non-Windows, libclang.so/.dylib is in lib/. +    // With a static-library build of libclang, LibClangPath will contain the +    // path of the embedding binary, which for LLVM binaries will be in bin/. +    // ../lib gets us to lib/ in both cases. +    P = llvm::sys::path::parent_path(Dir); +    llvm::sys::path::append(P, Twine("lib") + CLANG_LIBDIR_SUFFIX, "clang", +                            CLANG_VERSION_STRING); +  } + +  return P.str(); +} +  Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,                 DiagnosticsEngine &Diags,                 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) @@ -106,7 +133,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,    // Provide a sane fallback if no VFS is specified.    if (!this->VFS) -    this->VFS = llvm::vfs::getRealFileSystem(); +    this->VFS = llvm::vfs::createPhysicalFileSystem().release();    Name = llvm::sys::path::filename(ClangExecutable);    Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -120,17 +147,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,  #endif    // Compute the path to the resource directory. -  StringRef ClangResourceDir(CLANG_RESOURCE_DIR); -  SmallString<128> P(Dir); -  if (ClangResourceDir != "") { -    llvm::sys::path::append(P, ClangResourceDir); -  } else { -    StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX); -    P = llvm::sys::path::parent_path(Dir); -    llvm::sys::path::append(P, Twine("lib") + ClangLibdirSuffix, "clang", -                            CLANG_VERSION_STRING); -  } -  ResourceDir = P.str(); +  ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);  }  void Driver::ParseDriverMode(StringRef ProgramName, @@ -230,8 +247,9 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,                            : diag::err_drv_unknown_argument;        Diags.Report(DiagID) << ArgString;      } else { -      DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion -                          : diag::err_drv_unknown_argument_with_suggestion; +      DiagID = IsCLMode() +                   ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion +                   : diag::err_drv_unknown_argument_with_suggestion;        Diags.Report(DiagID) << ArgString << Nearest;      }      ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > @@ -262,11 +280,13 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,      // -{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_print_supported_cpus)) ||               (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||               (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||               (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||               (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||               (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || +             (PhaseArg = DAL.getLastArg(options::OPT_emit_iterface_stubs)) ||               (PhaseArg = DAL.getLastArg(options::OPT__analyze,                                          options::OPT__analyze_auto)) ||               (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { @@ -946,6 +966,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {    InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)                                                : std::move(*CLOptions)); +  // The args for config files or /clang: flags belong to different InputArgList +  // objects than Args. This copies an Arg from one of those other InputArgLists +  // to the ownership of Args.    auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) {        unsigned Index = Args.MakeIndex(Opt->getSpelling());        Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(), @@ -987,6 +1010,11 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {      }    } +  // Check for working directory option before accessing any files +  if (Arg *WD = Args.getLastArg(options::OPT_working_directory)) +    if (VFS->setCurrentWorkingDirectory(WD->getValue())) +      Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue(); +    // FIXME: This stuff needs to go into the Compilation, not the driver.    bool CCCPrintPhases; @@ -1401,11 +1429,13 @@ void Driver::generateCompilationDiagnostics(  }  void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) { -  // Since commandLineFitsWithinSystemLimits() 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. +  // Since commandLineFitsWithinSystemLimits() 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 (Cmd.getCreator().getResponseFilesSupport() == Tool::RF_None || -      llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(), Cmd.getArguments())) +      llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(), +                                                   Cmd.getArguments()))      return;    std::string TmpName = GetTemporaryPath("response", "txt"); @@ -1559,8 +1589,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {    // We want to show cc1-only options only when clang is invoked with -cc1 or    // -Xclang. -  if (std::find(Flags.begin(), Flags.end(), "-Xclang") != Flags.end() || -      std::find(Flags.begin(), Flags.end(), "-cc1") != Flags.end()) +  if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1"))      DisableFlags &= ~options::NoDriverOption;    StringRef Cur; @@ -1625,11 +1654,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {    if (C.getArgs().hasArg(options::OPT_dumpversion)) {      // Since -dumpversion is only implemented for pedantic GCC compatibility, we      // return an answer which matches our definition of __VERSION__. -    // -    // If we want to return a more correct answer some day, then we should -    // introduce a non-pedantically GCC compatible mode to Clang in which we -    // provide sensible definitions for -dumpversion, __VERSION__, etc. -    llvm::outs() << "4.2.1\n"; +    llvm::outs() << CLANG_VERSION_STRING << "\n";      return false;    } @@ -1651,7 +1676,8 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {    }    if (C.getArgs().hasArg(options::OPT_v) || -      C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { +      C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) || +      C.getArgs().hasArg(options::OPT_print_supported_cpus)) {      PrintVersion(C, llvm::errs());      SuppressMissingInputWarning = true;    } @@ -1680,7 +1706,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {      bool separator = false;      for (const std::string &Path : TC.getProgramPaths()) {        if (separator) -        llvm::outs() << ':'; +        llvm::outs() << llvm::sys::EnvPathSeparator;        llvm::outs() << Path;        separator = true;      } @@ -1691,7 +1717,7 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {      for (const std::string &Path : TC.getFilePaths()) {        // Always print a separator. ResourceDir was the first item shown. -      llvm::outs() << ':'; +      llvm::outs() << llvm::sys::EnvPathSeparator;        // Interpretation of leading '=' is needed only for NetBSD.        if (Path[0] == '=')          llvm::outs() << sysroot << Path.substr(1); @@ -1960,31 +1986,20 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,    }  } -/// Check that the file referenced by Value exists. If it doesn't, -/// issue a diagnostic and return false. -static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, -                                   StringRef Value, types::ID Ty) { -  if (!D.getCheckInputsExist()) +bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, +                                    types::ID Ty, bool TypoCorrect) const { +  if (!getCheckInputsExist())      return true;    // stdin always exists.    if (Value == "-")      return true; -  SmallString<64> Path(Value); -  if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { -    if (!llvm::sys::path::is_absolute(Path)) { -      SmallString<64> Directory(WorkDir->getValue()); -      llvm::sys::path::append(Directory, Value); -      Path.assign(Directory); -    } -  } - -  if (D.getVFS().exists(Path)) +  if (getVFS().exists(Value))      return true; -  if (D.IsCLMode()) { -    if (!llvm::sys::path::is_absolute(Twine(Path)) && +  if (IsCLMode()) { +    if (!llvm::sys::path::is_absolute(Twine(Value)) &&          llvm::sys::Process::FindInEnvPath("LIB", Value))        return true; @@ -1996,7 +2011,26 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,      }    } -  D.Diag(clang::diag::err_drv_no_such_file) << Path; +  if (TypoCorrect) { +    // Check if the filename is a typo for an option flag. OptTable thinks +    // that all args that are not known options and that start with / are +    // filenames, but e.g. `/diagnostic:caret` is more likely a typo for +    // the option `/diagnostics:caret` than a reference to a file in the root +    // directory. +    unsigned IncludedFlagsBitmask; +    unsigned ExcludedFlagsBitmask; +    std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = +        getIncludeExcludeOptionFlagMasks(IsCLMode()); +    std::string Nearest; +    if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, +                              ExcludedFlagsBitmask) <= 1) { +      Diag(clang::diag::err_drv_no_such_file_with_suggestion) +          << Value << Nearest; +      return false; +    } +  } + +  Diag(clang::diag::err_drv_no_such_file) << Value;    return false;  } @@ -2019,7 +2053,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,      Arg *Previous = nullptr;      bool ShowNote = false; -    for (Arg *A : Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) { +    for (Arg *A : +         Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) {        if (Previous) {          Diag(clang::diag::warn_drv_overriding_flag_option)            << Previous->getSpelling() << A->getSpelling(); @@ -2084,6 +2119,12 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,                Diag(clang::diag::warn_drv_treating_input_as_cxx)                    << getTypeName(OldTy) << getTypeName(Ty);            } + +          // If running with -fthinlto-index=, extensions that normally identify +          // native object files actually identify LLVM bitcode files. +          if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) && +              Ty == types::TY_Object) +            Ty = types::TY_LLVM_BC;          }          // -ObjC and -ObjC++ override the default language, but only for "source @@ -2112,19 +2153,21 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,          }        } -      if (DiagnoseInputExistence(*this, Args, Value, Ty)) +      if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true))          Inputs.push_back(std::make_pair(Ty, A));      } else if (A->getOption().matches(options::OPT__SLASH_Tc)) {        StringRef Value = A->getValue(); -      if (DiagnoseInputExistence(*this, Args, Value, types::TY_C)) { +      if (DiagnoseInputExistence(Args, Value, types::TY_C, +                                 /*TypoCorrect=*/false)) {          Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());          Inputs.push_back(std::make_pair(types::TY_C, InputArg));        }        A->claim();      } else if (A->getOption().matches(options::OPT__SLASH_Tp)) {        StringRef Value = A->getValue(); -      if (DiagnoseInputExistence(*this, Args, Value, types::TY_CXX)) { +      if (DiagnoseInputExistence(Args, Value, types::TY_CXX, +                                 /*TypoCorrect=*/false)) {          Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue());          Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));        } @@ -2146,7 +2189,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,          Diag(clang::diag::err_drv_unknown_language) << A->getValue();          InputType = types::TY_Object;        } -    } else if (A->getOption().getID() == options::OPT__SLASH_U) { +    } else if (A->getOption().getID() == options::OPT_U) {        assert(A->getNumValues() == 1 && "The /U option has one value.");        StringRef Val = A->getValue(0);        if (Val.find_first_of("/\\") != StringRef::npos) { @@ -2278,6 +2321,9 @@ class OffloadingActionBuilder final {      /// Flag that is set to true if this builder acted on the current input.      bool IsActive = false; + +    /// Flag for -fgpu-rdc. +    bool Relocatable = false;    public:      CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,                            const Driver::InputList &Inputs, @@ -2323,6 +2369,12 @@ class OffloadingActionBuilder final {        // If this is an unbundling action use it as is for each CUDA toolchain.        if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) { + +        // If -fgpu-rdc is disabled, should not unbundle since there is no +        // device code to link. +        if (!Relocatable) +          return ABRT_Inactive; +          CudaDeviceActions.clear();          auto *IA = cast<InputAction>(UA->getInputs().back());          std::string FileName = IA->getInputArg().getAsString(Args); @@ -2394,6 +2446,9 @@ class OffloadingActionBuilder final {            !C.hasOffloadToolChain<Action::OFK_HIP>())          return false; +      Relocatable = Args.hasFlag(options::OPT_fgpu_rdc, +          options::OPT_fno_gpu_rdc, /*Default=*/false); +        const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();        assert(HostTC && "No toolchain for host compilation.");        if (HostTC->getTriple().isNVPTX() || @@ -2579,13 +2634,11 @@ class OffloadingActionBuilder final {    class HIPActionBuilder final : public CudaActionBuilderBase {      /// The linker inputs obtained for each device arch.      SmallVector<ActionList, 8> DeviceLinkerInputs; -    bool Relocatable;    public:      HIPActionBuilder(Compilation &C, DerivedArgList &Args,                       const Driver::InputList &Inputs) -        : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP), -          Relocatable(false) {} +        : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {}      bool canUseBundlerUnbundler() const override { return true; } @@ -2690,13 +2743,6 @@ class OffloadingActionBuilder final {          ++I;        }      } - -    bool initialize() override { -      Relocatable = Args.hasFlag(options::OPT_fgpu_rdc, -          options::OPT_fno_gpu_rdc, /*Default=*/false); - -      return CudaActionBuilderBase::initialize(); -    }    };    /// OpenMP action builder. The host bitcode is passed to the device frontend @@ -3341,6 +3387,18 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,      Args.ClaimAllArgs(options::OPT_cl_compile_Group);    } +  // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom +  // Compile phase that prints out supported cpu models and quits. +  if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) { +    // Use the -mcpu=? flag as the dummy input to cc1. +    Actions.clear(); +    Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C); +    Actions.push_back( +        C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing)); +    for (auto &I : Inputs) +      I.second->claim(); +  } +    // Claim ignored clang-cl options.    Args.ClaimAllArgs(options::OPT_cl_ignored_Group); @@ -3426,6 +3484,8 @@ Action *Driver::ConstructPhaseAction(        return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);      if (Args.hasArg(options::OPT_verify_pch))        return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing); +    if (Args.hasArg(options::OPT_emit_iterface_stubs)) +      return C.MakeAction<CompileJobAction>(Input, types::TY_IFS);      return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);    }    case phases::Backend: { @@ -3963,9 +4023,9 @@ InputInfo Driver::BuildJobsForActionNoCache(      Input.claim();      if (Input.getOption().matches(options::OPT_INPUT)) {        const char *Name = Input.getValue(); -      return InputInfo(A, Name, /* BaseInput = */ Name); +      return InputInfo(A, Name, /* _BaseInput = */ Name);      } -    return InputInfo(A, &Input, /* BaseInput = */ ""); +    return InputInfo(A, &Input, /* _BaseInput = */ "");    }    if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { @@ -4244,10 +4304,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,      Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);      if (CCGenDiagnostics && A) {        SmallString<128> CrashDirectory(A->getValue()); +      if (!getVFS().exists(CrashDirectory)) +        llvm::sys::fs::create_directories(CrashDirectory);        llvm::sys::path::append(CrashDirectory, Split.first);        const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%"; -      std::error_code EC = -          llvm::sys::fs::createUniqueFile(CrashDirectory + Middle + Suffix, TmpName); +      std::error_code EC = llvm::sys::fs::createUniqueFile( +          CrashDirectory + Middle + Suffix, TmpName);        if (EC) {          Diag(clang::diag::err_unable_to_make_temp) << EC.message();          return ""; @@ -4401,6 +4463,11 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {    if (llvm::sys::fs::exists(Twine(P)))      return P.str(); +  SmallString<128> D(Dir); +  llvm::sys::path::append(D, "..", Name); +  if (llvm::sys::fs::exists(Twine(D))) +    return D.str(); +    if (auto P = SearchPaths(TC.getLibraryPaths()))      return *P; @@ -4558,6 +4625,11 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,                 !Target.hasEnvironment())          TC = llvm::make_unique<toolchains::MipsLLVMToolChain>(*this, Target,                                                                Args); +      else if (Target.getArch() == llvm::Triple::ppc || +               Target.getArch() == llvm::Triple::ppc64 || +               Target.getArch() == llvm::Triple::ppc64le) +        TC = llvm::make_unique<toolchains::PPCLinuxToolChain>(*this, Target, +                                                              Args);        else          TC = llvm::make_unique<toolchains::Linux>(*this, Target, Args);        break; @@ -4571,6 +4643,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,        TC = llvm::make_unique<toolchains::Solaris>(*this, Target, Args);        break;      case llvm::Triple::AMDHSA: +    case llvm::Triple::AMDPAL: +    case llvm::Triple::Mesa3D:        TC = llvm::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);        break;      case llvm::Triple::Win32: @@ -4750,7 +4824,8 @@ bool Driver::GetReleaseVersion(StringRef Str,    return false;  } -std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const { +std::pair<unsigned, unsigned> +Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {    unsigned IncludedFlagsBitmask = 0;    unsigned ExcludedFlagsBitmask = options::NoDriverOption;  | 
