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 
19 Action::~Action() {}
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   }
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 
73 void Action::propagateOffloadInfo(const Action *A) {
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 
128 BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
129     : Action(BindArchClass, Input), ArchName(_ArchName) {}
130 
131 void OffloadAction::anchor() {}
132 
133 OffloadAction::OffloadAction(const HostDependence &HDep)
134     : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
135   OffloadingArch = HDep.getBoundArch();
136   ActiveOffloadKindMask = HDep.getOffloadKinds();
137   HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
138                                              HDep.getBoundArch());
139 }
140 
141 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
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 
160 OffloadAction::OffloadAction(const HostDependence &HDep,
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();
166   ActiveOffloadKindMask = HDep.getOffloadKinds();
167   HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
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 
180 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
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 
188 void OffloadAction::doOnEachDeviceDependence(
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 
210 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
211   doOnHostDependence(Work);
212   doOnEachDeviceDependence(Work);
213 }
214 
215 void OffloadAction::doOnEachDependence(bool IsHostDependence,
216                                        const OffloadActionWorkTy &Work) const {
217   if (IsHostDependence)
218     doOnHostDependence(Work);
219   else
220     doOnEachDeviceDependence(Work);
221 }
222 
223 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
224 
225 Action *OffloadAction::getHostDependence() const {
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 
231 bool OffloadAction::hasSingleDeviceDependence(
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 
247 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
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 
256 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
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 
266 JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
267     : Action(Kind, Input, Type) {}
268 
269 JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
270   : Action(Kind, Inputs, Type) {
271 }
272 
273 void PreprocessJobAction::anchor() {}
274 
275 PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
276     : JobAction(PreprocessJobClass, Input, OutputType) {}
277 
278 void PrecompileJobAction::anchor() {}
279 
280 PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
281     : JobAction(PrecompileJobClass, Input, OutputType) {}
282 
283 void AnalyzeJobAction::anchor() {}
284 
285 AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
286     : JobAction(AnalyzeJobClass, Input, OutputType) {}
287 
288 void MigrateJobAction::anchor() {}
289 
290 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
291     : JobAction(MigrateJobClass, Input, OutputType) {}
292 
293 void CompileJobAction::anchor() {}
294 
295 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
296     : JobAction(CompileJobClass, Input, OutputType) {}
297 
298 void BackendJobAction::anchor() {}
299 
300 BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
301     : JobAction(BackendJobClass, Input, OutputType) {}
302 
303 void AssembleJobAction::anchor() {}
304 
305 AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
306     : JobAction(AssembleJobClass, Input, OutputType) {}
307 
308 void LinkJobAction::anchor() {}
309 
310 LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
311   : JobAction(LinkJobClass, Inputs, Type) {
312 }
313 
314 void LipoJobAction::anchor() {}
315 
316 LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
317   : JobAction(LipoJobClass, Inputs, Type) {
318 }
319 
320 void DsymutilJobAction::anchor() {}
321 
322 DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
323   : JobAction(DsymutilJobClass, Inputs, Type) {
324 }
325 
326 void VerifyJobAction::anchor() {}
327 
328 VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
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 
337 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
338                                                    types::ID Type)
339     : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
340 
341 void VerifyPCHJobAction::anchor() {}
342 
343 VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
344     : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
345