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