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 "clang/Driver/ToolChain.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/Regex.h"
17 using namespace clang::driver;
18 using namespace llvm::opt;
22 const char *Action::getClassName(ActionClass AC) {
24 case InputClass: return "input";
25 case BindArchClass: return "bind-arch";
28 case PreprocessJobClass: return "preprocessor";
29 case PrecompileJobClass: return "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";
101 // TODO: Add other programming models here.
104 if (!ActiveOffloadKindMask)
107 std::string Res("host");
108 if (ActiveOffloadKindMask & OFK_Cuda)
110 if (ActiveOffloadKindMask & OFK_OpenMP)
113 // TODO: Add other programming models here.
118 /// Return a string that can be used as prefix in order to generate unique files
119 /// for each offloading kind.
121 Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
122 llvm::StringRef NormalizedTriple,
123 bool CreatePrefixForHost) {
124 // Don't generate prefix for host actions unless required.
125 if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
128 std::string Res("-");
129 Res += GetOffloadKindName(Kind);
131 Res += NormalizedTriple;
135 /// Return a string with the offload kind name. If that is not defined, we
137 llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
147 // TODO: Add other programming models here.
150 llvm_unreachable("invalid offload kind");
153 void InputAction::anchor() {}
155 InputAction::InputAction(const Arg &_Input, types::ID _Type)
156 : Action(InputClass, _Type), Input(_Input) {
159 void BindArchAction::anchor() {}
161 BindArchAction::BindArchAction(Action *Input, llvm::StringRef ArchName)
162 : Action(BindArchClass, Input), ArchName(ArchName) {}
164 void OffloadAction::anchor() {}
166 OffloadAction::OffloadAction(const HostDependence &HDep)
167 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
168 OffloadingArch = HDep.getBoundArch();
169 ActiveOffloadKindMask = HDep.getOffloadKinds();
170 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
171 HDep.getBoundArch());
174 OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
175 : Action(OffloadClass, DDeps.getActions(), Ty),
176 DevToolChains(DDeps.getToolChains()) {
177 auto &OKinds = DDeps.getOffloadKinds();
178 auto &BArchs = DDeps.getBoundArchs();
180 // If all inputs agree on the same kind, use it also for this action.
181 if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
182 OffloadingDeviceKind = OKinds.front();
184 // If we have a single dependency, inherit the architecture from it.
185 if (OKinds.size() == 1)
186 OffloadingArch = BArchs.front();
188 // Propagate info to the dependencies.
189 for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
190 getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
193 OffloadAction::OffloadAction(const HostDependence &HDep,
194 const DeviceDependences &DDeps)
195 : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
196 DevToolChains(DDeps.getToolChains()) {
197 // We use the kinds of the host dependence for this action.
198 OffloadingArch = HDep.getBoundArch();
199 ActiveOffloadKindMask = HDep.getOffloadKinds();
200 HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
201 HDep.getBoundArch());
203 // Add device inputs and propagate info to the device actions. Do work only if
204 // we have dependencies.
205 for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
206 if (auto *A = DDeps.getActions()[i]) {
207 getInputs().push_back(A);
208 A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
209 DDeps.getBoundArchs()[i]);
213 void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
216 assert(!getInputs().empty() && "No dependencies for offload action??");
217 auto *A = getInputs().front();
218 Work(A, HostTC, A->getOffloadingArch());
221 void OffloadAction::doOnEachDeviceDependence(
222 const OffloadActionWorkTy &Work) const {
223 auto I = getInputs().begin();
224 auto E = getInputs().end();
228 // We expect to have the same number of input dependences and device tool
229 // chains, except if we also have a host dependence. In that case we have one
230 // more dependence than we have device tool chains.
231 assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
232 "Sizes of action dependences and toolchains are not consistent!");
238 auto TI = DevToolChains.begin();
239 for (; I != E; ++I, ++TI)
240 Work(*I, *TI, (*I)->getOffloadingArch());
243 void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
244 doOnHostDependence(Work);
245 doOnEachDeviceDependence(Work);
248 void OffloadAction::doOnEachDependence(bool IsHostDependence,
249 const OffloadActionWorkTy &Work) const {
250 if (IsHostDependence)
251 doOnHostDependence(Work);
253 doOnEachDeviceDependence(Work);
256 bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
258 Action *OffloadAction::getHostDependence() const {
259 assert(hasHostDependence() && "Host dependence does not exist!");
260 assert(!getInputs().empty() && "No dependencies for offload action??");
261 return HostTC ? getInputs().front() : nullptr;
264 bool OffloadAction::hasSingleDeviceDependence(
265 bool DoNotConsiderHostActions) const {
266 if (DoNotConsiderHostActions)
267 return getInputs().size() == (HostTC ? 2 : 1);
268 return !HostTC && getInputs().size() == 1;
272 OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
273 assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
274 "Single device dependence does not exist!");
275 // The previous assert ensures the number of entries in getInputs() is
276 // consistent with what we are doing here.
277 return HostTC ? getInputs()[1] : getInputs().front();
280 void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
281 const char *BoundArch,
283 DeviceActions.push_back(&A);
284 DeviceToolChains.push_back(&TC);
285 DeviceBoundArchs.push_back(BoundArch);
286 DeviceOffloadKinds.push_back(OKind);
289 OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
290 const char *BoundArch,
291 const DeviceDependences &DDeps)
292 : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
293 for (auto K : DDeps.getOffloadKinds())
294 HostOffloadKinds |= K;
297 void JobAction::anchor() {}
299 JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
300 : Action(Kind, Input, Type) {}
302 JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
303 : Action(Kind, Inputs, Type) {
306 void PreprocessJobAction::anchor() {}
308 PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
309 : JobAction(PreprocessJobClass, Input, OutputType) {}
311 void PrecompileJobAction::anchor() {}
313 PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
314 : JobAction(PrecompileJobClass, Input, OutputType) {}
316 void AnalyzeJobAction::anchor() {}
318 AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
319 : JobAction(AnalyzeJobClass, Input, OutputType) {}
321 void MigrateJobAction::anchor() {}
323 MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
324 : JobAction(MigrateJobClass, Input, OutputType) {}
326 void CompileJobAction::anchor() {}
328 CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
329 : JobAction(CompileJobClass, Input, OutputType) {}
331 void BackendJobAction::anchor() {}
333 BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
334 : JobAction(BackendJobClass, Input, OutputType) {}
336 void AssembleJobAction::anchor() {}
338 AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
339 : JobAction(AssembleJobClass, Input, OutputType) {}
341 void LinkJobAction::anchor() {}
343 LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
344 : JobAction(LinkJobClass, Inputs, Type) {
347 void LipoJobAction::anchor() {}
349 LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
350 : JobAction(LipoJobClass, Inputs, Type) {
353 void DsymutilJobAction::anchor() {}
355 DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
356 : JobAction(DsymutilJobClass, Inputs, Type) {
359 void VerifyJobAction::anchor() {}
361 VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
363 : JobAction(Kind, Input, Type) {
364 assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
365 "ActionClass is not a valid VerifyJobAction");
368 void VerifyDebugInfoJobAction::anchor() {}
370 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
372 : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
374 void VerifyPCHJobAction::anchor() {}
376 VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
377 : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
379 void OffloadBundlingJobAction::anchor() {}
381 OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
382 : JobAction(OffloadBundlingJobClass, Inputs, Inputs.front()->getType()) {}
384 void OffloadUnbundlingJobAction::anchor() {}
386 OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
387 : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}