Clang Project

clang_source_code/lib/Driver/Action.cpp
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
9#include "clang/Driver/Action.h"
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
20const char *Action::getClassName(ActionClass AC) {
21  switch (AC) {
22  case InputClassreturn "input";
23  case BindArchClassreturn "bind-arch";
24  case OffloadClass:
25    return "offload";
26  case PreprocessJobClassreturn "preprocessor";
27  case PrecompileJobClassreturn "precompiler";
28  case HeaderModulePrecompileJobClassreturn "header-module-precompiler";
29  case AnalyzeJobClassreturn "analyzer";
30  case MigrateJobClassreturn "migrator";
31  case CompileJobClassreturn "compiler";
32  case BackendJobClassreturn "backend";
33  case AssembleJobClassreturn "assembler";
34  case LinkJobClassreturn "linker";
35  case LipoJobClassreturn "lipo";
36  case DsymutilJobClassreturn "dsymutil";
37  case VerifyDebugInfoJobClassreturn "verify-debug-info";
38  case VerifyPCHJobClassreturn "verify-pch";
39  case OffloadBundlingJobClass:
40    return "clang-offload-bundler";
41  case OffloadUnbundlingJobClass:
42    return "clang-offload-unbundler";
43  }
44
45  llvm_unreachable("invalid class");
46}
47
48void Action::propagateDeviceOffloadInfo(OffloadKind OKindconst char *OArch) {
49  // Offload action set its own kinds on their dependences.
50  if (Kind == OffloadClass)
51    return;
52  // Unbundling actions use the host kinds.
53  if (Kind == OffloadUnbundlingJobClass)
54    return;
55
56   (0) . __assert_fail ("(OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) && \"Setting device kind to a different device??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 57, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
57 (0) . __assert_fail ("(OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) && \"Setting device kind to a different device??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 57, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "Setting device kind to a different device??");
58   (0) . __assert_fail ("!ActiveOffloadKindMask && \"Setting a device kind in a host action??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 58, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
59  OffloadingDeviceKind = OKind;
60  OffloadingArch = OArch;
61
62  for (auto *A : Inputs)
63    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
64}
65
66void Action::propagateHostOffloadInfo(unsigned OKindsconst char *OArch) {
67  // Offload action set its own kinds on their dependences.
68  if (Kind == OffloadClass)
69    return;
70
71   (0) . __assert_fail ("OffloadingDeviceKind == OFK_None && \"Setting a host kind in a device action.\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 72, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(OffloadingDeviceKind == OFK_None &&
72 (0) . __assert_fail ("OffloadingDeviceKind == OFK_None && \"Setting a host kind in a device action.\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 72, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "Setting a host kind in a device action.");
73  ActiveOffloadKindMask |= OKinds;
74  OffloadingArch = OArch;
75
76  for (auto *A : Inputs)
77    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
78}
79
80void Action::propagateOffloadInfo(const Action *A) {
81  if (unsigned HK = A->getOffloadingHostActiveKinds())
82    propagateHostOffloadInfo(HKA->getOffloadingArch());
83  else
84    propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
85                               A->getOffloadingArch());
86}
87
88std::string Action::getOffloadingKindPrefix() const {
89  switch (OffloadingDeviceKind) {
90  case OFK_None:
91    break;
92  case OFK_Host:
93    llvm_unreachable("Host kind is not an offloading device kind.");
94    break;
95  case OFK_Cuda:
96    return "device-cuda";
97  case OFK_OpenMP:
98    return "device-openmp";
99  case OFK_HIP:
100    return "device-hip";
101
102    // TODO: Add other programming models here.
103  }
104
105  if (!ActiveOffloadKindMask)
106    return {};
107
108  std::string Res("host");
109   (0) . __assert_fail ("!((ActiveOffloadKindMask & OFK_Cuda) && (ActiveOffloadKindMask & OFK_HIP)) && \"Cannot offload CUDA and HIP at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 111, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
110 (0) . __assert_fail ("!((ActiveOffloadKindMask & OFK_Cuda) && (ActiveOffloadKindMask & OFK_HIP)) && \"Cannot offload CUDA and HIP at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 111, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">           (ActiveOffloadKindMask & OFK_HIP)) &&
111 (0) . __assert_fail ("!((ActiveOffloadKindMask & OFK_Cuda) && (ActiveOffloadKindMask & OFK_HIP)) && \"Cannot offload CUDA and HIP at the same time\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 111, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "Cannot offload CUDA and HIP at the same time");
112  if (ActiveOffloadKindMask & OFK_Cuda)
113    Res += "-cuda";
114  if (ActiveOffloadKindMask & OFK_HIP)
115    Res += "-hip";
116  if (ActiveOffloadKindMask & OFK_OpenMP)
117    Res += "-openmp";
118
119  // TODO: Add other programming models here.
120
121  return Res;
122}
123
124/// Return a string that can be used as prefix in order to generate unique files
125/// for each offloading kind.
126std::string
127Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
128                                    StringRef NormalizedTriple,
129                                    bool CreatePrefixForHost) {
130  // Don't generate prefix for host actions unless required.
131  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
132    return {};
133
134  std::string Res("-");
135  Res += GetOffloadKindName(Kind);
136  Res += "-";
137  Res += NormalizedTriple;
138  return Res;
139}
140
141/// Return a string with the offload kind name. If that is not defined, we
142/// assume 'host'.
143StringRef Action::GetOffloadKindName(OffloadKind Kind) {
144  switch (Kind) {
145  case OFK_None:
146  case OFK_Host:
147    return "host";
148  case OFK_Cuda:
149    return "cuda";
150  case OFK_OpenMP:
151    return "openmp";
152  case OFK_HIP:
153    return "hip";
154
155    // TODO: Add other programming models here.
156  }
157
158  llvm_unreachable("invalid offload kind");
159}
160
161void InputAction::anchor() {}
162
163InputAction::InputAction(const Arg &_Inputtypes::ID _Type)
164    : Action(InputClass_Type), Input(_Input) {}
165
166void BindArchAction::anchor() {}
167
168BindArchAction::BindArchAction(Action *InputStringRef ArchName)
169    : Action(BindArchClassInput), ArchName(ArchName) {}
170
171void OffloadAction::anchor() {}
172
173OffloadAction::OffloadAction(const HostDependence &HDep)
174    : Action(OffloadClassHDep.getAction()), HostTC(HDep.getToolChain()) {
175  OffloadingArch = HDep.getBoundArch();
176  ActiveOffloadKindMask = HDep.getOffloadKinds();
177  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
178                                             HDep.getBoundArch());
179}
180
181OffloadAction::OffloadAction(const DeviceDependences &DDepstypes::ID Ty)
182    : Action(OffloadClassDDeps.getActions(), Ty),
183      DevToolChains(DDeps.getToolChains()) {
184  auto &OKinds = DDeps.getOffloadKinds();
185  auto &BArchs = DDeps.getBoundArchs();
186
187  // If all inputs agree on the same kind, use it also for this action.
188  if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
189    OffloadingDeviceKind = OKinds.front();
190
191  // If we have a single dependency, inherit the architecture from it.
192  if (OKinds.size() == 1)
193    OffloadingArch = BArchs.front();
194
195  // Propagate info to the dependencies.
196  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
197    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
198}
199
200OffloadAction::OffloadAction(const HostDependence &HDep,
201                             const DeviceDependences &DDeps)
202    : Action(OffloadClassHDep.getAction()), HostTC(HDep.getToolChain()),
203      DevToolChains(DDeps.getToolChains()) {
204  // We use the kinds of the host dependence for this action.
205  OffloadingArch = HDep.getBoundArch();
206  ActiveOffloadKindMask = HDep.getOffloadKinds();
207  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
208                                             HDep.getBoundArch());
209
210  // Add device inputs and propagate info to the device actions. Do work only if
211  // we have dependencies.
212  for (unsigned i = 0e = DDeps.getActions().size(); i != e; ++i)
213    if (auto *A = DDeps.getActions()[i]) {
214      getInputs().push_back(A);
215      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
216                                    DDeps.getBoundArchs()[i]);
217    }
218}
219
220void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Workconst {
221  if (!HostTC)
222    return;
223   (0) . __assert_fail ("!getInputs().empty() && \"No dependencies for offload action??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 223, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!getInputs().empty() && "No dependencies for offload action??");
224  auto *A = getInputs().front();
225  Work(A, HostTC, A->getOffloadingArch());
226}
227
228void OffloadAction::doOnEachDeviceDependence(
229    const OffloadActionWorkTy &Workconst {
230  auto I = getInputs().begin();
231  auto E = getInputs().end();
232  if (I == E)
233    return;
234
235  // We expect to have the same number of input dependences and device tool
236  // chains, except if we also have a host dependence. In that case we have one
237  // more dependence than we have device tool chains.
238   (0) . __assert_fail ("getInputs().size() == DevToolChains.size() + (HostTC ? 1 . 0) && \"Sizes of action dependences and toolchains are not consistent!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 239, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
239 (0) . __assert_fail ("getInputs().size() == DevToolChains.size() + (HostTC ? 1 . 0) && \"Sizes of action dependences and toolchains are not consistent!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 239, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "Sizes of action dependences and toolchains are not consistent!");
240
241  // Skip host action
242  if (HostTC)
243    ++I;
244
245  auto TI = DevToolChains.begin();
246  for (; I != E; ++I, ++TI)
247    Work(*I, *TI, (*I)->getOffloadingArch());
248}
249
250void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Workconst {
251  doOnHostDependence(Work);
252  doOnEachDeviceDependence(Work);
253}
254
255void OffloadAction::doOnEachDependence(bool IsHostDependence,
256                                       const OffloadActionWorkTy &Workconst {
257  if (IsHostDependence)
258    doOnHostDependence(Work);
259  else
260    doOnEachDeviceDependence(Work);
261}
262
263bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
264
265Action *OffloadAction::getHostDependence() const {
266   (0) . __assert_fail ("hasHostDependence() && \"Host dependence does not exist!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 266, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasHostDependence() && "Host dependence does not exist!");
267   (0) . __assert_fail ("!getInputs().empty() && \"No dependencies for offload action??\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 267, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!getInputs().empty() && "No dependencies for offload action??");
268  return HostTC ? getInputs().front() : nullptr;
269}
270
271bool OffloadAction::hasSingleDeviceDependence(
272    bool DoNotConsiderHostActionsconst {
273  if (DoNotConsiderHostActions)
274    return getInputs().size() == (HostTC ? 2 : 1);
275  return !HostTC && getInputs().size() == 1;
276}
277
278Action *
279OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActionsconst {
280   (0) . __assert_fail ("hasSingleDeviceDependence(DoNotConsiderHostActions) && \"Single device dependence does not exist!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 281, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
281 (0) . __assert_fail ("hasSingleDeviceDependence(DoNotConsiderHostActions) && \"Single device dependence does not exist!\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 281, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "Single device dependence does not exist!");
282  // The previous assert ensures the number of entries in getInputs() is
283  // consistent with what we are doing here.
284  return HostTC ? getInputs()[1] : getInputs().front();
285}
286
287void OffloadAction::DeviceDependences::add(Action &Aconst ToolChain &TC,
288                                           const char *BoundArch,
289                                           OffloadKind OKind) {
290  DeviceActions.push_back(&A);
291  DeviceToolChains.push_back(&TC);
292  DeviceBoundArchs.push_back(BoundArch);
293  DeviceOffloadKinds.push_back(OKind);
294}
295
296OffloadAction::HostDependence::HostDependence(Action &Aconst ToolChain &TC,
297                                              const char *BoundArch,
298                                              const DeviceDependences &DDeps)
299    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
300  for (auto K : DDeps.getOffloadKinds())
301    HostOffloadKinds |= K;
302}
303
304void JobAction::anchor() {}
305
306JobAction::JobAction(ActionClass KindAction *Inputtypes::ID Type)
307    : Action(KindInputType) {}
308
309JobAction::JobAction(ActionClass Kindconst ActionList &Inputstypes::ID Type)
310    : Action(KindInputsType) {}
311
312void PreprocessJobAction::anchor() {}
313
314PreprocessJobAction::PreprocessJobAction(Action *Inputtypes::ID OutputType)
315    : JobAction(PreprocessJobClassInputOutputType) {}
316
317void PrecompileJobAction::anchor() {}
318
319PrecompileJobAction::PrecompileJobAction(Action *Inputtypes::ID OutputType)
320    : JobAction(PrecompileJobClassInputOutputType) {}
321
322PrecompileJobAction::PrecompileJobAction(ActionClass KindAction *Input,
323                                         types::ID OutputType)
324    : JobAction(KindInputOutputType) {
325   (0) . __assert_fail ("isa((Action*)this) && \"invalid action kind\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 325, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
326}
327
328void HeaderModulePrecompileJobAction::anchor() {}
329
330HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
331    Action *Inputtypes::ID OutputTypeconst char *ModuleName)
332    : PrecompileJobAction(HeaderModulePrecompileJobClassInputOutputType),
333      ModuleName(ModuleName) {}
334
335void AnalyzeJobAction::anchor() {}
336
337AnalyzeJobAction::AnalyzeJobAction(Action *Inputtypes::ID OutputType)
338    : JobAction(AnalyzeJobClassInputOutputType) {}
339
340void MigrateJobAction::anchor() {}
341
342MigrateJobAction::MigrateJobAction(Action *Inputtypes::ID OutputType)
343    : JobAction(MigrateJobClassInputOutputType) {}
344
345void CompileJobAction::anchor() {}
346
347CompileJobAction::CompileJobAction(Action *Inputtypes::ID OutputType)
348    : JobAction(CompileJobClassInputOutputType) {}
349
350void BackendJobAction::anchor() {}
351
352BackendJobAction::BackendJobAction(Action *Inputtypes::ID OutputType)
353    : JobAction(BackendJobClassInputOutputType) {}
354
355void AssembleJobAction::anchor() {}
356
357AssembleJobAction::AssembleJobAction(Action *Inputtypes::ID OutputType)
358    : JobAction(AssembleJobClassInputOutputType) {}
359
360void LinkJobAction::anchor() {}
361
362LinkJobAction::LinkJobAction(ActionList &Inputstypes::ID Type)
363    : JobAction(LinkJobClassInputsType) {}
364
365void LipoJobAction::anchor() {}
366
367LipoJobAction::LipoJobAction(ActionList &Inputstypes::ID Type)
368    : JobAction(LipoJobClassInputsType) {}
369
370void DsymutilJobAction::anchor() {}
371
372DsymutilJobAction::DsymutilJobAction(ActionList &Inputstypes::ID Type)
373    : JobAction(DsymutilJobClassInputsType) {}
374
375void VerifyJobAction::anchor() {}
376
377VerifyJobAction::VerifyJobAction(ActionClass KindAction *Input,
378                                 types::ID Type)
379    : JobAction(KindInputType) {
380   (0) . __assert_fail ("(Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && \"ActionClass is not a valid VerifyJobAction\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 381, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
381 (0) . __assert_fail ("(Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && \"ActionClass is not a valid VerifyJobAction\"", "/home/seafit/code_projects/clang_source/clang/lib/Driver/Action.cpp", 381, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "ActionClass is not a valid VerifyJobAction");
382}
383
384void VerifyDebugInfoJobAction::anchor() {}
385
386VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
387                                                   types::ID Type)
388    : VerifyJobAction(VerifyDebugInfoJobClassInputType) {}
389
390void VerifyPCHJobAction::anchor() {}
391
392VerifyPCHJobAction::VerifyPCHJobAction(Action *Inputtypes::ID Type)
393    : VerifyJobAction(VerifyPCHJobClassInputType) {}
394
395void OffloadBundlingJobAction::anchor() {}
396
397OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
398    : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
399
400void OffloadUnbundlingJobAction::anchor() {}
401
402OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
403    : JobAction(OffloadUnbundlingJobClassInputInput->getType()) {}
404
clang::driver::Action::getClassName
clang::driver::Action::propagateDeviceOffloadInfo
clang::driver::Action::propagateHostOffloadInfo
clang::driver::Action::propagateOffloadInfo
clang::driver::Action::getOffloadingKindPrefix
clang::driver::Action::GetOffloadingFileNamePrefix
clang::driver::Action::GetOffloadKindName
clang::driver::InputAction::anchor
clang::driver::BindArchAction::anchor
clang::driver::OffloadAction::anchor
clang::driver::OffloadAction::doOnHostDependence
clang::driver::OffloadAction::doOnEachDeviceDependence
clang::driver::OffloadAction::doOnEachDependence
clang::driver::OffloadAction::doOnEachDependence
clang::driver::OffloadAction::hasHostDependence
clang::driver::OffloadAction::getHostDependence
clang::driver::OffloadAction::hasSingleDeviceDependence
clang::driver::OffloadAction::getSingleDeviceDependence
clang::driver::OffloadAction::DeviceDependences::add
clang::driver::JobAction::anchor
clang::driver::PreprocessJobAction::anchor
clang::driver::PrecompileJobAction::anchor
clang::driver::HeaderModulePrecompileJobAction::anchor
clang::driver::AnalyzeJobAction::anchor
clang::driver::MigrateJobAction::anchor
clang::driver::CompileJobAction::anchor
clang::driver::BackendJobAction::anchor
clang::driver::AssembleJobAction::anchor
clang::driver::LinkJobAction::anchor
clang::driver::LipoJobAction::anchor
clang::driver::DsymutilJobAction::anchor
clang::driver::VerifyJobAction::anchor
clang::driver::VerifyDebugInfoJobAction::anchor
clang::driver::VerifyPCHJobAction::anchor
clang::driver::OffloadBundlingJobAction::anchor
clang::driver::OffloadUnbundlingJobAction::anchor