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