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