1 //===- Action.cpp - Abstract compilation steps ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Driver/Action.h"
10 #include "llvm/Support/ErrorHandling.h"
11 #include <cassert>
12 #include <string>
13 
14 using namespace clang;
15 using namespace driver;
16 using namespace llvm::opt;
17 
18 Action::~Action() = default;
19 
20 const char *Action::getClassName(ActionClass AC) {
21   switch (AC) {
22   case InputClass: return "input";
23   case BindArchClass: return "bind-arch";
24   case OffloadClass:
25     return "offload";
26   case PreprocessJobClass: return "preprocessor";
27   case PrecompileJobClass: return "precompiler";
28   case HeaderModulePrecompileJobClass: return "header-module-precompiler";
29   case ExtractAPIJobClass:
30     return "api-extractor";
31   case AnalyzeJobClass: return "analyzer";
32   case MigrateJobClass: return "migrator";
33   case CompileJobClass: return "compiler";
34   case BackendJobClass: return "backend";
35   case AssembleJobClass: return "assembler";
36   case IfsMergeJobClass: return "interface-stub-merger";
37   case LinkJobClass: return "linker";
38   case LipoJobClass: return "lipo";
39   case DsymutilJobClass: return "dsymutil";
40   case VerifyDebugInfoJobClass: return "verify-debug-info";
41   case VerifyPCHJobClass: return "verify-pch";
42   case OffloadBundlingJobClass:
43     return "clang-offload-bundler";
44   case OffloadUnbundlingJobClass:
45     return "clang-offload-unbundler";
46   case OffloadWrapperJobClass:
47     return "clang-offload-wrapper";
48   case OffloadPackagerJobClass:
49     return "clang-offload-packager";
50   case LinkerWrapperJobClass:
51     return "clang-linker-wrapper";
52   case StaticLibJobClass:
53     return "static-lib-linker";
54   }
55 
56   llvm_unreachable("invalid class");
57 }
58 
59 void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
60                                         const ToolChain *OToolChain) {
61   // Offload action set its own kinds on their dependences.
62   if (Kind == OffloadClass)
63     return;
64   // Unbundling actions use the host kinds.
65   if (Kind == OffloadUnbundlingJobClass)
66     return;
67 
68   assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
69          "Setting device kind to a different device??");
70   assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
71   OffloadingDeviceKind = OKind;
72   OffloadingArch = OArch;
73   OffloadingToolChain = OToolChain;
74 
75   for (auto *A : Inputs)
76     A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);
77 }
78 
79 void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
80   // Offload action set its own kinds on their dependences.
81   if (Kind == OffloadClass)
82     return;
83 
84   assert(OffloadingDeviceKind == OFK_None &&
85          "Setting a host kind in a device action.");
86   ActiveOffloadKindMask |= OKinds;
87   OffloadingArch = OArch;
88 
89   for (auto *A : Inputs)
90     A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
91 }
92 
93 void Action::propagateOffloadInfo(const Action *A) {
94   if (unsigned HK = A->getOffloadingHostActiveKinds())
95     propagateHostOffloadInfo(HK, A->getOffloadingArch());
96   else
97     propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
98                                A->getOffloadingArch(),
99                                A->getOffloadingToolChain());
100 }
101 
102 std::string Action::getOffloadingKindPrefix() const {
103   switch (OffloadingDeviceKind) {
104   case OFK_None:
105     break;
106   case OFK_Host:
107     llvm_unreachable("Host kind is not an offloading device kind.");
108     break;
109   case OFK_Cuda:
110     return "device-cuda";
111   case OFK_OpenMP:
112     return "device-openmp";
113   case OFK_HIP:
114     return "device-hip";
115 
116     // TODO: Add other programming models here.
117   }
118 
119   if (!ActiveOffloadKindMask)
120     return {};
121 
122   std::string Res("host");
123   assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
124            (ActiveOffloadKindMask & OFK_HIP)) &&
125          "Cannot offload CUDA and HIP at the same time");
126   if (ActiveOffloadKindMask & OFK_Cuda)
127     Res += "-cuda";
128   if (ActiveOffloadKindMask & OFK_HIP)
129     Res += "-hip";
130   if (ActiveOffloadKindMask & OFK_OpenMP)
131     Res += "-openmp";
132 
133   // TODO: Add other programming models here.
134 
135   return Res;
136 }
137 
138 /// Return a string that can be used as prefix in order to generate unique files
139 /// for each offloading kind.
140 std::string
141 Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
142                                     StringRef NormalizedTriple,
143                                     bool CreatePrefixForHost) {
144   // Don't generate prefix for host actions unless required.
145   if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
146     return {};
147 
148   std::string Res("-");
149   Res += GetOffloadKindName(Kind);
150   Res += "-";
151   Res += NormalizedTriple;
152   return Res;
153 }
154 
155 /// Return a string with the offload kind name. If that is not defined, we
156 /// assume 'host'.
157 StringRef Action::GetOffloadKindName(OffloadKind Kind) {
158   switch (Kind) {
159   case OFK_None:
160   case OFK_Host:
161     return "host";
162   case OFK_Cuda:
163     return "cuda";
164   case OFK_OpenMP:
165     return "openmp";
166   case OFK_HIP:
167     return "hip";
168 
169     // TODO: Add other programming models here.
170   }
171 
172   llvm_unreachable("invalid offload kind");
173 }
174 
175 void InputAction::anchor() {}
176 
177 InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
178     : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}
179 
180 void BindArchAction::anchor() {}
181 
182 BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
183     : Action(BindArchClass, Input), ArchName(ArchName) {}
184 
185 void OffloadAction::anchor() {}
186 
187 OffloadAction::OffloadAction(const HostDependence &HDep)
188     : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
189   OffloadingArch = HDep.getBoundArch();
190   ActiveOffloadKindMask = HDep.getOffloadKinds();
191   HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
192                                              HDep.getBoundArch());
193 }
194 
195 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
196     : Action(OffloadClass, DDeps.getActions(), Ty),
197       DevToolChains(DDeps.getToolChains()) {
198   auto &OKinds = DDeps.getOffloadKinds();
199   auto &BArchs = DDeps.getBoundArchs();
200   auto &OTCs = DDeps.getToolChains();
201 
202   // If all inputs agree on the same kind, use it also for this action.
203   if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
204     OffloadingDeviceKind = OKinds.front();
205 
206   // If we have a single dependency, inherit the architecture from it.
207   if (OKinds.size() == 1)
208     OffloadingArch = BArchs.front();
209 
210   // Propagate info to the dependencies.
211   for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
212     getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);
213 }
214 
215 OffloadAction::OffloadAction(const HostDependence &HDep,
216                              const DeviceDependences &DDeps)
217     : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
218       DevToolChains(DDeps.getToolChains()) {
219   // We use the kinds of the host dependence for this action.
220   OffloadingArch = HDep.getBoundArch();
221   ActiveOffloadKindMask = HDep.getOffloadKinds();
222   HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
223                                              HDep.getBoundArch());
224 
225   // Add device inputs and propagate info to the device actions. Do work only if
226   // we have dependencies.
227   for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
228     if (auto *A = DDeps.getActions()[i]) {
229       getInputs().push_back(A);
230       A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
231                                     DDeps.getBoundArchs()[i],
232                                     DDeps.getToolChains()[i]);
233     }
234 }
235 
236 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
237   if (!HostTC)
238     return;
239   assert(!getInputs().empty() && "No dependencies for offload action??");
240   auto *A = getInputs().front();
241   Work(A, HostTC, A->getOffloadingArch());
242 }
243 
244 void OffloadAction::doOnEachDeviceDependence(
245     const OffloadActionWorkTy &Work) const {
246   auto I = getInputs().begin();
247   auto E = getInputs().end();
248   if (I == E)
249     return;
250 
251   // We expect to have the same number of input dependences and device tool
252   // chains, except if we also have a host dependence. In that case we have one
253   // more dependence than we have device tool chains.
254   assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
255          "Sizes of action dependences and toolchains are not consistent!");
256 
257   // Skip host action
258   if (HostTC)
259     ++I;
260 
261   auto TI = DevToolChains.begin();
262   for (; I != E; ++I, ++TI)
263     Work(*I, *TI, (*I)->getOffloadingArch());
264 }
265 
266 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
267   doOnHostDependence(Work);
268   doOnEachDeviceDependence(Work);
269 }
270 
271 void OffloadAction::doOnEachDependence(bool IsHostDependence,
272                                        const OffloadActionWorkTy &Work) const {
273   if (IsHostDependence)
274     doOnHostDependence(Work);
275   else
276     doOnEachDeviceDependence(Work);
277 }
278 
279 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
280 
281 Action *OffloadAction::getHostDependence() const {
282   assert(hasHostDependence() && "Host dependence does not exist!");
283   assert(!getInputs().empty() && "No dependencies for offload action??");
284   return HostTC ? getInputs().front() : nullptr;
285 }
286 
287 bool OffloadAction::hasSingleDeviceDependence(
288     bool DoNotConsiderHostActions) const {
289   if (DoNotConsiderHostActions)
290     return getInputs().size() == (HostTC ? 2 : 1);
291   return !HostTC && getInputs().size() == 1;
292 }
293 
294 Action *
295 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
296   assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
297          "Single device dependence does not exist!");
298   // The previous assert ensures the number of entries in getInputs() is
299   // consistent with what we are doing here.
300   return HostTC ? getInputs()[1] : getInputs().front();
301 }
302 
303 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
304                                            const char *BoundArch,
305                                            OffloadKind OKind) {
306   DeviceActions.push_back(&A);
307   DeviceToolChains.push_back(&TC);
308   DeviceBoundArchs.push_back(BoundArch);
309   DeviceOffloadKinds.push_back(OKind);
310 }
311 
312 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
313                                               const char *BoundArch,
314                                               const DeviceDependences &DDeps)
315     : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
316   for (auto K : DDeps.getOffloadKinds())
317     HostOffloadKinds |= K;
318 }
319 
320 void JobAction::anchor() {}
321 
322 JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
323     : Action(Kind, Input, Type) {}
324 
325 JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
326     : Action(Kind, Inputs, Type) {}
327 
328 void PreprocessJobAction::anchor() {}
329 
330 PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
331     : JobAction(PreprocessJobClass, Input, OutputType) {}
332 
333 void PrecompileJobAction::anchor() {}
334 
335 PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
336     : JobAction(PrecompileJobClass, Input, OutputType) {}
337 
338 PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
339                                          types::ID OutputType)
340     : JobAction(Kind, Input, OutputType) {
341   assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
342 }
343 
344 void HeaderModulePrecompileJobAction::anchor() {}
345 
346 HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
347     Action *Input, types::ID OutputType, const char *ModuleName)
348     : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
349       ModuleName(ModuleName) {}
350 
351 void ExtractAPIJobAction::anchor() {}
352 
353 ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)
354     : JobAction(ExtractAPIJobClass, Inputs, OutputType) {}
355 
356 void AnalyzeJobAction::anchor() {}
357 
358 AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
359     : JobAction(AnalyzeJobClass, Input, OutputType) {}
360 
361 void MigrateJobAction::anchor() {}
362 
363 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
364     : JobAction(MigrateJobClass, Input, OutputType) {}
365 
366 void CompileJobAction::anchor() {}
367 
368 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
369     : JobAction(CompileJobClass, Input, OutputType) {}
370 
371 void BackendJobAction::anchor() {}
372 
373 BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
374     : JobAction(BackendJobClass, Input, OutputType) {}
375 
376 void AssembleJobAction::anchor() {}
377 
378 AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
379     : JobAction(AssembleJobClass, Input, OutputType) {}
380 
381 void IfsMergeJobAction::anchor() {}
382 
383 IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
384     : JobAction(IfsMergeJobClass, Inputs, Type) {}
385 
386 void LinkJobAction::anchor() {}
387 
388 LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
389     : JobAction(LinkJobClass, Inputs, Type) {}
390 
391 void LipoJobAction::anchor() {}
392 
393 LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
394     : JobAction(LipoJobClass, Inputs, Type) {}
395 
396 void DsymutilJobAction::anchor() {}
397 
398 DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
399     : JobAction(DsymutilJobClass, Inputs, Type) {}
400 
401 void VerifyJobAction::anchor() {}
402 
403 VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
404                                  types::ID Type)
405     : JobAction(Kind, Input, Type) {
406   assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
407          "ActionClass is not a valid VerifyJobAction");
408 }
409 
410 void VerifyDebugInfoJobAction::anchor() {}
411 
412 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
413                                                    types::ID Type)
414     : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
415 
416 void VerifyPCHJobAction::anchor() {}
417 
418 VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
419     : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
420 
421 void OffloadBundlingJobAction::anchor() {}
422 
423 OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
424     : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
425 
426 void OffloadUnbundlingJobAction::anchor() {}
427 
428 OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
429     : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
430 
431 void OffloadWrapperJobAction::anchor() {}
432 
433 OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs,
434                                                  types::ID Type)
435   : JobAction(OffloadWrapperJobClass, Inputs, Type) {}
436 
437 void OffloadPackagerJobAction::anchor() {}
438 
439 OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,
440                                                    types::ID Type)
441     : JobAction(OffloadPackagerJobClass, Inputs, Type) {}
442 
443 void LinkerWrapperJobAction::anchor() {}
444 
445 LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,
446                                                types::ID Type)
447     : JobAction(LinkerWrapperJobClass, Inputs, Type) {}
448 
449 void StaticLibJobAction::anchor() {}
450 
451 StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)
452     : JobAction(StaticLibJobClass, Inputs, Type) {}
453