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