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