clang  6.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 "clang/Driver/ToolChain.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/Regex.h"
16 #include <cassert>
17 using namespace clang::driver;
18 using namespace llvm::opt;
19 
21 
23  switch (AC) {
24  case InputClass: return "input";
25  case BindArchClass: return "bind-arch";
26  case OffloadClass:
27  return "offload";
28  case PreprocessJobClass: return "preprocessor";
29  case PrecompileJobClass: return "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 
101  // TODO: Add other programming models here.
102  }
103 
104  if (!ActiveOffloadKindMask)
105  return "";
106 
107  std::string Res("host");
108  if (ActiveOffloadKindMask & OFK_Cuda)
109  Res += "-cuda";
110  if (ActiveOffloadKindMask & OFK_OpenMP)
111  Res += "-openmp";
112 
113  // TODO: Add other programming models here.
114 
115  return Res;
116 }
117 
118 /// Return a string that can be used as prefix in order to generate unique files
119 /// for each offloading kind.
120 std::string
122  llvm::StringRef NormalizedTriple,
123  bool CreatePrefixForHost) {
124  // Don't generate prefix for host actions unless required.
125  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
126  return "";
127 
128  std::string Res("-");
129  Res += GetOffloadKindName(Kind);
130  Res += "-";
131  Res += NormalizedTriple;
132  return Res;
133 }
134 
135 /// Return a string with the offload kind name. If that is not defined, we
136 /// assume 'host'.
138  switch (Kind) {
139  case OFK_None:
140  case OFK_Host:
141  return "host";
142  case OFK_Cuda:
143  return "cuda";
144  case OFK_OpenMP:
145  return "openmp";
146 
147  // TODO: Add other programming models here.
148  }
149 
150  llvm_unreachable("invalid offload kind");
151 }
152 
153 void InputAction::anchor() {}
154 
155 InputAction::InputAction(const Arg &_Input, types::ID _Type)
156  : Action(InputClass, _Type), Input(_Input) {
157 }
158 
159 void BindArchAction::anchor() {}
160 
161 BindArchAction::BindArchAction(Action *Input, llvm::StringRef ArchName)
162  : Action(BindArchClass, Input), ArchName(ArchName) {}
163 
164 void OffloadAction::anchor() {}
165 
167  : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
168  OffloadingArch = HDep.getBoundArch();
171  HDep.getBoundArch());
172 }
173 
175  : Action(OffloadClass, DDeps.getActions(), Ty),
176  DevToolChains(DDeps.getToolChains()) {
177  auto &OKinds = DDeps.getOffloadKinds();
178  auto &BArchs = DDeps.getBoundArchs();
179 
180  // If all inputs agree on the same kind, use it also for this action.
181  if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
182  OffloadingDeviceKind = OKinds.front();
183 
184  // If we have a single dependency, inherit the architecture from it.
185  if (OKinds.size() == 1)
186  OffloadingArch = BArchs.front();
187 
188  // Propagate info to the dependencies.
189  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
190  getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
191 }
192 
194  const DeviceDependences &DDeps)
195  : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
196  DevToolChains(DDeps.getToolChains()) {
197  // We use the kinds of the host dependence for this action.
198  OffloadingArch = HDep.getBoundArch();
201  HDep.getBoundArch());
202 
203  // Add device inputs and propagate info to the device actions. Do work only if
204  // we have dependencies.
205  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
206  if (auto *A = DDeps.getActions()[i]) {
207  getInputs().push_back(A);
208  A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
209  DDeps.getBoundArchs()[i]);
210  }
211 }
212 
214  if (!HostTC)
215  return;
216  assert(!getInputs().empty() && "No dependencies for offload action??");
217  auto *A = getInputs().front();
218  Work(A, HostTC, A->getOffloadingArch());
219 }
220 
222  const OffloadActionWorkTy &Work) const {
223  auto I = getInputs().begin();
224  auto E = getInputs().end();
225  if (I == E)
226  return;
227 
228  // We expect to have the same number of input dependences and device tool
229  // chains, except if we also have a host dependence. In that case we have one
230  // more dependence than we have device tool chains.
231  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
232  "Sizes of action dependences and toolchains are not consistent!");
233 
234  // Skip host action
235  if (HostTC)
236  ++I;
237 
238  auto TI = DevToolChains.begin();
239  for (; I != E; ++I, ++TI)
240  Work(*I, *TI, (*I)->getOffloadingArch());
241 }
242 
244  doOnHostDependence(Work);
246 }
247 
248 void OffloadAction::doOnEachDependence(bool IsHostDependence,
249  const OffloadActionWorkTy &Work) const {
250  if (IsHostDependence)
251  doOnHostDependence(Work);
252  else
254 }
255 
256 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
257 
259  assert(hasHostDependence() && "Host dependence does not exist!");
260  assert(!getInputs().empty() && "No dependencies for offload action??");
261  return HostTC ? getInputs().front() : nullptr;
262 }
263 
265  bool DoNotConsiderHostActions) const {
266  if (DoNotConsiderHostActions)
267  return getInputs().size() == (HostTC ? 2 : 1);
268  return !HostTC && getInputs().size() == 1;
269 }
270 
271 Action *
272 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
273  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
274  "Single device dependence does not exist!");
275  // The previous assert ensures the number of entries in getInputs() is
276  // consistent with what we are doing here.
277  return HostTC ? getInputs()[1] : getInputs().front();
278 }
279 
281  const char *BoundArch,
282  OffloadKind OKind) {
283  DeviceActions.push_back(&A);
284  DeviceToolChains.push_back(&TC);
285  DeviceBoundArchs.push_back(BoundArch);
286  DeviceOffloadKinds.push_back(OKind);
287 }
288 
290  const char *BoundArch,
291  const DeviceDependences &DDeps)
292  : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
293  for (auto K : DDeps.getOffloadKinds())
294  HostOffloadKinds |= K;
295 }
296 
297 void JobAction::anchor() {}
298 
300  : Action(Kind, Input, Type) {}
301 
303  : Action(Kind, Inputs, Type) {
304 }
305 
306 void PreprocessJobAction::anchor() {}
307 
309  : JobAction(PreprocessJobClass, Input, OutputType) {}
310 
311 void PrecompileJobAction::anchor() {}
312 
314  : JobAction(PrecompileJobClass, Input, OutputType) {}
315 
316 void AnalyzeJobAction::anchor() {}
317 
319  : JobAction(AnalyzeJobClass, Input, OutputType) {}
320 
321 void MigrateJobAction::anchor() {}
322 
324  : JobAction(MigrateJobClass, Input, OutputType) {}
325 
326 void CompileJobAction::anchor() {}
327 
329  : JobAction(CompileJobClass, Input, OutputType) {}
330 
331 void BackendJobAction::anchor() {}
332 
334  : JobAction(BackendJobClass, Input, OutputType) {}
335 
336 void AssembleJobAction::anchor() {}
337 
339  : JobAction(AssembleJobClass, Input, OutputType) {}
340 
341 void LinkJobAction::anchor() {}
342 
344  : JobAction(LinkJobClass, Inputs, Type) {
345 }
346 
347 void LipoJobAction::anchor() {}
348 
350  : JobAction(LipoJobClass, Inputs, Type) {
351 }
352 
353 void DsymutilJobAction::anchor() {}
354 
356  : JobAction(DsymutilJobClass, Inputs, Type) {
357 }
358 
359 void VerifyJobAction::anchor() {}
360 
362  types::ID Type)
363  : JobAction(Kind, Input, Type) {
364  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
365  "ActionClass is not a valid VerifyJobAction");
366 }
367 
368 void VerifyDebugInfoJobAction::anchor() {}
369 
371  types::ID Type)
372  : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
373 
374 void VerifyPCHJobAction::anchor() {}
375 
377  : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
378 
379 void OffloadBundlingJobAction::anchor() {}
380 
382  : JobAction(OffloadBundlingJobClass, Inputs, Inputs.front()->getType()) {}
383 
384 void OffloadUnbundlingJobAction::anchor() {}
385 
387  : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
AssembleJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:338
OffloadAction(const HostDependence &HDep)
Definition: Action.cpp:166
PrecompileJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:313
BackendJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:333
const OffloadKindList & getOffloadKinds() const
Definition: Action.h:268
MigrateJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:323
The base class of the type hierarchy.
Definition: Type.h:1353
LinkJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:343
Type used to communicate device actions.
Definition: Action.h:237
const char * getClassName() const
Definition: Action.h:129
llvm::function_ref< void(Action *, const ToolChain *, const char *)> OffloadActionWorkTy
Definition: Action.h:301
InputAction(const llvm::opt::Arg &Input, types::ID Type)
Definition: Action.cpp:155
void doOnHostDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on the host dependence.
Definition: Action.cpp:213
VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type)
Definition: Action.cpp:361
VerifyDebugInfoJobAction(Action *Input, types::ID Type)
Definition: Action.cpp:370
CompileJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:328
JobAction(ActionClass Kind, Action *Input, types::ID Type)
Definition: Action.cpp:299
OffloadKind OffloadingDeviceKind
Offloading kind of the device.
Definition: Action.h:114
ActionList & getInputs()
Definition: Action.h:134
void doOnEachDeviceDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on each device dependence.
Definition: Action.cpp:221
LipoJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:349
Type used to communicate host actions.
Definition: Action.h:275
Action - Represent an abstract compilation step to perform.
Definition: Action.h:45
Action * getHostDependence() const
Return the host dependence of this action.
Definition: Action.cpp:258
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
static std::string GetOffloadingFileNamePrefix(OffloadKind Kind, llvm::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:121
types::ID getType() const
Definition: Action.h:132
DsymutilJobAction(ActionList &Inputs, types::ID Type)
Definition: Action.cpp:355
PreprocessJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:308
OffloadKind getOffloadingDeviceKind() const
Definition: Action.h:182
void doOnEachDependence(const OffloadActionWorkTy &Work) const
Execute the work specified in Work on each dependence.
Definition: Action.cpp:243
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:280
bool hasHostDependence() const
Return true if the action has a host dependence.
Definition: Action.cpp:256
unsigned ActiveOffloadKindMask
Offload information.
Definition: Action.h:112
virtual ~Action()
Definition: Action.cpp:20
VerifyPCHJobAction(Action *Input, types::ID Type)
Definition: Action.cpp:376
static StringRef GetOffloadKindName(OffloadKind Kind)
Return a string containing a offload kind name.
Definition: Action.cpp:137
const BoundArchList & getBoundArchs() const
Definition: Action.h:267
size_type size() const
Definition: Action.h:137
const ActionList & getActions() const
Get each of the individual arrays.
Definition: Action.h:265
HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, const unsigned OffloadKinds)
Definition: Action.h:286
const char * OffloadingArch
The Offloading architecture associated with this action.
Definition: Action.h:116
BindArchAction(Action *Input, StringRef ArchName)
Definition: Action.cpp:161
Kind
AnalyzeJobAction(Action *Input, types::ID OutputType)
Definition: Action.cpp:318
OffloadBundlingJobAction(ActionList &Inputs)
Definition: Action.cpp:381
unsigned getOffloadingHostActiveKinds() const
Definition: Action.h:179
bool hasSingleDeviceDependence(bool DoNotConsiderHostActions=false) const
Return true if the action has a single device dependence.
Definition: Action.cpp:264
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
std::string getOffloadingKindPrefix() const
Return a string containing the offload kind of the action.
Definition: Action.cpp:89
Action * getSingleDeviceDependence(bool DoNotConsiderHostActions=false) const
Return the single device dependence of this action.
Definition: Action.cpp:272
const char * getOffloadingArch() const
Definition: Action.h:183
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:73