1 //===- Action.cpp - Abstract compilation steps ----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/Driver/Action.h"
11 #include "llvm/Support/ErrorHandling.h"
15 using namespace clang;
16 using namespace driver;
17 using namespace llvm::opt;
19 Action::~Action() = default;
21 const char *Action::getClassName(ActionClass AC) {
23 case InputClass: return "input";
24 case BindArchClass: return "bind-arch";
27 case PreprocessJobClass: return "preprocessor";
28 case PrecompileJobClass: return "precompiler";
29 case HeaderModulePrecompileJobClass: return "header-module-precompiler";
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 LinkJobClass: return "linker";
36 case LipoJobClass: return "lipo";
37 case DsymutilJobClass: return "dsymutil";
38 case VerifyDebugInfoJobClass: return "verify-debug-info";
39 case VerifyPCHJobClass: return "verify-pch";
40 case OffloadBundlingJobClass:
41 return "clang-offload-bundler";
42 case OffloadUnbundlingJobClass:
43 return "clang-offload-unbundler";
46 llvm_unreachable("invalid class");
49 void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
50 // Offload action set its own kinds on their dependences.
51 if (Kind == OffloadClass)
53 // Unbundling actions use the host kinds.
54 if (Kind == OffloadUnbundlingJobClass)
57 assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
58 "Setting device kind to a different device??");
59 assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
60 OffloadingDeviceKind = OKind;
61 OffloadingArch = OArch;
63 for (auto *A : Inputs)
64 A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
67 void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
68 // Offload action set its own kinds on their dependences.
69 if (Kind == OffloadClass)
72 assert(OffloadingDeviceKind == OFK_None &&
73 "Setting a host kind in a device action.");
74 ActiveOffloadKindMask |= OKinds;
75 OffloadingArch = OArch;
77 for (auto *A : Inputs)
78 A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
81 void Action::propagateOffloadInfo(const Action *A) {
82 if (unsigned HK = A->getOffloadingHostActiveKinds())
83 propagateHostOffloadInfo(HK, A->getOffloadingArch());
85 propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
86 A->getOffloadingArch());
89 std::string Action::getOffloadingKindPrefix() const {
90 switch (OffloadingDeviceKind) {
94 llvm_unreachable("Host kind is not an offloading device kind.");
99 return "device-openmp";
103 // TODO: Add other programming models here.
106 if (!ActiveOffloadKindMask)
109 std::string Res("host");
110 assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
111 (ActiveOffloadKindMask & OFK_HIP)) &&
112 "Cannot offload CUDA and HIP at the same time");
113 if (ActiveOffloadKindMask & OFK_Cuda)
115 if (ActiveOffloadKindMask & OFK_HIP)
117 if (ActiveOffloadKindMask & OFK_OpenMP)
120 // TODO: Add other programming models here.
125 /// Return a string that can be used as prefix in order to generate unique files
126 /// for each offloading kind.
128 Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
129 StringRef NormalizedTriple,
130 bool CreatePrefixForHost) {
131 // Don't generate prefix for host actions unless required.
132 if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
135 std::string Res("-");
136 Res += GetOffloadKindName(Kind);
138 Res += NormalizedTriple;
142 /// Return a string with the offload kind name. If that is not defined, we
144 StringRef Action::GetOffloadKindName(OffloadKind Kind) {
156 // TODO: Add other programming models here.
159 llvm_unreachable("invalid offload kind");
162 void InputAction::anchor() {}
164 InputAction::InputAction(const Arg &_Input, types::ID _Type)
165 : Action(InputClass, _Type), Input(_Input) {}
167 void BindArchAction::anchor() {}
169 BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
170 : Action(BindArchClass, Input), ArchName(ArchName) {}
172 void OffloadAction::anchor() {}
174 OffloadAction::OffloadAction(const HostDependence &HDep)
175 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
176 OffloadingArch = HDep.getBoundArch();
177 ActiveOffloadKindMask = HDep.getOffloadKinds();
178 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
179 HDep.getBoundArch());
182 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
183 : Action(OffloadClass, DDeps.getActions(), Ty),
184 DevToolChains(DDeps.getToolChains()) {
185 auto &OKinds = DDeps.getOffloadKinds();
186 auto &BArchs = DDeps.getBoundArchs();
188 // If all inputs agree on the same kind, use it also for this action.
189 if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
190 OffloadingDeviceKind = OKinds.front();
192 // If we have a single dependency, inherit the architecture from it.
193 if (OKinds.size() == 1)
194 OffloadingArch = BArchs.front();
196 // Propagate info to the dependencies.
197 for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
198 getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
201 OffloadAction::OffloadAction(const HostDependence &HDep,
202 const DeviceDependences &DDeps)
203 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
204 DevToolChains(DDeps.getToolChains()) {
205 // We use the kinds of the host dependence for this action.
206 OffloadingArch = HDep.getBoundArch();
207 ActiveOffloadKindMask = HDep.getOffloadKinds();
208 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
209 HDep.getBoundArch());
211 // Add device inputs and propagate info to the device actions. Do work only if
212 // we have dependencies.
213 for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
214 if (auto *A = DDeps.getActions()[i]) {
215 getInputs().push_back(A);
216 A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
217 DDeps.getBoundArchs()[i]);
221 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
224 assert(!getInputs().empty() && "No dependencies for offload action??");
225 auto *A = getInputs().front();
226 Work(A, HostTC, A->getOffloadingArch());
229 void OffloadAction::doOnEachDeviceDependence(
230 const OffloadActionWorkTy &Work) const {
231 auto I = getInputs().begin();
232 auto E = getInputs().end();
236 // We expect to have the same number of input dependences and device tool
237 // chains, except if we also have a host dependence. In that case we have one
238 // more dependence than we have device tool chains.
239 assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
240 "Sizes of action dependences and toolchains are not consistent!");
246 auto TI = DevToolChains.begin();
247 for (; I != E; ++I, ++TI)
248 Work(*I, *TI, (*I)->getOffloadingArch());
251 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
252 doOnHostDependence(Work);
253 doOnEachDeviceDependence(Work);
256 void OffloadAction::doOnEachDependence(bool IsHostDependence,
257 const OffloadActionWorkTy &Work) const {
258 if (IsHostDependence)
259 doOnHostDependence(Work);
261 doOnEachDeviceDependence(Work);
264 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
266 Action *OffloadAction::getHostDependence() const {
267 assert(hasHostDependence() && "Host dependence does not exist!");
268 assert(!getInputs().empty() && "No dependencies for offload action??");
269 return HostTC ? getInputs().front() : nullptr;
272 bool OffloadAction::hasSingleDeviceDependence(
273 bool DoNotConsiderHostActions) const {
274 if (DoNotConsiderHostActions)
275 return getInputs().size() == (HostTC ? 2 : 1);
276 return !HostTC && getInputs().size() == 1;
280 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
281 assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
282 "Single device dependence does not exist!");
283 // The previous assert ensures the number of entries in getInputs() is
284 // consistent with what we are doing here.
285 return HostTC ? getInputs()[1] : getInputs().front();
288 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
289 const char *BoundArch,
291 DeviceActions.push_back(&A);
292 DeviceToolChains.push_back(&TC);
293 DeviceBoundArchs.push_back(BoundArch);
294 DeviceOffloadKinds.push_back(OKind);
297 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
298 const char *BoundArch,
299 const DeviceDependences &DDeps)
300 : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
301 for (auto K : DDeps.getOffloadKinds())
302 HostOffloadKinds |= K;
305 void JobAction::anchor() {}
307 JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
308 : Action(Kind, Input, Type) {}
310 JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
311 : Action(Kind, Inputs, Type) {}
313 void PreprocessJobAction::anchor() {}
315 PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
316 : JobAction(PreprocessJobClass, Input, OutputType) {}
318 void PrecompileJobAction::anchor() {}
320 PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
321 : JobAction(PrecompileJobClass, Input, OutputType) {}
323 PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
324 types::ID OutputType)
325 : JobAction(Kind, Input, OutputType) {
326 assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
329 void HeaderModulePrecompileJobAction::anchor() {}
331 HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
332 Action *Input, types::ID OutputType, const char *ModuleName)
333 : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
334 ModuleName(ModuleName) {}
336 void AnalyzeJobAction::anchor() {}
338 AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
339 : JobAction(AnalyzeJobClass, Input, OutputType) {}
341 void MigrateJobAction::anchor() {}
343 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
344 : JobAction(MigrateJobClass, Input, OutputType) {}
346 void CompileJobAction::anchor() {}
348 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
349 : JobAction(CompileJobClass, Input, OutputType) {}
351 void BackendJobAction::anchor() {}
353 BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
354 : JobAction(BackendJobClass, Input, OutputType) {}
356 void AssembleJobAction::anchor() {}
358 AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
359 : JobAction(AssembleJobClass, Input, OutputType) {}
361 void LinkJobAction::anchor() {}
363 LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
364 : JobAction(LinkJobClass, Inputs, Type) {}
366 void LipoJobAction::anchor() {}
368 LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
369 : JobAction(LipoJobClass, Inputs, Type) {}
371 void DsymutilJobAction::anchor() {}
373 DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
374 : JobAction(DsymutilJobClass, Inputs, Type) {}
376 void VerifyJobAction::anchor() {}
378 VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
380 : JobAction(Kind, Input, Type) {
381 assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
382 "ActionClass is not a valid VerifyJobAction");
385 void VerifyDebugInfoJobAction::anchor() {}
387 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
389 : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
391 void VerifyPCHJobAction::anchor() {}
393 VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
394 : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
396 void OffloadBundlingJobAction::anchor() {}
398 OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
399 : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
401 void OffloadUnbundlingJobAction::anchor() {}
403 OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
404 : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}