clang  11.0.0git
Action.cpp
Go to the documentation of this file.
1 //===- Action.cpp - Abstract compilation steps ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Driver/Action.h"
10 #include "llvm/Support/ErrorHandling.h"
11 #include <cassert>
12 #include <string>
13 
14 using namespace clang;
15 using namespace driver;
16 using namespace llvm::opt;
17 
18 Action::~Action() = default;
19 
21  switch (AC) {
22  case InputClass: return "input";
23  case BindArchClass: return "bind-arch";
24  case OffloadClass:
25  return "offload";
26  case PreprocessJobClass: return "preprocessor";
27  case PrecompileJobClass: return "precompiler";
28  case HeaderModulePrecompileJobClass: return "header-module-precompiler";
29  case AnalyzeJobClass: return "analyzer";
30  case MigrateJobClass: return "migrator";
31  case CompileJobClass: return "compiler";
32  case BackendJobClass: return "backend";
33  case AssembleJobClass: return "assembler";
34  case IfsMergeJobClass: return "interface-stub-merger";
35  case LinkJobClass: return "linker";
36  case LipoJobClass: return "lipo";
37  case DsymutilJobClass: return "dsymutil";
38  case VerifyDebugInfoJobClass: return "verify-debug-info";
39  case VerifyPCHJobClass: return "verify-pch";
40  case OffloadBundlingJobClass:
41  return "clang-offload-bundler";
42  case OffloadUnbundlingJobClass:
43  return "clang-offload-unbundler";
44  case OffloadWrapperJobClass:
45  return "clang-offload-wrapper";
46  case StaticLibJobClass:
47  return "static-lib-linker";
48  }
49 
50  llvm_unreachable("invalid class");
51 }
52 
53 void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
54  // Offload action set its own kinds on their dependences.
55  if (Kind == OffloadClass)
56  return;
57  // Unbundling actions use the host kinds.
58  if (Kind == OffloadUnbundlingJobClass)
59  return;
60 
61  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
62  "Setting device kind to a different device??");
63  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
64  OffloadingDeviceKind = OKind;
65  OffloadingArch = OArch;
66 
67  for (auto *A : Inputs)
68  A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
69 }
70 
71 void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
72  // Offload action set its own kinds on their dependences.
73  if (Kind == OffloadClass)
74  return;
75 
76  assert(OffloadingDeviceKind == OFK_None &&
77  "Setting a host kind in a device action.");
78  ActiveOffloadKindMask |= OKinds;
79  OffloadingArch = OArch;
80 
81  for (auto *A : Inputs)
82  A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
83 }
84 
86  if (unsigned HK = A->getOffloadingHostActiveKinds())
87  propagateHostOffloadInfo(HK, A->getOffloadingArch());
88  else
89  propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
90  A->getOffloadingArch());
91 }
92 
93 std::string Action::getOffloadingKindPrefix() const {
94  switch (OffloadingDeviceKind) {
95  case OFK_None:
96  break;
97  case OFK_Host:
98  llvm_unreachable("Host kind is not an offloading device kind.");
99  break;
100  case OFK_Cuda:
101  return "device-cuda";
102  case OFK_OpenMP:
103  return "device-openmp";
104  case OFK_HIP:
105  return "device-hip";
106 
107  // TODO: Add other programming models here.
108  }
109 
110  if (!ActiveOffloadKindMask)
111  return {};
112 
113  std::string Res("host");
114  assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
115  (ActiveOffloadKindMask & OFK_HIP)) &&
116  "Cannot offload CUDA and HIP at the same time");
117  if (ActiveOffloadKindMask & OFK_Cuda)
118  Res += "-cuda";
119  if (ActiveOffloadKindMask & OFK_HIP)
120  Res += "-hip";
121  if (ActiveOffloadKindMask & OFK_OpenMP)
122  Res += "-openmp";
123 
124  // TODO: Add other programming models here.
125 
126  return Res;
127 }
128 
129 /// Return a string that can be used as prefix in order to generate unique files
130 /// for each offloading kind.
131 std::string
133  StringRef NormalizedTriple,
134  bool CreatePrefixForHost) {
135  // Don't generate prefix for host actions unless required.
136  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
137  return {};
138 
139  std::string Res("-");
140  Res += GetOffloadKindName(Kind);
141  Res += "-";
142  Res += NormalizedTriple;
143  return Res;
144 }
145 
146 /// Return a string with the offload kind name. If that is not defined, we
147 /// assume 'host'.
149  switch (Kind) {
150  case OFK_None:
151  case OFK_Host:
152  return "host";
153  case OFK_Cuda:
154  return "cuda";
155  case OFK_OpenMP:
156  return "openmp";
157  case OFK_HIP:
158  return "hip";
159 
160  // TODO: Add other programming models here.
161  }
162 
163  llvm_unreachable("invalid offload kind");
164 }
165 
166 void InputAction::anchor() {}
167 
168 InputAction::InputAction(const Arg &_Input, types::ID _Type)
169  : Action(InputClass, _Type), Input(_Input) {}
170 
171 void BindArchAction::anchor() {}
172 
173 BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
174  : Action(BindArchClass, Input), ArchName(ArchName) {}
175 
176 void OffloadAction::anchor() {}
177 
179  : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
180  OffloadingArch = HDep.getBoundArch();
183  HDep.getBoundArch());
184 }
185 
187  : Action(OffloadClass, DDeps.getActions(), Ty),
188  DevToolChains(DDeps.getToolChains()) {
189  auto &OKinds = DDeps.getOffloadKinds();
190  auto &BArchs = DDeps.getBoundArchs();
191 
192  // If all inputs agree on the same kind, use it also for this action.
193  if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
194  OffloadingDeviceKind = OKinds.front();
195 
196  // If we have a single dependency, inherit the architecture from it.
197  if (OKinds.size() == 1)
198  OffloadingArch = BArchs.front();
199 
200  // Propagate info to the dependencies.
201  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
202  getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
203 }
204 
206  const DeviceDependences &DDeps)
207  : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
208  DevToolChains(DDeps.getToolChains()) {
209  // We use the kinds of the host dependence for this action.
210  OffloadingArch = HDep.getBoundArch();
213  HDep.getBoundArch());
214 
215  // Add device inputs and propagate info to the device actions. Do work only if
216  // we have dependencies.
217  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
218  if (auto *A = DDeps.getActions()[i]) {
219  getInputs().push_back(A);
220  A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
221  DDeps.getBoundArchs()[i]);
222  }
223 }
224 
226  if (!HostTC)
227  return;
228  assert(!getInputs().empty() && "No dependencies for offload action??");
229  auto *A = getInputs().front();
230  Work(A, HostTC, A->getOffloadingArch());
231 }
232 
234  const OffloadActionWorkTy &Work) const {
235  auto I = getInputs().begin();
236  auto E = getInputs().end();
237  if (I == E)
238  return;
239 
240  // We expect to have the same number of input dependences and device tool
241  // chains, except if we also have a host dependence. In that case we have one
242  // more dependence than we have device tool chains.
243  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
244  "Sizes of action dependences and toolchains are not consistent!");
245 
246  // Skip host action
247  if (HostTC)
248  ++I;
249 
250  auto TI = DevToolChains.begin();
251  for (; I != E; ++I, ++TI)
252  Work(*I, *TI, (*I)->getOffloadingArch());
253 }
254 
256  doOnHostDependence(Work);
258 }
259 
260 void OffloadAction::doOnEachDependence(bool IsHostDependence,
261  const OffloadActionWorkTy &Work) const {
262  if (IsHostDependence)
263  doOnHostDependence(Work);
264  else
266 }
267 
268 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
269 
271  assert(hasHostDependence() && "Host dependence does not exist!");
272  assert(!getInputs().empty() && "No dependencies for offload action??");
273  return HostTC ? getInputs().front() : nullptr;
274 }
275 
277  bool DoNotConsiderHostActions) const {
278  if (DoNotConsiderHostActions)
279  return getInputs().size() == (HostTC ? 2 : 1);
280  return !HostTC && getInputs().size() == 1;
281 }
282 
283 Action *
284 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
285  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
286  "Single device dependence does not exist!");
287  // The previous assert ensures the number of entries in getInputs() is
288  // consistent with what we are doing here.
289  return HostTC ? getInputs()[1] : getInputs().front();
290 }
291 
293  const char *BoundArch,
294  OffloadKind OKind) {
295  DeviceActions.push_back(&A);
296  DeviceToolChains.push_back(&TC);
297  DeviceBoundArchs.push_back(BoundArch);
298  DeviceOffloadKinds.push_back(OKind);
299 }
300 
302  const char *BoundArch,
303  const DeviceDependences &DDeps)
304  : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
305  for (auto K : DDeps.getOffloadKinds())
306  HostOffloadKinds |= K;
307 }
308 
309 void JobAction::anchor() {}
310 
312  : Action(Kind, Input, Type) {}
313 
315  : Action(Kind, Inputs, Type) {}
316 
317 void PreprocessJobAction::anchor() {}
318 
320  : JobAction(PreprocessJobClass, Input, OutputType) {}
321 
322 void PrecompileJobAction::anchor() {}
323 
325  : JobAction(PrecompileJobClass, Input, OutputType) {}
326 
328  types::ID OutputType)
329  : JobAction(Kind, Input, OutputType) {
330  assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
331 }
332 
333 void HeaderModulePrecompileJobAction::anchor() {}
334 
336  Action *Input, types::ID OutputType, const char *ModuleName)
338  ModuleName(ModuleName) {}
339 
340 void AnalyzeJobAction::anchor() {}
341 
343  : JobAction(AnalyzeJobClass, Input, OutputType) {}
344 
345 void MigrateJobAction::anchor() {}
346 
348  : JobAction(MigrateJobClass, Input, OutputType) {}
349 
350 void CompileJobAction::anchor() {}
351 
353  : JobAction(CompileJobClass, Input, OutputType) {}
354 
355 void BackendJobAction::anchor() {}
356 
358  : JobAction(BackendJobClass, Input, OutputType) {}
359 
360 void AssembleJobAction::anchor() {}
361 
363  : JobAction(AssembleJobClass, Input, OutputType) {}
364 
365 void IfsMergeJobAction::anchor() {}
366 
368  : JobAction(IfsMergeJobClass, Inputs, Type) {}
369 
370 void LinkJobAction::anchor() {}
371 
373  : JobAction(LinkJobClass, Inputs, Type) {}
374 
375 void LipoJobAction::anchor() {}
376 
378  : JobAction(LipoJobClass, Inputs, Type) {}
379 
380 void DsymutilJobAction::anchor() {}
381 
383  : JobAction(DsymutilJobClass, Inputs, Type) {}
384 
385 void VerifyJobAction::anchor() {}
386 
388  types::ID Type)
389  : JobAction(Kind, Input, Type) {
390  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
391  "ActionClass is not a valid VerifyJobAction");
392 }
393 
394 void VerifyDebugInfoJobAction::anchor() {}
395 
397  types::ID Type)
398  : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
399 
400 void VerifyPCHJobAction::anchor() {}
401 
403  : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
404 
405 void OffloadBundlingJobAction::anchor() {}
406 
408  : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
409 
410 void OffloadUnbundlingJobAction::anchor() {}
411 
413  : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
414 
415 void OffloadWrapperJobAction::anchor() {}
416 
418  types::ID Type)
419  : JobAction(OffloadWrapperJobClass, Inputs, Type) {}
420 
421 void StaticLibJobAction::anchor() {}
422 
424  : JobAction(StaticLibJobClass, Inputs, Type) {}
AssembleJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:362
OffloadAction(const HostDependence &HDep)
Definition: Action.cpp:178
BackendJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:357
const OffloadKindList & getOffloadKinds() const
Definition: Action.h:290
MigrateJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:347
The base class of the type hierarchy.
Definition: Type.h:1472
LinkJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:372
Type used to communicate device actions.
Definition: Action.h:256
const char * getClassName() const
Definition: Action.h:140
InputAction(const llvm::opt::Arg &Input, types::ID Type)
Definition: Action.cpp:168
void doOnHostDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on the host dependence.
Definition: Action.cpp:225
VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type)
Definition: Action.cpp:387
VerifyDebugInfoJobAction(Action *Input, types::ID Type)
Definition: Action.cpp:396
CompileJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:352
JobAction(ActionClass Kind, Action *Input, types::ID Type)
Definition: Action.cpp:311
OffloadKind OffloadingDeviceKind
Offloading kind of the device.
Definition: Action.h:124
ActionList & getInputs()
Definition: Action.h:145
void doOnEachDeviceDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on each device dependence.
Definition: Action.cpp:233
LipoJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:377
Type used to communicate host actions.
Definition: Action.h:297
Action - Represent an abstract compilation step to perform.
Definition: Action.h:47
Action * getHostDependence() const
Return the host dependence of this action.
Definition: Action.cpp:270
void propagateOffloadInfo(const Action *A)
Set the offload info of this action to be the same as the provided action, and propagate it to its de...
Definition: Action.cpp:85
types::ID getType() const
Definition: Action.h:143
DsymutilJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:382
PreprocessJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:319
OffloadKind getOffloadingDeviceKind() const
Definition: Action.h:199
void doOnEachDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on each dependence.
Definition: Action.cpp:255
void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch)
Set the device offload info of this action and propagate it to its dependences.
Definition: Action.cpp:53
void add(Action &A, const ToolChain &TC, const char *BoundArch, OffloadKind OKind)
Add a action along with the associated toolchain, bound arch, and offload kind.
Definition: Action.cpp:292
bool hasHostDependence() const
Return true if the action has a host dependence.
Definition: Action.cpp:268
unsigned ActiveOffloadKindMask
Offload information.
Definition: Action.h:121
IfsMergeJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:367
VerifyPCHJobAction(Action *Input, types::ID Type)
Definition: Action.cpp:402
const BoundArchList & getBoundArchs() const
Definition: Action.h:289
size_type size() const
Definition: Action.h:148
const ActionList & getActions() const
Get each of the individual arrays.
Definition: Action.h:287
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, const unsigned OffloadKinds)
Definition: Action.h:311
const char * OffloadingArch
The Offloading architecture associated with this action.
Definition: Action.h:127
BindArchAction(Action *Input, StringRef ArchName)
Definition: Action.cpp:173
Kind
AnalyzeJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:342
OffloadWrapperJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:417
OffloadBundlingJobAction(ActionList &Inputs)
Definition: Action.cpp:407
unsigned getOffloadingHostActiveKinds() const
Definition: Action.h:195
Dataflow Directional Tag Classes.
llvm::function_ref< void(Action *, const ToolChain *, const char *)> OffloadActionWorkTy
Definition: Action.h:327
bool hasSingleDeviceDependence(bool DoNotConsiderHostActions=false) const
Return true if the action has a single device dependence.
Definition: Action.cpp:276
static StringRef GetOffloadKindName(OffloadKind Kind)
Return a string containing a offload kind name.
Definition: Action.cpp:148
void propagateHostOffloadInfo(unsigned OKinds, const char *OArch)
Append the host offload info of this action and propagate it to its dependences.
Definition: Action.cpp:71
static std::string GetOffloadingFileNamePrefix(OffloadKind Kind, StringRef NormalizedTriple, bool CreatePrefixForHost=false)
Return a string that can be used as prefix in order to generate unique files for each offloading kind...
Definition: Action.cpp:132
StaticLibJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:423
std::string getOffloadingKindPrefix() const
Return a string containing the offload kind of the action.
Definition: Action.cpp:93
HeaderModulePrecompileJobAction(Action *Input, types::ID OutputType, const char *ModuleName)
Definition: Action.cpp:335
PrecompileJobAction(ActionClass Kind, Action *Input, types::ID OutputType)
Definition: Action.cpp:327
Action * getSingleDeviceDependence(bool DoNotConsiderHostActions=false) const
Return the single device dependence of this action.
Definition: Action.cpp:284
const char * getOffloadingArch() const
Definition: Action.h:200
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:90