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