18#include "llvm/ADT/STLExtras.h"
19#include "llvm/Option/ArgList.h"
20#include "llvm/Option/OptSpecifier.h"
21#include "llvm/Option/Option.h"
22#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/ThreadPool.h"
24#include "llvm/Support/Threading.h"
25#include "llvm/Support/raw_ostream.h"
26#include "llvm/TargetParser/Triple.h"
31#include <system_error>
39 InputArgList *_Args, DerivedArgList *_TranslatedArgs,
41 : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
42 TranslatedArgs(_TranslatedArgs), ContainsError(ContainsError) {
44 OrderedOffloadingToolchains.insert(
51 if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
54 delete TranslatedArgs;
58 for (
auto Arg : TCArgs)
59 if (Arg.second != TranslatedArgs)
67 TC = &DefaultToolChain;
69 DerivedArgList *&Entry = TCArgs[{TC, BA, DeviceOffloadKind}];
72 DerivedArgList *OpenMPArgs =
nullptr;
78 *TranslatedArgs, SameTripleAsHost, AllocatedArgs);
81 DerivedArgList *NewDAL =
nullptr;
95 Entry = TC->
TranslateArgs(*TranslatedArgs, BA, DeviceOffloadKind);
97 Entry = TranslatedArgs;
107 for (
auto *ArgPtr : AllocatedArgs)
108 Entry->AddSynthesizedArg(ArgPtr);
128 if (!llvm::sys::fs::can_write(
File) || !llvm::sys::fs::is_regular_file(
File))
131 if (std::error_code EC = llvm::sys::fs::remove(
File)) {
145 bool IssueErrors)
const {
147 for (
const auto &
File: Files)
154 bool IssueErrors)
const {
156 for (
const auto &
File : Files) {
159 if (JA &&
File.first != JA)
167 const Command *&FailingCommand,
168 bool LogOnly)
const {
171 raw_ostream *OS = &llvm::errs();
172 std::unique_ptr<llvm::raw_fd_ostream> OwnedStream;
177 !
getDriver().CCPrintOptionsFilename.empty()) {
179 OwnedStream.reset(
new llvm::raw_fd_ostream(
181 llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF));
188 OS = OwnedStream.get();
192 *OS <<
"[Logging clang options]\n";
194 C.Print(*OS,
"\n",
getDriver().CCPrintOptions);
201 bool ExecutionFailed;
202 int Res =
C.Execute(Redirects, &
Error, &ExecutionFailed);
204 PostCallback(
C, Res);
205 if (!
Error.empty()) {
206 assert(Res &&
"Error string set with 0 result code!");
213 return ExecutionFailed ? 1 : Res;
220 if (FailingCommands.empty())
230 for (
const auto &CI : FailingCommands)
231 if (A == &(CI.second->getSource()))
234 for (
const auto *AI : A->
inputs())
243 return ActionDependsOn(Input, Other);
265 return llvm::none_of(Jobs, [&](
const Command *Job) {
270static std::optional<llvm::ThreadPoolStrategy>
276 if (!OffloadJobs.isValid())
280 return llvm::jobserver_concurrency();
282 if (OffloadJobs.NumThreads < 2)
285 return llvm::hardware_concurrency(std::min(OffloadJobs.NumThreads, NumJobs));
298static std::optional<ParallelOffloadJobGroupResult>
300 ArrayRef<std::optional<StringRef>> Redirects,
304 const Command &Job = *JobStorage[StartIndex];
309 for (
size_t I = StartIndex; I < JobStorage.size(); ++I) {
310 const Command &Candidate = *JobStorage[I];
323 if (!llvm::all_of(ParallelJobs, [&](
const Command *
Other) {
325 &
Other->getSource());
329 ParallelJobs.push_back(&Candidate);
332 std::optional<llvm::ThreadPoolStrategy> Strategy =
338 llvm::DefaultThreadPool Pool(*Strategy);
339 for (
auto IndexedJob : llvm::enumerate(ParallelJobs)) {
340 size_t Index = IndexedJob.index();
341 const Command *ParallelJob = IndexedJob.value();
342 Pool.async([&, Index, ParallelJob] {
343 Results[Index].Res = ParallelJob->
Execute(
344 Redirects, &Results[Index].
Error, &Results[Index].ExecutionFailed);
349 for (
auto [Index, ParallelJob] : llvm::enumerate(ParallelJobs)) {
351 if (!
Result.Error.empty()) {
352 assert(
Result.Res &&
"Error string set with 0 result code!");
353 D.
Diag(diag::err_drv_command_failure) <<
Result.Error;
357 FailingCommands.push_back(
358 std::make_pair(
Result.ExecutionFailed ? 1 :
Result.Res, ParallelJob));
367 bool LogOnly)
const {
372 bool CanRunJobsInParallel =
376 Redirects.empty() && !PostCallback;
378 const auto &JobStorage = Jobs.getJobs();
379 for (
size_t I = 0; I < JobStorage.size();) {
380 const auto &Job = *JobStorage[I];
386 if (CanRunJobsInParallel) {
387 if (std::optional<ParallelOffloadJobGroupResult>
Result =
389 Redirects, JobStorage, I,
396 const Command *FailingCommand =
nullptr;
398 FailingCommands.push_back(std::make_pair(Res, FailingCommand));
400 if (TheDriver.IsCLMode())
408 ForDiagnostics =
true;
416 if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
422 FailureResultFiles.clear();
426 OptSpecifier OutputOpts[] = {
427 options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M,
428 options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ,
429 options::OPT_MQ, options::OPT_MT, options::OPT_MV};
430 for (
const auto &Opt : OutputOpts) {
431 if (TranslatedArgs->hasArg(Opt))
432 TranslatedArgs->eraseArg(Opt);
434 TranslatedArgs->ClaimAllArgs();
438 for (
auto Arg : TCArgs)
439 if (Arg.second != TranslatedArgs)
444 Redirects = {std::nullopt, {
""}, {
""}};
447 ForceKeepTempFiles =
true;
455 this->Redirects = Redirects;
static bool ActionFailed(const Action *A, const FailingCommandList &FailingCommands)
static bool HasDistinctBoundArch(const Command &Candidate, ArrayRef< const Command * > Jobs)
static bool ActionDependsOn(const Action *A, const Action *Other)
static bool ActionsAreIndependent(const Action *A, const Action *B)
static std::optional< ParallelOffloadJobGroupResult > tryExecuteParallelOffloadJobGroup(const Driver &D, const ArgList &Args, ArrayRef< std::optional< StringRef > > Redirects, const JobList::list_type &JobStorage, size_t StartIndex, FailingCommandList &FailingCommands)
static bool SameParallelOffloadJobGroup(const Command &A, const Command &B)
SmallVectorImpl< std::pair< int, const Command * > > FailingCommandList
static bool CanRunInParallelOffloadJobGroup(const Command &Job)
static std::optional< llvm::ThreadPoolStrategy > getParallelOffloadJobsStrategy(const ArgList &Args, unsigned NumJobs)
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Action - Represent an abstract compilation step to perform.
bool isOffloading(OffloadKind OKind) const
Command - An executable path/name and argument vector to execute.
const Action & getSource() const
getSource - Return the Action which caused the creation of this job.
StringRef getOffloadDeviceParallelJobGroup() const
bool PrintInputFilenames
Whether to print the input filenames when executing.
bool InProcess
Whether the command will be executed in this process or not.
BoundArch getBoundArch() const
Return the bound architecture for this command, if any.
virtual int Execute(ArrayRef< std::optional< StringRef > > Redirects, std::string *ErrMsg, bool *ExecutionFailed) const
int ExecuteCommand(const Command &C, const Command *&FailingCommand, bool LogOnly=false) const
ExecuteCommand - Execute an actual command.
bool CleanupFileMap(const ArgStringMap &Files, const JobAction *JA, bool IssueErrors=false) const
CleanupFileMap - Remove the files in the given map.
bool CleanupFile(const char *File, bool IssueErrors=false) const
CleanupFile - Delete a given file.
Compilation(const Driver &D, const ToolChain &DefaultToolChain, llvm::opt::InputArgList *Args, llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError)
bool CleanupFileList(const llvm::opt::ArgStringList &Files, bool IssueErrors=false) const
CleanupFileList - Remove the files in the given list.
const llvm::opt::DerivedArgList & getArgsForToolChain(const ToolChain *TC, BoundArch BA, Action::OffloadKind DeviceOffloadKind)
getArgsForToolChain - Return the derived argument list for the tool chain TC (or the default tool cha...
StringRef getSysRoot() const
Returns the sysroot path.
void Redirect(ArrayRef< std::optional< StringRef > > Redirects)
Redirect - Redirect output of this compilation.
void initCompilationForDiagnostics()
initCompilationForDiagnostics - Remove stale state and suppress output so compilation can be reexecut...
const llvm::opt::DerivedArgList & getArgs() const
void ExecuteJobs(const JobList &Jobs, SmallVectorImpl< std::pair< int, const Command * > > &FailingCommands, bool LogOnly=false) const
ExecuteJob - Execute a single job.
const ToolChain * getSingleOffloadToolChain() const
Return an offload toolchain of the provided kind.
const Driver & getDriver() const
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
std::string SysRoot
sysroot, if present
unsigned CCPrintProcessStats
Set CC_PRINT_PROC_STAT mode, which causes the driver to dump performance report to CC_PRINT_PROC_STAT...
bool IsCLMode() const
Whether the driver should follow cl.exe like behavior.
unsigned CCGenDiagnostics
Whether the driver is generating diagnostics for debugging purposes.
DiagnosticBuilder Diag(unsigned DiagID) const
unsigned CCPrintOptions
Set CC_PRINT_OPTIONS mode, which is like -v but logs the commands to CCPrintOptionsFilename or to std...
JobList - A sequence of jobs to perform.
SmallVector< std::unique_ptr< Command >, 4 > list_type
llvm::DenseMap< const JobAction *, const char * > ArgStringMap
ArgStringMap - Type used to map a JobAction to its result file.
The JSON file list parser is used to communicate input to InstallAPI.
@ Success
Annotation was successful.
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.
Represents a bound architecture for offload / multiple architecture compilation.