diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/Driver.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Driver/Driver.cpp | 347 |
1 files changed, 267 insertions, 80 deletions
diff --git a/contrib/llvm-project/clang/lib/Driver/Driver.cpp b/contrib/llvm-project/clang/lib/Driver/Driver.cpp index ece8222dcf24..418e1d3e8ec9 100644 --- a/contrib/llvm-project/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm-project/clang/lib/Driver/Driver.cpp @@ -46,6 +46,8 @@ #include "ToolChains/VEToolchain.h" #include "ToolChains/WebAssembly.h" #include "ToolChains/XCore.h" +#include "ToolChains/ZOS.h" +#include "clang/Basic/TargetID.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -70,6 +72,7 @@ #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ExitCodes.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Host.h" @@ -86,13 +89,17 @@ #include <utility> #if LLVM_ON_UNIX #include <unistd.h> // getpid -#include <sysexits.h> // EX_IOERR #endif using namespace clang::driver; using namespace clang; using namespace llvm::opt; +static llvm::Triple getHIPOffloadTargetTriple() { + static const llvm::Triple T("amdgcn-amd-amdhsa"); + return T; +} + // static std::string Driver::GetResourcesPath(StringRef BinaryPath, StringRef CustomResourceDir) { @@ -121,12 +128,12 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath, } Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, - DiagnosticsEngine &Diags, + DiagnosticsEngine &Diags, std::string Title, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), + DriverTitle(Title), CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), @@ -204,6 +211,11 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings, std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = getIncludeExcludeOptionFlagMasks(IsClCompatMode); + // Make sure that Flang-only options don't pollute the Clang output + // TODO: Make sure that Clang-only options don't pollute Flang output + if (!IsFlangMode()) + ExcludedFlagsBitmask |= options::FlangOnlyOption; + unsigned MissingArgIndex, MissingArgCount; InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, @@ -672,10 +684,8 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, } else if (IsHIP) { const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>(); const llvm::Triple &HostTriple = HostTC->getTriple(); - StringRef DeviceTripleStr; auto OFK = Action::OFK_HIP; - DeviceTripleStr = "amdgcn-amd-amdhsa"; - llvm::Triple HIPTriple(DeviceTripleStr); + llvm::Triple HIPTriple = getHIPOffloadTargetTriple(); // Use the HIP and host triples as the key into the ToolChains map, // because the device toolchain we create depends on both. auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()]; @@ -769,10 +779,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C, /// by Dirs. /// static bool searchForFile(SmallVectorImpl<char> &FilePath, - ArrayRef<std::string> Dirs, - StringRef FileName) { + ArrayRef<StringRef> Dirs, StringRef FileName) { SmallString<128> WPath; - for (const std::string &Dir : Dirs) { + for (const StringRef &Dir : Dirs) { if (Dir.empty()) continue; WPath.clear(); @@ -797,7 +806,7 @@ bool Driver::readConfigFile(StringRef FileName) { // Read options from config file. llvm::SmallString<128> CfgFileName(FileName); llvm::sys::path::native(CfgFileName); - ConfigFile = std::string(CfgFileName.str()); + ConfigFile = std::string(CfgFileName); bool ContainErrors; CfgOptions = std::make_unique<InputArgList>( ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors)); @@ -854,9 +863,10 @@ bool Driver::loadConfigFile() { std::vector<std::string> ConfigFiles = CLOptions->getAllArgValues(options::OPT_config); if (ConfigFiles.size() > 1) { - if (!std::all_of( - ConfigFiles.begin(), ConfigFiles.end(), - [ConfigFiles](std::string s) { return s == ConfigFiles[0]; })) { + if (!std::all_of(ConfigFiles.begin(), ConfigFiles.end(), + [ConfigFiles](const std::string &s) { + return s == ConfigFiles[0]; + })) { Diag(diag::err_drv_duplicate_config); return true; } @@ -929,10 +939,7 @@ bool Driver::loadConfigFile() { } // Prepare list of directories where config file is searched for. - SmallVector<std::string, 3> CfgFileSearchDirs; - CfgFileSearchDirs.push_back(UserConfigDir); - CfgFileSearchDirs.push_back(SystemConfigDir); - CfgFileSearchDirs.push_back(Dir); + StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir}; // Try to find config file. First try file with corrected architecture. llvm::SmallString<128> CfgFilePath; @@ -963,7 +970,7 @@ bool Driver::loadConfigFile() { // --config. If it was deduced from executable name, it is not an error. if (FileSpecifiedExplicitly) { Diag(diag::err_drv_config_file_not_found) << CfgFileName; - for (const std::string &SearchDir : CfgFileSearchDirs) + for (const StringRef &SearchDir : CfgFileSearchDirs) if (!SearchDir.empty()) Diag(diag::note_drv_config_file_searched_in) << SearchDir; return true; @@ -978,17 +985,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // FIXME: Handle environment options which affect driver behavior, somewhere // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS. - if (Optional<std::string> CompilerPathValue = - llvm::sys::Process::GetEnv("COMPILER_PATH")) { - StringRef CompilerPath = *CompilerPathValue; - while (!CompilerPath.empty()) { - std::pair<StringRef, StringRef> Split = - CompilerPath.split(llvm::sys::EnvPathSeparator); - PrefixDirs.push_back(std::string(Split.first)); - CompilerPath = Split.second; - } - } - // We look for the driver mode option early, because the mode can affect // how other options are parsed. ParseDriverMode(ClangExecutable, ArgList.slice(1)); @@ -1013,13 +1009,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // 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(), - Index, BaseArg); - Copy->getValues() = Opt->getValues(); - if (Opt->isClaimed()) - Copy->claim(); - Args.append(Copy); + unsigned Index = Args.MakeIndex(Opt->getSpelling()); + Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Args.getArgString(Index), + Index, BaseArg); + Copy->getValues() = Opt->getValues(); + if (Opt->isClaimed()) + Copy->claim(); + Copy->setOwnsValues(Opt->getOwnsValues()); + Opt->setOwnsValues(false); + Args.append(Copy); }; if (HasConfigFile) @@ -1106,6 +1104,16 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { A->claim(); PrefixDirs.push_back(A->getValue(0)); } + if (Optional<std::string> CompilerPathValue = + llvm::sys::Process::GetEnv("COMPILER_PATH")) { + StringRef CompilerPath = *CompilerPathValue; + while (!CompilerPath.empty()) { + std::pair<StringRef, StringRef> Split = + CompilerPath.split(llvm::sys::EnvPathSeparator); + PrefixDirs.push_back(std::string(Split.first)); + CompilerPath = Split.second; + } + } if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) SysRoot = A->getValue(); if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ)) @@ -1567,6 +1575,11 @@ void Driver::PrintHelp(bool ShowHidden) const { if (!ShowHidden) ExcludedFlagsBitmask |= HelpHidden; + if (IsFlangMode()) + IncludedFlagsBitmask |= options::FlangOption; + else + ExcludedFlagsBitmask |= options::FlangOnlyOption; + std::string Usage = llvm::formatv("{0} [options] file...", Name).str(); getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(), IncludedFlagsBitmask, ExcludedFlagsBitmask, @@ -1574,9 +1587,13 @@ void Driver::PrintHelp(bool ShowHidden) const { } void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { - // FIXME: The following handlers should use a callback mechanism, we don't - // know what the client would like to do. - OS << getClangFullVersion() << '\n'; + if (IsFlangMode()) { + OS << getClangToolFullVersion("flang-new") << '\n'; + } else { + // FIXME: The following handlers should use a callback mechanism, we don't + // know what the client would like to do. + OS << getClangFullVersion() << '\n'; + } const ToolChain &TC = C.getDefaultToolChain(); OS << "Target: " << TC.getTripleString() << '\n'; @@ -1614,9 +1631,14 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const { std::vector<std::string> SuggestedCompletions; std::vector<std::string> Flags; - unsigned short DisableFlags = + unsigned int DisableFlags = options::NoDriverOption | options::Unsupported | options::Ignored; + // Make sure that Flang-only options don't pollute the Clang output + // TODO: Make sure that Clang-only options don't pollute Flang output + if (!IsFlangMode()) + DisableFlags |= options::FlangOnlyOption; + // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag," // because the latter indicates that the user put space before pushing tab // which should end up in a file completion. @@ -1749,6 +1771,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { if (C.getArgs().hasArg(options::OPT_print_search_dirs)) { llvm::outs() << "programs: ="; bool separator = false; + // Print -B and COMPILER_PATH. + for (const std::string &Path : PrefixDirs) { + if (separator) + llvm::outs() << llvm::sys::EnvPathSeparator; + llvm::outs() << Path; + separator = true; + } for (const std::string &Path : TC.getProgramPaths()) { if (separator) llvm::outs() << llvm::sys::EnvPathSeparator; @@ -2067,7 +2096,7 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, if (IsCLMode()) { if (!llvm::sys::path::is_absolute(Twine(Value)) && - llvm::sys::Process::FindInEnvPath("LIB", Value)) + llvm::sys::Process::FindInEnvPath("LIB", Value, ';')) return true; if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) { @@ -2384,8 +2413,20 @@ class OffloadingActionBuilder final { bool EmitLLVM = false; bool EmitAsm = false; + /// ID to identify each device compilation. For CUDA it is simply the + /// GPU arch string. For HIP it is either the GPU arch string or GPU + /// arch string plus feature strings delimited by a plus sign, e.g. + /// gfx906+xnack. + struct TargetID { + /// Target ID string which is persistent throughout the compilation. + const char *ID; + TargetID(CudaArch Arch) { ID = CudaArchToString(Arch); } + TargetID(const char *ID) : ID(ID) {} + operator const char *() { return ID; } + operator StringRef() { return StringRef(ID); } + }; /// List of GPU architectures to use in this compilation. - SmallVector<CudaArch, 4> GpuArchList; + SmallVector<TargetID, 4> GpuArchList; /// The CUDA actions for the current input. ActionList CudaDeviceActions; @@ -2421,8 +2462,9 @@ class OffloadingActionBuilder final { // If the host input is not CUDA or HIP, we don't need to bother about // this input. - if (IA->getType() != types::TY_CUDA && - IA->getType() != types::TY_HIP) { + if (!(IA->getType() == types::TY_CUDA || + IA->getType() == types::TY_HIP || + IA->getType() == types::TY_PP_HIP)) { // The builder will ignore this input. IsActive = false; return ABRT_Inactive; @@ -2450,7 +2492,7 @@ class OffloadingActionBuilder final { // If -fgpu-rdc is disabled, should not unbundle since there is no // device code to link. - if (!Relocatable) + if (UA->getType() == types::TY_Object && !Relocatable) return ABRT_Inactive; CudaDeviceActions.clear(); @@ -2468,7 +2510,7 @@ class OffloadingActionBuilder final { for (auto Arch : GpuArchList) { CudaDeviceActions.push_back(UA); - UA->registerDependentActionInfo(ToolChains[0], CudaArchToString(Arch), + UA->registerDependentActionInfo(ToolChains[0], Arch, AssociatedOffloadKind); } return ABRT_Success; @@ -2479,16 +2521,15 @@ class OffloadingActionBuilder final { void appendTopLevelActions(ActionList &AL) override { // Utility to append actions to the top level list. - auto AddTopLevel = [&](Action *A, CudaArch BoundArch) { + auto AddTopLevel = [&](Action *A, TargetID TargetID) { OffloadAction::DeviceDependences Dep; - Dep.add(*A, *ToolChains.front(), CudaArchToString(BoundArch), - AssociatedOffloadKind); + Dep.add(*A, *ToolChains.front(), TargetID, AssociatedOffloadKind); AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType())); }; // If we have a fat binary, add it to the list. if (CudaFatBinary) { - AddTopLevel(CudaFatBinary, CudaArch::UNKNOWN); + AddTopLevel(CudaFatBinary, CudaArch::UNUSED); CudaDeviceActions.clear(); CudaFatBinary = nullptr; return; @@ -2510,6 +2551,13 @@ class OffloadingActionBuilder final { CudaDeviceActions.clear(); } + /// Get canonicalized offload arch option. \returns empty StringRef if the + /// option is invalid. + virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0; + + virtual llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> + getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0; + bool initialize() override { assert(AssociatedOffloadKind == Action::OFK_Cuda || AssociatedOffloadKind == Action::OFK_HIP); @@ -2557,7 +2605,7 @@ class OffloadingActionBuilder final { EmitAsm = Args.getLastArg(options::OPT_S); // Collect all cuda_gpu_arch parameters, removing duplicates. - std::set<CudaArch> GpuArchs; + std::set<StringRef> GpuArchs; bool Error = false; for (Arg *A : Args) { if (!(A->getOption().matches(options::OPT_offload_arch_EQ) || @@ -2565,27 +2613,35 @@ class OffloadingActionBuilder final { continue; A->claim(); - const StringRef ArchStr = A->getValue(); + StringRef ArchStr = A->getValue(); if (A->getOption().matches(options::OPT_no_offload_arch_EQ) && ArchStr == "all") { GpuArchs.clear(); continue; } - CudaArch Arch = StringToCudaArch(ArchStr); - if (Arch == CudaArch::UNKNOWN) { - C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; + ArchStr = getCanonicalOffloadArch(ArchStr); + if (ArchStr.empty()) { Error = true; } else if (A->getOption().matches(options::OPT_offload_arch_EQ)) - GpuArchs.insert(Arch); + GpuArchs.insert(ArchStr); else if (A->getOption().matches(options::OPT_no_offload_arch_EQ)) - GpuArchs.erase(Arch); + GpuArchs.erase(ArchStr); else llvm_unreachable("Unexpected option."); } + auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs); + if (ConflictingArchs) { + C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo) + << ConflictingArchs.getValue().first + << ConflictingArchs.getValue().second; + C.setContainsError(); + return true; + } + // Collect list of GPUs remaining in the set. - for (CudaArch Arch : GpuArchs) - GpuArchList.push_back(Arch); + for (auto Arch : GpuArchs) + GpuArchList.push_back(Arch.data()); // Default to sm_20 which is the lowest common denominator for // supported GPUs. sm_20 code should work correctly, if @@ -2607,6 +2663,21 @@ class OffloadingActionBuilder final { DefaultCudaArch = CudaArch::SM_20; } + StringRef getCanonicalOffloadArch(StringRef ArchStr) override { + CudaArch Arch = StringToCudaArch(ArchStr); + if (Arch == CudaArch::UNKNOWN) { + C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; + return StringRef(); + } + return CudaArchToString(Arch); + } + + llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> + getConflictOffloadArchCombination( + const std::set<StringRef> &GpuArchs) override { + return llvm::None; + } + ActionBuilderReturnCode getDeviceDependences(OffloadAction::DeviceDependences &DA, phases::ID CurPhase, phases::ID FinalPhase, @@ -2666,8 +2737,7 @@ class OffloadingActionBuilder final { for (auto &A : {AssembleAction, BackendAction}) { OffloadAction::DeviceDependences DDep; - DDep.add(*A, *ToolChains.front(), CudaArchToString(GpuArchList[I]), - Action::OFK_Cuda); + DDep.add(*A, *ToolChains.front(), GpuArchList[I], Action::OFK_Cuda); DeviceActions.push_back( C.MakeAction<OffloadAction>(DDep, A->getType())); } @@ -2726,6 +2796,25 @@ class OffloadingActionBuilder final { bool canUseBundlerUnbundler() const override { return true; } + StringRef getCanonicalOffloadArch(StringRef IdStr) override { + llvm::StringMap<bool> Features; + auto ArchStr = + parseTargetID(getHIPOffloadTargetTriple(), IdStr, &Features); + if (!ArchStr) { + C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr; + C.setContainsError(); + return StringRef(); + } + auto CanId = getCanonicalTargetID(ArchStr.getValue(), Features); + return Args.MakeArgStringRef(CanId); + }; + + llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> + getConflictOffloadArchCombination( + const std::set<StringRef> &GpuArchs) override { + return getConflictTargetIDCombination(GpuArchs); + } + ActionBuilderReturnCode getDeviceDependences(OffloadAction::DeviceDependences &DA, phases::ID CurPhase, phases::ID FinalPhase, @@ -2770,8 +2859,8 @@ class OffloadingActionBuilder final { // device arch of the next action being propagated to the above link // action. OffloadAction::DeviceDependences DDep; - DDep.add(*CudaDeviceActions[I], *ToolChains.front(), - CudaArchToString(GpuArchList[I]), AssociatedOffloadKind); + DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I], + AssociatedOffloadKind); CudaDeviceActions[I] = C.MakeAction<OffloadAction>( DDep, CudaDeviceActions[I]->getType()); } @@ -2838,7 +2927,7 @@ class OffloadingActionBuilder final { // LI contains all the inputs for the linker. OffloadAction::DeviceDependences DeviceLinkDeps; DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0], - CudaArchToString(GpuArchList[I]), AssociatedOffloadKind); + GpuArchList[I], AssociatedOffloadKind); AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps, DeviceLinkAction->getType())); ++I; @@ -3164,7 +3253,8 @@ public: // the input is not a bundle. if (CanUseBundler && isa<InputAction>(HostAction) && InputArg->getOption().getKind() == llvm::opt::Option::InputClass && - !types::isSrcFile(HostAction->getType())) { + (!types::isSrcFile(HostAction->getType()) || + HostAction->getType() == types::TY_PP_HIP)) { auto UnbundlingHostAction = C.MakeAction<OffloadUnbundlingJobAction>(HostAction); UnbundlingHostAction->registerDependentActionInfo( @@ -3799,9 +3889,15 @@ void Driver::BuildJobs(Compilation &C) const { } } + const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple(); + if (RawTriple.isOSAIX()) + if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) + Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << RawTriple.str(); + // Collect the list of architectures. llvm::StringSet<> ArchNames; - if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) + if (RawTriple.isOSBinFormatMachO()) for (const Arg *A : C.getArgs()) if (A->getOption().matches(options::OPT_arch)) ArchNames.insert(A->getValue()); @@ -3831,11 +3927,70 @@ void Driver::BuildJobs(Compilation &C) const { /*TargetDeviceOffloadKind*/ Action::OFK_None); } - // If we have more than one job, then disable integrated-cc1 for now. - if (C.getJobs().size() > 1) + 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) for (auto &J : C.getJobs()) J.InProcess = false; + if (!StatReportFile.empty() || PrintProcessStat) { + C.setPostCallback([=](const Command &Cmd, int Res) { + Optional<llvm::sys::ProcessStatistics> ProcStat = + Cmd.getProcessStatistics(); + if (!ProcStat) + return; + if (PrintProcessStat) { + using namespace llvm; + // Human readable output. + outs() << sys::path::filename(Cmd.getExecutable()) << ": " + << "output="; + if (Cmd.getOutputFilenames().empty()) + outs() << "\"\""; + else + outs() << Cmd.getOutputFilenames().front(); + 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()) { + // 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); + 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); + if (EC) + return; + auto L = OS.lock(); + if (!L) { + llvm::errs() << "ERROR: Cannot lock file " << StatReportFile << ": " + << toString(L.takeError()) << "\n"; + return; + } + OS << Buffer; + } + }); + } + // If the user passed -Qunused-arguments or there were errors, don't warn // about any unused arguments. if (Diags.hasErrorOccurred() || @@ -4527,11 +4682,29 @@ static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue, return Args.MakeArgString(Filename.c_str()); } +static bool HasPreprocessOutput(const Action &JA) { + if (isa<PreprocessJobAction>(JA)) + return true; + if (isa<OffloadAction>(JA) && isa<PreprocessJobAction>(JA.getInputs()[0])) + return true; + if (isa<OffloadBundlingJobAction>(JA) && + HasPreprocessOutput(*(JA.getInputs()[0]))) + return true; + return false; +} + const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, const char *BaseInput, - StringRef BoundArch, bool AtTopLevel, + StringRef OrigBoundArch, bool AtTopLevel, bool MultipleArchs, StringRef OffloadingPrefix) const { + std::string BoundArch = OrigBoundArch.str(); +#if defined(_WIN32) + // BoundArch may contains ':', which is invalid in file names on Windows, + // therefore replace it with '%'. + std::replace(BoundArch.begin(), BoundArch.end(), ':', '@'); +#endif + llvm::PrettyStackTraceString CrashInfo("Computing output path"); // Output to a user requested destination? if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) { @@ -4552,8 +4725,9 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, } // Default to writing to stdout? - if (AtTopLevel && !CCGenDiagnostics && isa<PreprocessJobAction>(JA)) + if (AtTopLevel && !CCGenDiagnostics && HasPreprocessOutput(JA)) { return "-"; + } // Is this the assembly listing for /FA? if (JA.getType() == types::TY_PP_Asm && @@ -4595,10 +4769,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, } SmallString<128> BasePath(BaseInput); + SmallString<128> ExternalPath(""); StringRef BaseName; // Dsymutil actions should use the full path. - if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA)) + if (isa<DsymutilJobAction>(JA) && C.getArgs().hasArg(options::OPT_dsym_dir)) { + ExternalPath += C.getArgs().getLastArg(options::OPT_dsym_dir)->getValue(); + // We use posix style here because the tests (specifically + // darwin-dsymutil.c) demonstrate that posix style paths are acceptable + // even on Windows and if we don't then the similar test covering this + // fails. + llvm::sys::path::append(ExternalPath, llvm::sys::path::Style::posix, + llvm::sys::path::filename(BasePath)); + BaseName = ExternalPath; + } else if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA)) BaseName = BasePath; else BaseName = llvm::sys::path::filename(BasePath); @@ -4786,8 +4970,7 @@ void Driver::generatePrefixedToolNames( Names.emplace_back((DefaultTargetTriple + "-" + Tool).str()); } -static bool ScanDirForExecutable(SmallString<128> &Dir, - const std::string &Name) { +static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) { llvm::sys::path::append(Dir, Name); if (llvm::sys::fs::can_execute(Twine(Dir))) return true; @@ -4804,9 +4987,8 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const { for (const auto &PrefixDir : PrefixDirs) { if (llvm::sys::fs::is_directory(PrefixDir)) { SmallString<128> P(PrefixDir); - for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) - if (ScanDirForExecutable(P, TargetSpecificExecutable)) - return std::string(P.str()); + if (ScanDirForExecutable(P, Name)) + return std::string(P.str()); } else { SmallString<128> P((PrefixDir + Name).str()); if (llvm::sys::fs::can_execute(Twine(P))) @@ -4931,9 +5113,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, !Target.hasEnvironment()) TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target, Args); - else if (Target.getArch() == llvm::Triple::ppc || - Target.getArch() == llvm::Triple::ppc64 || - Target.getArch() == llvm::Triple::ppc64le) + else if (Target.isPPC()) TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target, Args); else if (Target.getArch() == llvm::Triple::ve) @@ -4996,6 +5176,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Hurd: TC = std::make_unique<toolchains::Hurd>(*this, Target, Args); break; + case llvm::Triple::ZOS: + TC = std::make_unique<toolchains::ZOS>(*this, Target, Args); + break; default: // Of these targets, Hexagon is the only one that might have // an OS of Linux, in which case it got handled above already. @@ -5029,7 +5212,11 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: - TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args); + if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args)) + TC = + std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args); + else + TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args); break; case llvm::Triple::ve: TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args); |