diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /clang/lib/Driver/Driver.cpp | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
download | src-344a3780b2e33f6ca763666c380202b18aab72a3.tar.gz src-344a3780b2e33f6ca763666c380202b18aab72a3.zip |
Vendor import of llvm-project main 88e66fa60ae5, the last commit beforevendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
the upstream release/13.x branch was created.
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 431 |
1 files changed, 310 insertions, 121 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 418e1d3e8ec9..5c323cb6ea23 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -7,9 +7,9 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Driver.h" -#include "InputInfo.h" #include "ToolChains/AIX.h" #include "ToolChains/AMDGPU.h" +#include "ToolChains/AMDGPUOpenMP.h" #include "ToolChains/AVR.h" #include "ToolChains/Ananas.h" #include "ToolChains/BareMetal.h" @@ -53,6 +53,7 @@ #include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/InputInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" @@ -62,6 +63,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" @@ -76,6 +78,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" @@ -133,13 +136,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - DriverTitle(Title), CCPrintOptionsFilename(nullptr), - CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), + DriverTitle(Title), CCPrintStatReportFilename(), CCPrintOptionsFilename(), + CCPrintHeadersFilename(), CCLogDiagnosticsFilename(), CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), - TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc), - CheckInputsExist(true), GenReproducer(false), - SuppressMissingInputWarning(false) { + CCPrintProcessStats(false), TargetTriple(TargetTriple), + CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true), + GenReproducer(false), SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) this->VFS = llvm::vfs::getRealFileSystem(); @@ -166,28 +169,9 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); } -void Driver::ParseDriverMode(StringRef ProgramName, - ArrayRef<const char *> Args) { - if (ClangNameParts.isEmpty()) - ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName); - setDriverModeFromOption(ClangNameParts.DriverMode); - - for (const char *ArgPtr : Args) { - // Ignore nullptrs, they are the response file's EOL markers. - if (ArgPtr == nullptr) - continue; - const StringRef Arg = ArgPtr; - setDriverModeFromOption(Arg); - } -} - -void Driver::setDriverModeFromOption(StringRef Opt) { - const std::string OptName = +void Driver::setDriverMode(StringRef Value) { + static const std::string OptName = getOpts().getOption(options::OPT_driver_mode).getPrefixedName(); - if (!Opt.startswith(OptName)) - return; - StringRef Value = Opt.drop_front(OptName.size()); - if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value) .Case("gcc", GCCMode) .Case("g++", GXXMode) @@ -517,14 +501,21 @@ static llvm::Triple computeTargetTriple(const Driver &D, AT = Target.get64BitArchVariant().getArch(); if (Target.getEnvironment() == llvm::Triple::GNUX32) Target.setEnvironment(llvm::Triple::GNU); + else if (Target.getEnvironment() == llvm::Triple::MuslX32) + Target.setEnvironment(llvm::Triple::Musl); } 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); + if (Target.getEnvironment() == llvm::Triple::Musl) + Target.setEnvironment(llvm::Triple::MuslX32); + else + Target.setEnvironment(llvm::Triple::GNUX32); } else if (A->getOption().matches(options::OPT_m32)) { AT = Target.get32BitArchVariant().getArch(); if (Target.getEnvironment() == llvm::Triple::GNUX32) Target.setEnvironment(llvm::Triple::GNU); + else if (Target.getEnvironment() == llvm::Triple::MuslX32) + Target.setEnvironment(llvm::Triple::Musl); } else if (A->getOption().matches(options::OPT_m16) && Target.get32BitArchVariant().getArch() == llvm::Triple::x86) { AT = llvm::Triple::x86; @@ -582,9 +573,9 @@ static llvm::Triple computeTargetTriple(const Driver &D, A = Args.getLastArg(options::OPT_march_EQ); if (A && Target.isRISCV()) { StringRef ArchName = A->getValue(); - if (ArchName.startswith_lower("rv32")) + if (ArchName.startswith_insensitive("rv32")) Target.setArch(llvm::Triple::riscv32); - else if (ArchName.startswith_lower("rv64")) + else if (ArchName.startswith_insensitive("rv64")) Target.setArch(llvm::Triple::riscv64); } @@ -592,16 +583,24 @@ static llvm::Triple computeTargetTriple(const Driver &D, } // Parse the LTO options and record the type of LTO compilation -// based on which -f(no-)?lto(=.*)? option occurs last. -void Driver::setLTOMode(const llvm::opt::ArgList &Args) { - LTOMode = LTOK_None; - if (!Args.hasFlag(options::OPT_flto, options::OPT_flto_EQ, - options::OPT_fno_lto, false)) - return; +// based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)? +// option occurs last. +static llvm::Optional<driver::LTOKind> +parseLTOMode(Driver &D, const llvm::opt::ArgList &Args, OptSpecifier OptPos, + OptSpecifier OptNeg, OptSpecifier OptEq, bool IsOffload) { + driver::LTOKind LTOMode = LTOK_None; + // Non-offload LTO allows -flto=auto and -flto=jobserver. Offload LTO does + // not support those options. + if (!Args.hasFlag(OptPos, OptEq, OptNeg, false) && + (IsOffload || + (!Args.hasFlag(options::OPT_flto_EQ_auto, options::OPT_fno_lto, false) && + !Args.hasFlag(options::OPT_flto_EQ_jobserver, options::OPT_fno_lto, + false)))) + return None; StringRef LTOName("full"); - const Arg *A = Args.getLastArg(options::OPT_flto_EQ); + const Arg *A = Args.getLastArg(OptEq); if (A) LTOName = A->getValue(); @@ -612,9 +611,27 @@ void Driver::setLTOMode(const llvm::opt::ArgList &Args) { if (LTOMode == LTOK_Unknown) { assert(A); - Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() - << A->getValue(); + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(); + return None; } + return LTOMode; +} + +// Parse the LTO options. +void Driver::setLTOMode(const llvm::opt::ArgList &Args) { + LTOMode = LTOK_None; + if (auto M = parseLTOMode(*this, Args, options::OPT_flto, + options::OPT_fno_lto, options::OPT_flto_EQ, + /*IsOffload=*/false)) + LTOMode = M.getValue(); + + OffloadLTOMode = LTOK_None; + if (auto M = parseLTOMode(*this, Args, options::OPT_foffload_lto, + options::OPT_fno_offload_lto, + options::OPT_foffload_lto_EQ, + /*IsOffload=*/true)) + OffloadLTOMode = M.getValue(); } /// Compute the desired OpenMP runtime from the flags provided. @@ -739,18 +756,27 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, Diag(clang::diag::err_drv_invalid_omp_target) << Val; else { const ToolChain *TC; - // CUDA toolchains have to be selected differently. They pair host + // Device toolchains have to be selected differently. They pair host // and device in their implementation. - if (TT.isNVPTX()) { + if (TT.isNVPTX() || TT.isAMDGCN()) { const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); assert(HostTC && "Host toolchain should be always defined."); - auto &CudaTC = + auto &DeviceTC = ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()]; - if (!CudaTC) - CudaTC = std::make_unique<toolchains::CudaToolChain>( - *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP); - TC = CudaTC.get(); + if (!DeviceTC) { + if (TT.isNVPTX()) + DeviceTC = std::make_unique<toolchains::CudaToolChain>( + *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP); + else if (TT.isAMDGCN()) + DeviceTC = + std::make_unique<toolchains::AMDGPUOpenMPToolChain>( + *this, TT, *HostTC, C.getInputArgs()); + else + assert(DeviceTC && "Device toolchain not defined."); + } + + TC = DeviceTC.get(); } else TC = &getToolChain(C.getInputArgs(), TT); C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP); @@ -987,7 +1013,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // We look for the driver mode option early, because the mode can affect // how other options are parsed. - ParseDriverMode(ClangExecutable, ArgList.slice(1)); + + auto DriverMode = getDriverMode(ClangExecutable, ArgList.slice(1)); + if (!DriverMode.empty()) + setDriverMode(DriverMode); // FIXME: What are we going to do with -V and -b? @@ -1085,6 +1114,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { GenReproducer = Args.hasFlag(options::OPT_gen_reproducer, options::OPT_fno_crash_diagnostics, !!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")); + + // Process -fproc-stat-report options. + if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) { + CCPrintProcessStats = true; + CCPrintStatReportFilename = A->getValue(); + } + if (Args.hasArg(options::OPT_fproc_stat_report)) + CCPrintProcessStats = true; + // FIXME: TargetTriple is used by the target-prefixed calls to as/ld // and getToolChain is const. if (IsCLMode()) { @@ -1434,7 +1472,9 @@ void Driver::generateCompilationDiagnostics( llvm::SmallString<128> Script(CrashInfo.Filename); llvm::sys::path::replace_extension(Script, "sh"); std::error_code EC; - llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew); + llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew, + llvm::sys::fs::FA_Write, + llvm::sys::fs::OF_Text); if (EC) { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " << Script << " " << EC.message(); @@ -1471,8 +1511,7 @@ void Driver::generateCompilationDiagnostics( } } - for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file, - options::OPT_frewrite_map_file_EQ)) + for (const auto &A : C.getArgs().filtered(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) @@ -1581,7 +1620,7 @@ void Driver::PrintHelp(bool ShowHidden) const { ExcludedFlagsBitmask |= options::FlangOnlyOption; std::string Usage = llvm::formatv("{0} [options] file...", Name).str(); - getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(), + getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(), IncludedFlagsBitmask, ExcludedFlagsBitmask, /*ShowAllAliases=*/false); } @@ -1701,7 +1740,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const { // case-insensitive sorting for consistency with the -help option // which prints out options in the case-insensitive alphabetical order. llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) { - if (int X = A.compare_lower(B)) + if (int X = A.compare_insensitive(B)) return X < 0; return A.compare(B) > 0; }); @@ -1802,6 +1841,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return false; } + if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) { + std::string CandidateRuntimePath = TC.getRuntimePath(); + if (getVFS().exists(CandidateRuntimePath)) + llvm::outs() << CandidateRuntimePath << '\n'; + else + llvm::outs() << TC.getCompilerRTPath() << '\n'; + return false; + } + // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) { @@ -1870,6 +1918,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return false; } + if (C.getArgs().hasArg(options::OPT_print_multiarch)) { + llvm::outs() << TC.getMultiarchTriple(*this, TC.getTriple(), SysRoot) + << "\n"; + return false; + } + if (C.getArgs().hasArg(options::OPT_print_targets)) { llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs()); return false; @@ -2179,15 +2233,20 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, // stdin must be handled specially. if (memcmp(Value, "-", 2) == 0) { - // If running with -E, treat as a C input (this changes the builtin - // macros, for example). This may be overridden by -ObjC below. - // - // Otherwise emit an error but still use a valid type to avoid - // spurious errors (e.g., no inputs). - if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP()) - Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl - : clang::diag::err_drv_unknown_stdin_type); - Ty = types::TY_C; + if (IsFlangMode()) { + Ty = types::TY_Fortran; + } else { + // If running with -E, treat as a C input (this changes the + // builtin macros, for example). This may be overridden by -ObjC + // below. + // + // Otherwise emit an error but still use a valid type to avoid + // spurious errors (e.g., no inputs). + if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP()) + Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl + : clang::diag::err_drv_unknown_stdin_type); + Ty = types::TY_C; + } } else { // Otherwise lookup by extension. // Fallback is C if invoked as C preprocessor, C++ if invoked with @@ -2443,6 +2502,14 @@ class OffloadingActionBuilder final { /// Default GPU architecture if there's no one specified. CudaArch DefaultCudaArch = CudaArch::UNKNOWN; + /// Method to generate compilation unit ID specified by option + /// '-fuse-cuid='. + enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid }; + UseCUIDKind UseCUID = CUID_Hash; + + /// Compilation unit ID specified by option '-cuid='. + StringRef FixedCUID; + public: CudaActionBuilderBase(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs, @@ -2479,9 +2546,32 @@ class OffloadingActionBuilder final { // Replicate inputs for each GPU architecture. auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE : types::TY_CUDA_DEVICE; + std::string CUID = FixedCUID.str(); + if (CUID.empty()) { + if (UseCUID == CUID_Random) + CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(), + /*LowerCase=*/true); + else if (UseCUID == CUID_Hash) { + llvm::MD5 Hasher; + llvm::MD5::MD5Result Hash; + SmallString<256> RealPath; + llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath, + /*expand_tilde=*/true); + Hasher.update(RealPath); + for (auto *A : Args) { + if (A->getOption().matches(options::OPT_INPUT)) + continue; + Hasher.update(A->getAsString(Args)); + } + Hasher.final(Hash); + CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true); + } + } + IA->setId(CUID); + for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { CudaDeviceActions.push_back( - C.MakeAction<InputAction>(IA->getInputArg(), Ty)); + C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId())); } return ABRT_Success; @@ -2603,6 +2693,21 @@ class OffloadingActionBuilder final { options::OPT_cuda_device_only); EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); EmitAsm = Args.getLastArg(options::OPT_S); + FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ); + if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) { + StringRef UseCUIDStr = A->getValue(); + UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr) + .Case("hash", CUID_Hash) + .Case("random", CUID_Random) + .Case("none", CUID_None) + .Default(CUID_Invalid); + if (UseCUID == CUID_Invalid) { + C.getDriver().Diag(diag::err_drv_invalid_value) + << A->getAsString(Args) << UseCUIDStr; + C.setContainsError(); + return true; + } + } // Collect all cuda_gpu_arch parameters, removing duplicates. std::set<StringRef> GpuArchs; @@ -2665,7 +2770,7 @@ class OffloadingActionBuilder final { StringRef getCanonicalOffloadArch(StringRef ArchStr) override { CudaArch Arch = StringToCudaArch(ArchStr); - if (Arch == CudaArch::UNKNOWN) { + if (Arch == CudaArch::UNKNOWN || !IsNVIDIAGpuArch(Arch)) { C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; return StringRef(); } @@ -2786,12 +2891,25 @@ class OffloadingActionBuilder final { class HIPActionBuilder final : public CudaActionBuilderBase { /// The linker inputs obtained for each device arch. SmallVector<ActionList, 8> DeviceLinkerInputs; + bool GPUSanitize; + // The default bundling behavior depends on the type of output, therefore + // BundleOutput needs to be tri-value: None, true, or false. + // Bundle code objects except --no-gpu-output is specified for device + // only compilation. Bundle other type of output files only if + // --gpu-bundle-output is specified for device only compilation. + Optional<bool> BundleOutput; public: HIPActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) { DefaultCudaArch = CudaArch::GFX803; + GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize, + options::OPT_fno_gpu_sanitize, false); + if (Args.hasArg(options::OPT_gpu_bundle_output, + options::OPT_no_gpu_bundle_output)) + BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output, + options::OPT_no_gpu_bundle_output); } bool canUseBundlerUnbundler() const override { return true; } @@ -2840,17 +2958,31 @@ class OffloadingActionBuilder final { // a fat binary containing all the code objects for different GPU's. // The fat binary is then an input to the host action. for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { - auto BackendAction = C.getDriver().ConstructPhaseAction( - C, Args, phases::Backend, CudaDeviceActions[I], - AssociatedOffloadKind); - auto AssembleAction = C.getDriver().ConstructPhaseAction( - C, Args, phases::Assemble, BackendAction, AssociatedOffloadKind); - // Create a link action to link device IR with device library - // and generate ISA. - ActionList AL; - AL.push_back(AssembleAction); - CudaDeviceActions[I] = - C.MakeAction<LinkJobAction>(AL, types::TY_Image); + if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) { + // When LTO is enabled, skip the backend and assemble phases and + // use lld to link the bitcode. + ActionList AL; + AL.push_back(CudaDeviceActions[I]); + // Create a link action to link device IR with device library + // and generate ISA. + CudaDeviceActions[I] = + C.MakeAction<LinkJobAction>(AL, types::TY_Image); + } else { + // When LTO is not enabled, we follow the conventional + // compiler phases, including backend and assemble phases. + ActionList AL; + auto BackendAction = C.getDriver().ConstructPhaseAction( + C, Args, phases::Backend, CudaDeviceActions[I], + AssociatedOffloadKind); + auto AssembleAction = C.getDriver().ConstructPhaseAction( + C, Args, phases::Assemble, BackendAction, + AssociatedOffloadKind); + AL.push_back(AssembleAction); + // Create a link action to link device IR with device library + // and generate ISA. + CudaDeviceActions[I] = + C.MakeAction<LinkJobAction>(AL, types::TY_Image); + } // OffloadingActionBuilder propagates device arch until an offload // action. Since the next action for creating fatbin does @@ -2864,22 +2996,25 @@ class OffloadingActionBuilder final { CudaDeviceActions[I] = C.MakeAction<OffloadAction>( DDep, CudaDeviceActions[I]->getType()); } - // Create HIP fat binary with a special "link" action. - CudaFatBinary = - C.MakeAction<LinkJobAction>(CudaDeviceActions, - types::TY_HIP_FATBIN); - if (!CompileDeviceOnly) { - DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr, - AssociatedOffloadKind); - // Clear the fat binary, it is already a dependence to an host - // action. - CudaFatBinary = nullptr; - } + if (!CompileDeviceOnly || !BundleOutput.hasValue() || + BundleOutput.getValue()) { + // Create HIP fat binary with a special "link" action. + CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions, + types::TY_HIP_FATBIN); - // Remove the CUDA actions as they are already connected to an host - // action or fat binary. - CudaDeviceActions.clear(); + if (!CompileDeviceOnly) { + DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr, + AssociatedOffloadKind); + // Clear the fat binary, it is already a dependence to an host + // action. + CudaFatBinary = nullptr; + } + + // Remove the CUDA actions as they are already connected to an host + // action or fat binary. + CudaDeviceActions.clear(); + } return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success; } else if (CurPhase == phases::Link) { @@ -2906,6 +3041,20 @@ class OffloadingActionBuilder final { A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A, AssociatedOffloadKind); + if (CompileDeviceOnly && CurPhase == FinalPhase && + BundleOutput.hasValue() && BundleOutput.getValue()) { + for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) { + OffloadAction::DeviceDependences DDep; + DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I], + AssociatedOffloadKind); + CudaDeviceActions[I] = C.MakeAction<OffloadAction>( + DDep, CudaDeviceActions[I]->getType()); + } + CudaFatBinary = + C.MakeAction<OffloadBundlingJobAction>(CudaDeviceActions); + CudaDeviceActions.clear(); + } + return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host : ABRT_Success; } @@ -3343,7 +3492,7 @@ public: return nullptr; // Let builders add host linking actions. - Action* HA; + Action* HA = nullptr; for (DeviceActionBuilder *SB : SpecializedBuilders) { if (!SB->isValid()) continue; @@ -3418,7 +3567,8 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args, if (Args.hasArg(options::OPT_emit_llvm)) Diag(clang::diag::err_drv_emit_llvm_link); if (IsCLMode() && LTOMode != LTOK_None && - !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld")) + !Args.getLastArgValue(options::OPT_fuse_ld_EQ) + .equals_insensitive("lld")) Diag(clang::diag::err_drv_lto_without_lld); } @@ -3890,10 +4040,13 @@ void Driver::BuildJobs(Compilation &C) const { } const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple(); - if (RawTriple.isOSAIX()) + if (RawTriple.isOSAIX()) { if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << RawTriple.str(); + if (LTOMode == LTOK_Thin) + Diag(diag::err_drv_clang_unsupported) << "thinLTO on AIX"; + } // Collect the list of architectures. llvm::StringSet<> ArchNames; @@ -3927,66 +4080,64 @@ void Driver::BuildJobs(Compilation &C) const { /*TargetDeviceOffloadKind*/ Action::OFK_None); } - StringRef StatReportFile; - bool PrintProcessStat = false; - if (const Arg *A = C.getArgs().getLastArg(options::OPT_fproc_stat_report_EQ)) - StatReportFile = A->getValue(); - if (C.getArgs().hasArg(options::OPT_fproc_stat_report)) - PrintProcessStat = true; - // If we have more than one job, then disable integrated-cc1 for now. Do this // also when we need to report process execution statistics. - if (C.getJobs().size() > 1 || !StatReportFile.empty() || PrintProcessStat) + if (C.getJobs().size() > 1 || CCPrintProcessStats) for (auto &J : C.getJobs()) J.InProcess = false; - if (!StatReportFile.empty() || PrintProcessStat) { + if (CCPrintProcessStats) { C.setPostCallback([=](const Command &Cmd, int Res) { Optional<llvm::sys::ProcessStatistics> ProcStat = Cmd.getProcessStatistics(); if (!ProcStat) return; - if (PrintProcessStat) { + + const char *LinkingOutput = nullptr; + if (FinalOutput) + LinkingOutput = FinalOutput->getValue(); + else if (!Cmd.getOutputFilenames().empty()) + LinkingOutput = Cmd.getOutputFilenames().front().c_str(); + else + LinkingOutput = getDefaultImageName(); + + if (CCPrintStatReportFilename.empty()) { using namespace llvm; // Human readable output. outs() << sys::path::filename(Cmd.getExecutable()) << ": " - << "output="; - if (Cmd.getOutputFilenames().empty()) - outs() << "\"\""; - else - outs() << Cmd.getOutputFilenames().front(); + << "output=" << LinkingOutput; outs() << ", total=" << format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms" << ", user=" << format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms" << ", mem=" << ProcStat->PeakMemory << " Kb\n"; - } - if (!StatReportFile.empty()) { + } else { // CSV format. std::string Buffer; llvm::raw_string_ostream Out(Buffer); llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()), /*Quote*/ true); Out << ','; - if (Cmd.getOutputFilenames().empty()) - Out << "\"\""; - else - llvm::sys::printArg(Out, Cmd.getOutputFilenames().front(), true); + llvm::sys::printArg(Out, LinkingOutput, true); Out << ',' << ProcStat->TotalTime.count() << ',' << ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory << '\n'; Out.flush(); std::error_code EC; - llvm::raw_fd_ostream OS(StatReportFile, EC, llvm::sys::fs::OF_Append); + llvm::raw_fd_ostream OS(CCPrintStatReportFilename.c_str(), EC, + llvm::sys::fs::OF_Append | + llvm::sys::fs::OF_Text); if (EC) return; auto L = OS.lock(); if (!L) { - llvm::errs() << "ERROR: Cannot lock file " << StatReportFile << ": " + llvm::errs() << "ERROR: Cannot lock file " + << CCPrintStatReportFilename << ": " << toString(L.takeError()) << "\n"; return; } OS << Buffer; + OS.flush(); } }); } @@ -4479,6 +4630,25 @@ InputInfo Driver::BuildJobsForActionNoCache( if (!T) return InputInfo(); + if (BuildingForOffloadDevice && + A->getOffloadingDeviceKind() == Action::OFK_OpenMP) { + if (TC->getTriple().isAMDGCN()) { + // AMDGCN treats backend and assemble actions as no-op because + // linker does not support object files. + if (const BackendJobAction *BA = dyn_cast<BackendJobAction>(A)) { + return BuildJobsForAction(C, *BA->input_begin(), TC, BoundArch, + AtTopLevel, MultipleArchs, LinkingOutput, + CachedResults, TargetDeviceOffloadKind); + } + + if (const AssembleJobAction *AA = dyn_cast<AssembleJobAction>(A)) { + return BuildJobsForAction(C, *AA->input_begin(), TC, BoundArch, + AtTopLevel, MultipleArchs, LinkingOutput, + CachedResults, TargetDeviceOffloadKind); + } + } + } + // If we've collapsed action list that contained OffloadAction we // need to build jobs for host/device-side inputs it may have held. for (const auto *OA : CollapsedOffloadActions) @@ -4598,11 +4768,12 @@ InputInfo Driver::BuildJobsForActionNoCache( /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() && !AtTopLevel); if (isa<OffloadWrapperJobAction>(JA)) { - OffloadingPrefix += "-wrapper"; if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) BaseInput = FinalOutput->getValue(); else BaseInput = getDefaultImageName(); + BaseInput = + C.getArgs().MakeArgString(std::string(BaseInput) + "-wrapper"); } Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch, AtTopLevel, MultipleArchs, @@ -4729,6 +4900,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, return "-"; } + if (JA.getType() == types::TY_ModuleFile && + C.getArgs().getLastArg(options::OPT_module_file_info)) { + return "-"; + } + // Is this the assembly listing for /FA? if (JA.getType() == types::TY_PP_Asm && (C.getArgs().hasArg(options::OPT__SLASH_FA) || @@ -4963,11 +5139,6 @@ void Driver::generatePrefixedToolNames( // FIXME: Needs a better variable than TargetTriple Names.emplace_back((TargetTriple + "-" + Tool).str()); Names.emplace_back(Tool); - - // Allow the discovery of tools prefixed with LLVM's default target triple. - std::string DefaultTargetTriple = llvm::sys::getDefaultTargetTriple(); - if (DefaultTargetTriple != TargetTriple) - Names.emplace_back((DefaultTargetTriple + "-" + Tool).str()); } static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) { @@ -5158,7 +5329,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::MSVC: case llvm::Triple::UnknownEnvironment: if (Args.getLastArgValue(options::OPT_fuse_ld_EQ) - .startswith_lower("bfd")) + .startswith_insensitive("bfd")) TC = std::make_unique<toolchains::CrossWindowsToolChain>( *this, Target, Args); else @@ -5387,3 +5558,21 @@ bool clang::driver::willEmitRemarks(const ArgList &Args) { return true; return false; } + +llvm::StringRef clang::driver::getDriverMode(StringRef ProgName, + ArrayRef<const char *> Args) { + static const std::string OptName = + getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName(); + llvm::StringRef Opt; + for (StringRef Arg : Args) { + if (!Arg.startswith(OptName)) + continue; + Opt = Arg; + break; + } + if (Opt.empty()) + Opt = ToolChain::getTargetAndModeFromProgramName(ProgName).DriverMode; + return Opt.consume_front(OptName) ? Opt : ""; +} + +bool driver::IsClangCL(StringRef DriverMode) { return DriverMode.equals("cl"); } |