aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/Driver.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Driver/Driver.cpp347
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);