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