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