1341825Sdim//===- Action.cpp - Abstract compilation steps ----------------------------===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed
9193326Sed#include "clang/Driver/Action.h"
10226633Sdim#include "llvm/Support/ErrorHandling.h"
11193326Sed#include <cassert>
12341825Sdim#include <string>
13341825Sdim
14341825Sdimusing namespace clang;
15341825Sdimusing namespace driver;
16261991Sdimusing namespace llvm::opt;
17193326Sed
18341825SdimAction::~Action() = default;
19193326Sed
20193326Sedconst char *Action::getClassName(ActionClass AC) {
21193326Sed  switch (AC) {
22193326Sed  case InputClass: return "input";
23193326Sed  case BindArchClass: return "bind-arch";
24309124Sdim  case OffloadClass:
25309124Sdim    return "offload";
26193326Sed  case PreprocessJobClass: return "preprocessor";
27193326Sed  case PrecompileJobClass: return "precompiler";
28344779Sdim  case HeaderModulePrecompileJobClass: return "header-module-precompiler";
29193326Sed  case AnalyzeJobClass: return "analyzer";
30234353Sdim  case MigrateJobClass: return "migrator";
31193326Sed  case CompileJobClass: return "compiler";
32280031Sdim  case BackendJobClass: return "backend";
33193326Sed  case AssembleJobClass: return "assembler";
34360784Sdim  case IfsMergeJobClass: return "interface-stub-merger";
35193326Sed  case LinkJobClass: return "linker";
36193326Sed  case LipoJobClass: return "lipo";
37210299Sed  case DsymutilJobClass: return "dsymutil";
38276479Sdim  case VerifyDebugInfoJobClass: return "verify-debug-info";
39276479Sdim  case VerifyPCHJobClass: return "verify-pch";
40314564Sdim  case OffloadBundlingJobClass:
41314564Sdim    return "clang-offload-bundler";
42314564Sdim  case OffloadUnbundlingJobClass:
43314564Sdim    return "clang-offload-unbundler";
44360784Sdim  case OffloadWrapperJobClass:
45360784Sdim    return "clang-offload-wrapper";
46193326Sed  }
47198092Srdivacky
48226633Sdim  llvm_unreachable("invalid class");
49193326Sed}
50193326Sed
51309124Sdimvoid Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
52309124Sdim  // Offload action set its own kinds on their dependences.
53309124Sdim  if (Kind == OffloadClass)
54309124Sdim    return;
55314564Sdim  // Unbundling actions use the host kinds.
56314564Sdim  if (Kind == OffloadUnbundlingJobClass)
57314564Sdim    return;
58309124Sdim
59309124Sdim  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
60309124Sdim         "Setting device kind to a different device??");
61309124Sdim  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
62309124Sdim  OffloadingDeviceKind = OKind;
63309124Sdim  OffloadingArch = OArch;
64309124Sdim
65309124Sdim  for (auto *A : Inputs)
66309124Sdim    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
67309124Sdim}
68309124Sdim
69309124Sdimvoid Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
70309124Sdim  // Offload action set its own kinds on their dependences.
71309124Sdim  if (Kind == OffloadClass)
72309124Sdim    return;
73309124Sdim
74309124Sdim  assert(OffloadingDeviceKind == OFK_None &&
75309124Sdim         "Setting a host kind in a device action.");
76309124Sdim  ActiveOffloadKindMask |= OKinds;
77309124Sdim  OffloadingArch = OArch;
78309124Sdim
79309124Sdim  for (auto *A : Inputs)
80309124Sdim    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
81309124Sdim}
82309124Sdim
83309124Sdimvoid Action::propagateOffloadInfo(const Action *A) {
84309124Sdim  if (unsigned HK = A->getOffloadingHostActiveKinds())
85309124Sdim    propagateHostOffloadInfo(HK, A->getOffloadingArch());
86309124Sdim  else
87309124Sdim    propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
88309124Sdim                               A->getOffloadingArch());
89309124Sdim}
90309124Sdim
91309124Sdimstd::string Action::getOffloadingKindPrefix() const {
92309124Sdim  switch (OffloadingDeviceKind) {
93309124Sdim  case OFK_None:
94309124Sdim    break;
95309124Sdim  case OFK_Host:
96309124Sdim    llvm_unreachable("Host kind is not an offloading device kind.");
97309124Sdim    break;
98309124Sdim  case OFK_Cuda:
99309124Sdim    return "device-cuda";
100314564Sdim  case OFK_OpenMP:
101314564Sdim    return "device-openmp";
102341825Sdim  case OFK_HIP:
103341825Sdim    return "device-hip";
104309124Sdim
105309124Sdim    // TODO: Add other programming models here.
106309124Sdim  }
107309124Sdim
108309124Sdim  if (!ActiveOffloadKindMask)
109341825Sdim    return {};
110309124Sdim
111309124Sdim  std::string Res("host");
112341825Sdim  assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
113341825Sdim           (ActiveOffloadKindMask & OFK_HIP)) &&
114341825Sdim         "Cannot offload CUDA and HIP at the same time");
115309124Sdim  if (ActiveOffloadKindMask & OFK_Cuda)
116309124Sdim    Res += "-cuda";
117341825Sdim  if (ActiveOffloadKindMask & OFK_HIP)
118341825Sdim    Res += "-hip";
119314564Sdim  if (ActiveOffloadKindMask & OFK_OpenMP)
120314564Sdim    Res += "-openmp";
121309124Sdim
122309124Sdim  // TODO: Add other programming models here.
123309124Sdim
124309124Sdim  return Res;
125309124Sdim}
126309124Sdim
127314564Sdim/// Return a string that can be used as prefix in order to generate unique files
128314564Sdim/// for each offloading kind.
129309124Sdimstd::string
130314564SdimAction::GetOffloadingFileNamePrefix(OffloadKind Kind,
131341825Sdim                                    StringRef NormalizedTriple,
132314564Sdim                                    bool CreatePrefixForHost) {
133314564Sdim  // Don't generate prefix for host actions unless required.
134314564Sdim  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
135341825Sdim    return {};
136309124Sdim
137309124Sdim  std::string Res("-");
138314564Sdim  Res += GetOffloadKindName(Kind);
139309124Sdim  Res += "-";
140309124Sdim  Res += NormalizedTriple;
141309124Sdim  return Res;
142309124Sdim}
143309124Sdim
144314564Sdim/// Return a string with the offload kind name. If that is not defined, we
145314564Sdim/// assume 'host'.
146341825SdimStringRef Action::GetOffloadKindName(OffloadKind Kind) {
147314564Sdim  switch (Kind) {
148314564Sdim  case OFK_None:
149314564Sdim  case OFK_Host:
150314564Sdim    return "host";
151314564Sdim  case OFK_Cuda:
152314564Sdim    return "cuda";
153314564Sdim  case OFK_OpenMP:
154314564Sdim    return "openmp";
155341825Sdim  case OFK_HIP:
156341825Sdim    return "hip";
157314564Sdim
158314564Sdim    // TODO: Add other programming models here.
159314564Sdim  }
160314564Sdim
161314564Sdim  llvm_unreachable("invalid offload kind");
162314564Sdim}
163314564Sdim
164234353Sdimvoid InputAction::anchor() {}
165234353Sdim
166198092SrdivackyInputAction::InputAction(const Arg &_Input, types::ID _Type)
167341825Sdim    : Action(InputClass, _Type), Input(_Input) {}
168193326Sed
169234353Sdimvoid BindArchAction::anchor() {}
170234353Sdim
171341825SdimBindArchAction::BindArchAction(Action *Input, StringRef ArchName)
172314564Sdim    : Action(BindArchClass, Input), ArchName(ArchName) {}
173193326Sed
174309124Sdimvoid OffloadAction::anchor() {}
175309124Sdim
176309124SdimOffloadAction::OffloadAction(const HostDependence &HDep)
177309124Sdim    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
178309124Sdim  OffloadingArch = HDep.getBoundArch();
179309124Sdim  ActiveOffloadKindMask = HDep.getOffloadKinds();
180309124Sdim  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
181309124Sdim                                             HDep.getBoundArch());
182296417Sdim}
183296417Sdim
184309124SdimOffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
185309124Sdim    : Action(OffloadClass, DDeps.getActions(), Ty),
186309124Sdim      DevToolChains(DDeps.getToolChains()) {
187309124Sdim  auto &OKinds = DDeps.getOffloadKinds();
188309124Sdim  auto &BArchs = DDeps.getBoundArchs();
189288943Sdim
190309124Sdim  // If all inputs agree on the same kind, use it also for this action.
191309124Sdim  if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
192309124Sdim    OffloadingDeviceKind = OKinds.front();
193309124Sdim
194309124Sdim  // If we have a single dependency, inherit the architecture from it.
195309124Sdim  if (OKinds.size() == 1)
196309124Sdim    OffloadingArch = BArchs.front();
197309124Sdim
198309124Sdim  // Propagate info to the dependencies.
199309124Sdim  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
200309124Sdim    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
201296417Sdim}
202288943Sdim
203309124SdimOffloadAction::OffloadAction(const HostDependence &HDep,
204309124Sdim                             const DeviceDependences &DDeps)
205309124Sdim    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
206309124Sdim      DevToolChains(DDeps.getToolChains()) {
207309124Sdim  // We use the kinds of the host dependence for this action.
208309124Sdim  OffloadingArch = HDep.getBoundArch();
209309124Sdim  ActiveOffloadKindMask = HDep.getOffloadKinds();
210309124Sdim  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
211309124Sdim                                             HDep.getBoundArch());
212309124Sdim
213309124Sdim  // Add device inputs and propagate info to the device actions. Do work only if
214309124Sdim  // we have dependencies.
215309124Sdim  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
216309124Sdim    if (auto *A = DDeps.getActions()[i]) {
217309124Sdim      getInputs().push_back(A);
218309124Sdim      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
219309124Sdim                                    DDeps.getBoundArchs()[i]);
220309124Sdim    }
221296417Sdim}
222296417Sdim
223309124Sdimvoid OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
224309124Sdim  if (!HostTC)
225309124Sdim    return;
226309124Sdim  assert(!getInputs().empty() && "No dependencies for offload action??");
227309124Sdim  auto *A = getInputs().front();
228309124Sdim  Work(A, HostTC, A->getOffloadingArch());
229296417Sdim}
230296417Sdim
231309124Sdimvoid OffloadAction::doOnEachDeviceDependence(
232309124Sdim    const OffloadActionWorkTy &Work) const {
233309124Sdim  auto I = getInputs().begin();
234309124Sdim  auto E = getInputs().end();
235309124Sdim  if (I == E)
236309124Sdim    return;
237288943Sdim
238309124Sdim  // We expect to have the same number of input dependences and device tool
239309124Sdim  // chains, except if we also have a host dependence. In that case we have one
240309124Sdim  // more dependence than we have device tool chains.
241309124Sdim  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
242309124Sdim         "Sizes of action dependences and toolchains are not consistent!");
243288943Sdim
244309124Sdim  // Skip host action
245309124Sdim  if (HostTC)
246309124Sdim    ++I;
247309124Sdim
248309124Sdim  auto TI = DevToolChains.begin();
249309124Sdim  for (; I != E; ++I, ++TI)
250309124Sdim    Work(*I, *TI, (*I)->getOffloadingArch());
251309124Sdim}
252309124Sdim
253309124Sdimvoid OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
254309124Sdim  doOnHostDependence(Work);
255309124Sdim  doOnEachDeviceDependence(Work);
256309124Sdim}
257309124Sdim
258309124Sdimvoid OffloadAction::doOnEachDependence(bool IsHostDependence,
259309124Sdim                                       const OffloadActionWorkTy &Work) const {
260309124Sdim  if (IsHostDependence)
261309124Sdim    doOnHostDependence(Work);
262309124Sdim  else
263309124Sdim    doOnEachDeviceDependence(Work);
264309124Sdim}
265309124Sdim
266309124Sdimbool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
267309124Sdim
268309124SdimAction *OffloadAction::getHostDependence() const {
269309124Sdim  assert(hasHostDependence() && "Host dependence does not exist!");
270309124Sdim  assert(!getInputs().empty() && "No dependencies for offload action??");
271309124Sdim  return HostTC ? getInputs().front() : nullptr;
272309124Sdim}
273309124Sdim
274309124Sdimbool OffloadAction::hasSingleDeviceDependence(
275309124Sdim    bool DoNotConsiderHostActions) const {
276309124Sdim  if (DoNotConsiderHostActions)
277309124Sdim    return getInputs().size() == (HostTC ? 2 : 1);
278309124Sdim  return !HostTC && getInputs().size() == 1;
279309124Sdim}
280309124Sdim
281309124SdimAction *
282309124SdimOffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
283309124Sdim  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
284309124Sdim         "Single device dependence does not exist!");
285309124Sdim  // The previous assert ensures the number of entries in getInputs() is
286309124Sdim  // consistent with what we are doing here.
287309124Sdim  return HostTC ? getInputs()[1] : getInputs().front();
288309124Sdim}
289309124Sdim
290309124Sdimvoid OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
291309124Sdim                                           const char *BoundArch,
292309124Sdim                                           OffloadKind OKind) {
293309124Sdim  DeviceActions.push_back(&A);
294309124Sdim  DeviceToolChains.push_back(&TC);
295309124Sdim  DeviceBoundArchs.push_back(BoundArch);
296309124Sdim  DeviceOffloadKinds.push_back(OKind);
297309124Sdim}
298309124Sdim
299309124SdimOffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
300309124Sdim                                              const char *BoundArch,
301309124Sdim                                              const DeviceDependences &DDeps)
302309124Sdim    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
303309124Sdim  for (auto K : DDeps.getOffloadKinds())
304309124Sdim    HostOffloadKinds |= K;
305309124Sdim}
306309124Sdim
307234353Sdimvoid JobAction::anchor() {}
308234353Sdim
309296417SdimJobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
310296417Sdim    : Action(Kind, Input, Type) {}
311193326Sed
312198092SrdivackyJobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
313341825Sdim    : Action(Kind, Inputs, Type) {}
314193326Sed
315234353Sdimvoid PreprocessJobAction::anchor() {}
316234353Sdim
317296417SdimPreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
318296417Sdim    : JobAction(PreprocessJobClass, Input, OutputType) {}
319193326Sed
320234353Sdimvoid PrecompileJobAction::anchor() {}
321234353Sdim
322296417SdimPrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
323296417Sdim    : JobAction(PrecompileJobClass, Input, OutputType) {}
324193326Sed
325344779SdimPrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
326344779Sdim                                         types::ID OutputType)
327344779Sdim    : JobAction(Kind, Input, OutputType) {
328344779Sdim  assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
329344779Sdim}
330344779Sdim
331344779Sdimvoid HeaderModulePrecompileJobAction::anchor() {}
332344779Sdim
333344779SdimHeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
334344779Sdim    Action *Input, types::ID OutputType, const char *ModuleName)
335344779Sdim    : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
336344779Sdim      ModuleName(ModuleName) {}
337344779Sdim
338234353Sdimvoid AnalyzeJobAction::anchor() {}
339234353Sdim
340296417SdimAnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
341296417Sdim    : JobAction(AnalyzeJobClass, Input, OutputType) {}
342193326Sed
343234353Sdimvoid MigrateJobAction::anchor() {}
344234353Sdim
345296417SdimMigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
346296417Sdim    : JobAction(MigrateJobClass, Input, OutputType) {}
347234353Sdim
348234353Sdimvoid CompileJobAction::anchor() {}
349234353Sdim
350296417SdimCompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
351296417Sdim    : JobAction(CompileJobClass, Input, OutputType) {}
352193326Sed
353280031Sdimvoid BackendJobAction::anchor() {}
354280031Sdim
355296417SdimBackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
356296417Sdim    : JobAction(BackendJobClass, Input, OutputType) {}
357280031Sdim
358234353Sdimvoid AssembleJobAction::anchor() {}
359234353Sdim
360296417SdimAssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
361296417Sdim    : JobAction(AssembleJobClass, Input, OutputType) {}
362193326Sed
363360784Sdimvoid IfsMergeJobAction::anchor() {}
364360784Sdim
365360784SdimIfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
366360784Sdim    : JobAction(IfsMergeJobClass, Inputs, Type) {}
367360784Sdim
368234353Sdimvoid LinkJobAction::anchor() {}
369234353Sdim
370198092SrdivackyLinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
371341825Sdim    : JobAction(LinkJobClass, Inputs, Type) {}
372193326Sed
373234353Sdimvoid LipoJobAction::anchor() {}
374234353Sdim
375198092SrdivackyLipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
376341825Sdim    : JobAction(LipoJobClass, Inputs, Type) {}
377210299Sed
378234353Sdimvoid DsymutilJobAction::anchor() {}
379234353Sdim
380210299SedDsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
381341825Sdim    : JobAction(DsymutilJobClass, Inputs, Type) {}
382226633Sdim
383234353Sdimvoid VerifyJobAction::anchor() {}
384234353Sdim
385296417SdimVerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
386296417Sdim                                 types::ID Type)
387296417Sdim    : JobAction(Kind, Input, Type) {
388276479Sdim  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
389276479Sdim         "ActionClass is not a valid VerifyJobAction");
390226633Sdim}
391276479Sdim
392276479Sdimvoid VerifyDebugInfoJobAction::anchor() {}
393276479Sdim
394296417SdimVerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
395296417Sdim                                                   types::ID Type)
396296417Sdim    : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
397276479Sdim
398276479Sdimvoid VerifyPCHJobAction::anchor() {}
399276479Sdim
400296417SdimVerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
401296417Sdim    : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
402314564Sdim
403314564Sdimvoid OffloadBundlingJobAction::anchor() {}
404314564Sdim
405314564SdimOffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
406344779Sdim    : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
407314564Sdim
408314564Sdimvoid OffloadUnbundlingJobAction::anchor() {}
409314564Sdim
410314564SdimOffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
411314564Sdim    : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
412360784Sdim
413360784Sdimvoid OffloadWrapperJobAction::anchor() {}
414360784Sdim
415360784SdimOffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs,
416360784Sdim                                                 types::ID Type)
417360784Sdim  : JobAction(OffloadWrapperJobClass, Inputs, Type) {}
418