1 //===- Action.cpp - Abstract compilation steps ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Driver/Action.h"
10 #include "llvm/Support/ErrorHandling.h"
14 using namespace clang
;
15 using namespace driver
;
16 using namespace llvm::opt
;
18 Action::~Action() = default;
20 const char *Action::getClassName(ActionClass AC
) {
22 case InputClass
: return "input";
23 case BindArchClass
: return "bind-arch";
26 case PreprocessJobClass
: return "preprocessor";
27 case PrecompileJobClass
: return "precompiler";
28 case ExtractAPIJobClass
:
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";
41 case OffloadBundlingJobClass
:
42 return "clang-offload-bundler";
43 case OffloadUnbundlingJobClass
:
44 return "clang-offload-unbundler";
45 case OffloadPackagerJobClass
:
46 return "clang-offload-packager";
47 case LinkerWrapperJobClass
:
48 return "clang-linker-wrapper";
49 case StaticLibJobClass
:
50 return "static-lib-linker";
51 case BinaryAnalyzeJobClass
:
52 return "binary-analyzer";
55 llvm_unreachable("invalid class");
58 void 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
)
63 // Unbundling actions use the host kinds.
64 if (Kind
== OffloadUnbundlingJobClass
)
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??");
70 OffloadingDeviceKind
= OKind
;
71 OffloadingArch
= OArch
;
72 OffloadingToolChain
= OToolChain
;
74 for (auto *A
: Inputs
)
75 A
->propagateDeviceOffloadInfo(OffloadingDeviceKind
, OArch
, OToolChain
);
78 void Action::propagateHostOffloadInfo(unsigned OKinds
, const char *OArch
) {
79 // Offload action set its own kinds on their dependences.
80 if (Kind
== OffloadClass
)
83 assert(OffloadingDeviceKind
== OFK_None
&&
84 "Setting a host kind in a device action.");
85 ActiveOffloadKindMask
|= OKinds
;
86 OffloadingArch
= OArch
;
88 for (auto *A
: Inputs
)
89 A
->propagateHostOffloadInfo(ActiveOffloadKindMask
, OArch
);
92 void Action::propagateOffloadInfo(const Action
*A
) {
93 if (unsigned HK
= A
->getOffloadingHostActiveKinds())
94 propagateHostOffloadInfo(HK
, A
->getOffloadingArch());
96 propagateDeviceOffloadInfo(A
->getOffloadingDeviceKind(),
97 A
->getOffloadingArch(),
98 A
->getOffloadingToolChain());
101 std::string
Action::getOffloadingKindPrefix() const {
102 switch (OffloadingDeviceKind
) {
106 llvm_unreachable("Host kind is not an offloading device kind.");
109 return "device-cuda";
111 return "device-openmp";
115 // TODO: Add other programming models here.
118 if (!ActiveOffloadKindMask
)
121 std::string
Res("host");
122 assert(!((ActiveOffloadKindMask
& OFK_Cuda
) &&
123 (ActiveOffloadKindMask
& OFK_HIP
)) &&
124 "Cannot offload CUDA and HIP at the same time");
125 if (ActiveOffloadKindMask
& OFK_Cuda
)
127 if (ActiveOffloadKindMask
& OFK_HIP
)
129 if (ActiveOffloadKindMask
& OFK_OpenMP
)
132 // TODO: Add other programming models here.
137 /// Return a string that can be used as prefix in order to generate unique files
138 /// for each offloading kind.
140 Action::GetOffloadingFileNamePrefix(OffloadKind Kind
,
141 StringRef NormalizedTriple
,
142 bool CreatePrefixForHost
) {
143 // Don't generate prefix for host actions unless required.
144 if (!CreatePrefixForHost
&& (Kind
== OFK_None
|| Kind
== OFK_Host
))
147 std::string
Res("-");
148 Res
+= GetOffloadKindName(Kind
);
150 Res
+= NormalizedTriple
;
154 /// Return a string with the offload kind name. If that is not defined, we
156 StringRef
Action::GetOffloadKindName(OffloadKind Kind
) {
168 // TODO: Add other programming models here.
171 llvm_unreachable("invalid offload kind");
174 void InputAction::anchor() {}
176 InputAction::InputAction(const Arg
&_Input
, types::ID _Type
, StringRef _Id
)
177 : Action(InputClass
, _Type
), Input(_Input
), Id(_Id
.str()) {}
179 void BindArchAction::anchor() {}
181 BindArchAction::BindArchAction(Action
*Input
, StringRef ArchName
)
182 : Action(BindArchClass
, Input
), ArchName(ArchName
) {}
184 void OffloadAction::anchor() {}
186 OffloadAction::OffloadAction(const HostDependence
&HDep
)
187 : Action(OffloadClass
, HDep
.getAction()), HostTC(HDep
.getToolChain()) {
188 OffloadingArch
= HDep
.getBoundArch();
189 ActiveOffloadKindMask
= HDep
.getOffloadKinds();
190 HDep
.getAction()->propagateHostOffloadInfo(HDep
.getOffloadKinds(),
191 HDep
.getBoundArch());
194 OffloadAction::OffloadAction(const DeviceDependences
&DDeps
, types::ID Ty
)
195 : Action(OffloadClass
, DDeps
.getActions(), Ty
),
196 DevToolChains(DDeps
.getToolChains()) {
197 auto &OKinds
= DDeps
.getOffloadKinds();
198 auto &BArchs
= DDeps
.getBoundArchs();
199 auto &OTCs
= DDeps
.getToolChains();
201 // If all inputs agree on the same kind, use it also for this action.
202 if (llvm::all_equal(OKinds
))
203 OffloadingDeviceKind
= OKinds
.front();
205 // If we have a single dependency, inherit the architecture from it.
206 if (OKinds
.size() == 1)
207 OffloadingArch
= BArchs
.front();
209 // Propagate info to the dependencies.
210 for (unsigned i
= 0, e
= getInputs().size(); i
!= e
; ++i
)
211 getInputs()[i
]->propagateDeviceOffloadInfo(OKinds
[i
], BArchs
[i
], OTCs
[i
]);
214 OffloadAction::OffloadAction(const HostDependence
&HDep
,
215 const DeviceDependences
&DDeps
)
216 : Action(OffloadClass
, HDep
.getAction()), HostTC(HDep
.getToolChain()),
217 DevToolChains(DDeps
.getToolChains()) {
218 // We use the kinds of the host dependence for this action.
219 OffloadingArch
= HDep
.getBoundArch();
220 ActiveOffloadKindMask
= HDep
.getOffloadKinds();
221 HDep
.getAction()->propagateHostOffloadInfo(HDep
.getOffloadKinds(),
222 HDep
.getBoundArch());
224 // Add device inputs and propagate info to the device actions. Do work only if
225 // we have dependencies.
226 for (unsigned i
= 0, e
= DDeps
.getActions().size(); i
!= e
; ++i
) {
227 if (auto *A
= DDeps
.getActions()[i
]) {
228 getInputs().push_back(A
);
229 A
->propagateDeviceOffloadInfo(DDeps
.getOffloadKinds()[i
],
230 DDeps
.getBoundArchs()[i
],
231 DDeps
.getToolChains()[i
]);
232 // If this action is used to forward single dependency, set the toolchain.
233 if (DDeps
.getActions().size() == 1)
234 OffloadingToolChain
= DDeps
.getToolChains()[i
];
239 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy
&Work
) const {
242 assert(!getInputs().empty() && "No dependencies for offload action??");
243 auto *A
= getInputs().front();
244 Work(A
, HostTC
, A
->getOffloadingArch());
247 void OffloadAction::doOnEachDeviceDependence(
248 const OffloadActionWorkTy
&Work
) const {
249 auto I
= getInputs().begin();
250 auto E
= getInputs().end();
254 // We expect to have the same number of input dependences and device tool
255 // chains, except if we also have a host dependence. In that case we have one
256 // more dependence than we have device tool chains.
257 assert(getInputs().size() == DevToolChains
.size() + (HostTC
? 1 : 0) &&
258 "Sizes of action dependences and toolchains are not consistent!");
264 auto TI
= DevToolChains
.begin();
265 for (; I
!= E
; ++I
, ++TI
)
266 Work(*I
, *TI
, (*I
)->getOffloadingArch());
269 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy
&Work
) const {
270 doOnHostDependence(Work
);
271 doOnEachDeviceDependence(Work
);
274 void OffloadAction::doOnEachDependence(bool IsHostDependence
,
275 const OffloadActionWorkTy
&Work
) const {
276 if (IsHostDependence
)
277 doOnHostDependence(Work
);
279 doOnEachDeviceDependence(Work
);
282 bool OffloadAction::hasHostDependence() const { return HostTC
!= nullptr; }
284 Action
*OffloadAction::getHostDependence() const {
285 assert(hasHostDependence() && "Host dependence does not exist!");
286 assert(!getInputs().empty() && "No dependencies for offload action??");
287 return HostTC
? getInputs().front() : nullptr;
290 bool OffloadAction::hasSingleDeviceDependence(
291 bool DoNotConsiderHostActions
) const {
292 if (DoNotConsiderHostActions
)
293 return getInputs().size() == (HostTC
? 2 : 1);
294 return !HostTC
&& getInputs().size() == 1;
298 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions
) const {
299 assert(hasSingleDeviceDependence(DoNotConsiderHostActions
) &&
300 "Single device dependence does not exist!");
301 // The previous assert ensures the number of entries in getInputs() is
302 // consistent with what we are doing here.
303 return HostTC
? getInputs()[1] : getInputs().front();
306 void OffloadAction::DeviceDependences::add(Action
&A
, const ToolChain
&TC
,
307 const char *BoundArch
,
309 DeviceActions
.push_back(&A
);
310 DeviceToolChains
.push_back(&TC
);
311 DeviceBoundArchs
.push_back(BoundArch
);
312 DeviceOffloadKinds
.push_back(OKind
);
315 void OffloadAction::DeviceDependences::add(Action
&A
, const ToolChain
&TC
,
316 const char *BoundArch
,
317 unsigned OffloadKindMask
) {
318 DeviceActions
.push_back(&A
);
319 DeviceToolChains
.push_back(&TC
);
320 DeviceBoundArchs
.push_back(BoundArch
);
322 // Add each active offloading kind from a mask.
323 for (OffloadKind OKind
: {OFK_OpenMP
, OFK_Cuda
, OFK_HIP
})
324 if (OKind
& OffloadKindMask
)
325 DeviceOffloadKinds
.push_back(OKind
);
328 OffloadAction::HostDependence::HostDependence(Action
&A
, const ToolChain
&TC
,
329 const char *BoundArch
,
330 const DeviceDependences
&DDeps
)
331 : HostAction(A
), HostToolChain(TC
), HostBoundArch(BoundArch
) {
332 for (auto K
: DDeps
.getOffloadKinds())
333 HostOffloadKinds
|= K
;
336 void JobAction::anchor() {}
338 JobAction::JobAction(ActionClass Kind
, Action
*Input
, types::ID Type
)
339 : Action(Kind
, Input
, Type
) {}
341 JobAction::JobAction(ActionClass Kind
, const ActionList
&Inputs
, types::ID Type
)
342 : Action(Kind
, Inputs
, Type
) {}
344 void PreprocessJobAction::anchor() {}
346 PreprocessJobAction::PreprocessJobAction(Action
*Input
, types::ID OutputType
)
347 : JobAction(PreprocessJobClass
, Input
, OutputType
) {}
349 void PrecompileJobAction::anchor() {}
351 PrecompileJobAction::PrecompileJobAction(Action
*Input
, types::ID OutputType
)
352 : JobAction(PrecompileJobClass
, Input
, OutputType
) {}
354 PrecompileJobAction::PrecompileJobAction(ActionClass Kind
, Action
*Input
,
355 types::ID OutputType
)
356 : JobAction(Kind
, Input
, OutputType
) {
357 assert(isa
<PrecompileJobAction
>((Action
*)this) && "invalid action kind");
360 void ExtractAPIJobAction::anchor() {}
362 ExtractAPIJobAction::ExtractAPIJobAction(Action
*Inputs
, types::ID OutputType
)
363 : JobAction(ExtractAPIJobClass
, Inputs
, OutputType
) {}
365 void AnalyzeJobAction::anchor() {}
367 AnalyzeJobAction::AnalyzeJobAction(Action
*Input
, types::ID OutputType
)
368 : JobAction(AnalyzeJobClass
, Input
, OutputType
) {}
370 void MigrateJobAction::anchor() {}
372 MigrateJobAction::MigrateJobAction(Action
*Input
, types::ID OutputType
)
373 : JobAction(MigrateJobClass
, Input
, OutputType
) {}
375 void CompileJobAction::anchor() {}
377 CompileJobAction::CompileJobAction(Action
*Input
, types::ID OutputType
)
378 : JobAction(CompileJobClass
, Input
, OutputType
) {}
380 void BackendJobAction::anchor() {}
382 BackendJobAction::BackendJobAction(Action
*Input
, types::ID OutputType
)
383 : JobAction(BackendJobClass
, Input
, OutputType
) {}
385 void AssembleJobAction::anchor() {}
387 AssembleJobAction::AssembleJobAction(Action
*Input
, types::ID OutputType
)
388 : JobAction(AssembleJobClass
, Input
, OutputType
) {}
390 void IfsMergeJobAction::anchor() {}
392 IfsMergeJobAction::IfsMergeJobAction(ActionList
&Inputs
, types::ID Type
)
393 : JobAction(IfsMergeJobClass
, Inputs
, Type
) {}
395 void LinkJobAction::anchor() {}
397 LinkJobAction::LinkJobAction(ActionList
&Inputs
, types::ID Type
)
398 : JobAction(LinkJobClass
, Inputs
, Type
) {}
400 void LipoJobAction::anchor() {}
402 LipoJobAction::LipoJobAction(ActionList
&Inputs
, types::ID Type
)
403 : JobAction(LipoJobClass
, Inputs
, Type
) {}
405 void DsymutilJobAction::anchor() {}
407 DsymutilJobAction::DsymutilJobAction(ActionList
&Inputs
, types::ID Type
)
408 : JobAction(DsymutilJobClass
, Inputs
, Type
) {}
410 void VerifyJobAction::anchor() {}
412 VerifyJobAction::VerifyJobAction(ActionClass Kind
, Action
*Input
,
414 : JobAction(Kind
, Input
, Type
) {
415 assert((Kind
== VerifyDebugInfoJobClass
|| Kind
== VerifyPCHJobClass
) &&
416 "ActionClass is not a valid VerifyJobAction");
419 void VerifyDebugInfoJobAction::anchor() {}
421 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action
*Input
,
423 : VerifyJobAction(VerifyDebugInfoJobClass
, Input
, Type
) {}
425 void VerifyPCHJobAction::anchor() {}
427 VerifyPCHJobAction::VerifyPCHJobAction(Action
*Input
, types::ID Type
)
428 : VerifyJobAction(VerifyPCHJobClass
, Input
, Type
) {}
430 void OffloadBundlingJobAction::anchor() {}
432 OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList
&Inputs
)
433 : JobAction(OffloadBundlingJobClass
, Inputs
, Inputs
.back()->getType()) {}
435 void OffloadUnbundlingJobAction::anchor() {}
437 OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action
*Input
)
438 : JobAction(OffloadUnbundlingJobClass
, Input
, Input
->getType()) {}
440 void OffloadPackagerJobAction::anchor() {}
442 OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList
&Inputs
,
444 : JobAction(OffloadPackagerJobClass
, Inputs
, Type
) {}
446 void LinkerWrapperJobAction::anchor() {}
448 LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList
&Inputs
,
450 : JobAction(LinkerWrapperJobClass
, Inputs
, Type
) {}
452 void StaticLibJobAction::anchor() {}
454 StaticLibJobAction::StaticLibJobAction(ActionList
&Inputs
, types::ID Type
)
455 : JobAction(StaticLibJobClass
, Inputs
, Type
) {}
457 void BinaryAnalyzeJobAction::anchor() {}
459 BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action
*Input
, types::ID Type
)
460 : JobAction(BinaryAnalyzeJobClass
, Input
, Type
) {}