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