Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Driver/Action.cpp
Line
Count
Source (jump to first uncovered line)
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
14
using namespace clang;
15
using namespace driver;
16
using namespace llvm::opt;
17
18
207k
Action::~Action() = default;
19
20
1.03k
const char *Action::getClassName(ActionClass AC) {
21
1.03k
  switch (AC) {
22
177
  case InputClass: return "input";
23
18
  case BindArchClass: return "bind-arch";
24
136
  case OffloadClass:
25
136
    return "offload";
26
155
  case PreprocessJobClass: return "preprocessor";
27
1
  case PrecompileJobClass: return "precompiler";
28
2
  case ExtractAPIJobClass:
29
2
    return "api-extractor";
30
1
  case AnalyzeJobClass: return "analyzer";
31
0
  case MigrateJobClass: return "migrator";
32
144
  case CompileJobClass: return "compiler";
33
142
  case BackendJobClass: return "backend";
34
108
  case AssembleJobClass: return "assembler";
35
0
  case IfsMergeJobClass: return "interface-stub-merger";
36
115
  case LinkJobClass: return "linker";
37
4
  case LipoJobClass: return "lipo";
38
2
  case DsymutilJobClass: return "dsymutil";
39
1
  case VerifyDebugInfoJobClass: return "verify-debug-info";
40
0
  case VerifyPCHJobClass: return "verify-pch";
41
8
  case OffloadBundlingJobClass:
42
8
    return "clang-offload-bundler";
43
13
  case OffloadUnbundlingJobClass:
44
13
    return "clang-offload-unbundler";
45
2
  case OffloadPackagerJobClass:
46
2
    return "clang-offload-packager";
47
2
  case LinkerWrapperJobClass:
48
2
    return "clang-linker-wrapper";
49
0
  case StaticLibJobClass:
50
0
    return "static-lib-linker";
51
1
  case BinaryAnalyzeJobClass:
52
1
    return "binary-analyzer";
53
1.03k
  }
54
55
0
  llvm_unreachable("invalid class");
56
0
}
57
58
void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
59
4.29k
                                        const ToolChain *OToolChain) {
60
  // Offload action set its own kinds on their dependences.
61
4.29k
  if (Kind == OffloadClass)
62
548
    return;
63
  // Unbundling actions use the host kinds.
64
3.74k
  if (Kind == OffloadUnbundlingJobClass)
65
66
    return;
66
67
3.67k
  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
68
3.67k
         "Setting device kind to a different device??");
69
3.67k
  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
70
3.67k
  OffloadingDeviceKind = OKind;
71
3.67k
  OffloadingArch = OArch;
72
3.67k
  OffloadingToolChain = OToolChain;
73
74
3.67k
  for (auto *A : Inputs)
75
3.14k
    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);
76
3.67k
}
77
78
175k
void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
79
  // Offload action set its own kinds on their dependences.
80
175k
  if (Kind == OffloadClass)
81
348
    return;
82
83
174k
  assert(OffloadingDeviceKind == OFK_None &&
84
174k
         "Setting a host kind in a device action.");
85
174k
  ActiveOffloadKindMask |= OKinds;
86
174k
  OffloadingArch = OArch;
87
88
174k
  for (auto *A : Inputs)
89
118k
    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
90
174k
}
91
92
0
void Action::propagateOffloadInfo(const Action *A) {
93
0
  if (unsigned HK = A->getOffloadingHostActiveKinds())
94
0
    propagateHostOffloadInfo(HK, A->getOffloadingArch());
95
0
  else
96
0
    propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
97
0
                               A->getOffloadingArch(),
98
0
                               A->getOffloadingToolChain());
99
0
}
100
101
1.05k
std::string Action::getOffloadingKindPrefix() const {
102
1.05k
  switch (OffloadingDeviceKind) {
103
447
  case OFK_None:
104
447
    break;
105
0
  case OFK_Host:
106
0
    llvm_unreachable("Host kind is not an offloading device kind.");
107
0
    break;
108
0
  case OFK_Cuda:
109
0
    return "device-cuda";
110
8
  case OFK_OpenMP:
111
8
    return "device-openmp";
112
600
  case OFK_HIP:
113
600
    return "device-hip";
114
115
    // TODO: Add other programming models here.
116
1.05k
  }
117
118
447
  if (!ActiveOffloadKindMask)
119
237
    return {};
120
121
210
  std::string Res("host");
122
210
  assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
123
210
           (ActiveOffloadKindMask & OFK_HIP)) &&
124
210
         "Cannot offload CUDA and HIP at the same time");
125
210
  if (ActiveOffloadKindMask & OFK_Cuda)
126
0
    Res += "-cuda";
127
210
  if (ActiveOffloadKindMask & OFK_HIP)
128
202
    Res += "-hip";
129
210
  if (ActiveOffloadKindMask & OFK_OpenMP)
130
8
    Res += "-openmp";
131
132
  // TODO: Add other programming models here.
133
134
210
  return Res;
135
210
}
136
137
/// Return a string that can be used as prefix in order to generate unique files
138
/// for each offloading kind.
139
std::string
140
Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
141
                                    StringRef NormalizedTriple,
142
25.2k
                                    bool CreatePrefixForHost) {
143
  // Don't generate prefix for host actions unless required.
144
25.2k
  if (!CreatePrefixForHost && 
(24.8k
Kind == OFK_None24.8k
||
Kind == OFK_Host1.20k
))
145
23.6k
    return {};
146
147
1.59k
  std::string Res("-");
148
1.59k
  Res += GetOffloadKindName(Kind);
149
1.59k
  Res += "-";
150
1.59k
  Res += NormalizedTriple;
151
1.59k
  return Res;
152
25.2k
}
153
154
/// Return a string with the offload kind name. If that is not defined, we
155
/// assume 'host'.
156
137k
StringRef Action::GetOffloadKindName(OffloadKind Kind) {
157
137k
  switch (Kind) {
158
133k
  case OFK_None:
159
133k
  case OFK_Host:
160
133k
    return "host";
161
508
  case OFK_Cuda:
162
508
    return "cuda";
163
95
  case OFK_OpenMP:
164
95
    return "openmp";
165
3.17k
  case OFK_HIP:
166
3.17k
    return "hip";
167
168
    // TODO: Add other programming models here.
169
137k
  }
170
171
0
  llvm_unreachable("invalid offload kind");
172
0
}
173
174
0
void InputAction::anchor() {}
175
176
InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
177
57.4k
    : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}
178
179
0
void BindArchAction::anchor() {}
180
181
BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
182
20.6k
    : Action(BindArchClass, Input), ArchName(ArchName) {}
183
184
0
void OffloadAction::anchor() {}
185
186
OffloadAction::OffloadAction(const HostDependence &HDep)
187
0
    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
188
0
  OffloadingArch = HDep.getBoundArch();
189
0
  ActiveOffloadKindMask = HDep.getOffloadKinds();
190
0
  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
191
0
                                             HDep.getBoundArch());
192
0
}
193
194
OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
195
748
    : Action(OffloadClass, DDeps.getActions(), Ty),
196
748
      DevToolChains(DDeps.getToolChains()) {
197
748
  auto &OKinds = DDeps.getOffloadKinds();
198
748
  auto &BArchs = DDeps.getBoundArchs();
199
748
  auto &OTCs = DDeps.getToolChains();
200
201
  // If all inputs agree on the same kind, use it also for this action.
202
748
  if (llvm::all_equal(OKinds))
203
748
    OffloadingDeviceKind = OKinds.front();
204
205
  // If we have a single dependency, inherit the architecture from it.
206
748
  if (OKinds.size() == 1)
207
746
    OffloadingArch = BArchs.front();
208
209
  // Propagate info to the dependencies.
210
1.49k
  for (unsigned i = 0, e = getInputs().size(); i != e; 
++i750
)
211
750
    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);
212
748
}
213
214
OffloadAction::OffloadAction(const HostDependence &HDep,
215
                             const DeviceDependences &DDeps)
216
272
    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
217
272
      DevToolChains(DDeps.getToolChains()) {
218
  // We use the kinds of the host dependence for this action.
219
272
  OffloadingArch = HDep.getBoundArch();
220
272
  ActiveOffloadKindMask = HDep.getOffloadKinds();
221
272
  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
222
272
                                             HDep.getBoundArch());
223
224
  // Add device inputs and propagate info to the device actions. Do work only if
225
  // we have dependencies.
226
545
  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; 
++i273
) {
227
273
    if (auto *A = DDeps.getActions()[i]) {
228
273
      getInputs().push_back(A);
229
273
      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
230
273
                                    DDeps.getBoundArchs()[i],
231
273
                                    DDeps.getToolChains()[i]);
232
      // If this action is used to forward single dependency, set the toolchain.
233
273
      if (DDeps.getActions().size() == 1)
234
271
        OffloadingToolChain = DDeps.getToolChains()[i];
235
273
    }
236
273
  }
237
272
}
238
239
265
void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
240
265
  if (!HostTC)
241
229
    return;
242
36
  assert(!getInputs().empty() && "No dependencies for offload action??");
243
36
  auto *A = getInputs().front();
244
36
  Work(A, HostTC, A->getOffloadingArch());
245
36
}
246
247
void OffloadAction::doOnEachDeviceDependence(
248
1.11k
    const OffloadActionWorkTy &Work) const {
249
1.11k
  auto I = getInputs().begin();
250
1.11k
  auto E = getInputs().end();
251
1.11k
  if (I == E)
252
0
    return;
253
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
1.11k
  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
258
1.11k
         "Sizes of action dependences and toolchains are not consistent!");
259
260
  // Skip host action
261
1.11k
  if (HostTC)
262
259
    ++I;
263
264
1.11k
  auto TI = DevToolChains.begin();
265
2.23k
  for (; I != E; 
++I, ++TI1.12k
)
266
1.12k
    Work(*I, *TI, (*I)->getOffloadingArch());
267
1.11k
}
268
269
252
void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
270
252
  doOnHostDependence(Work);
271
252
  doOnEachDeviceDependence(Work);
272
252
}
273
274
void OffloadAction::doOnEachDependence(bool IsHostDependence,
275
249
                                       const OffloadActionWorkTy &Work) const {
276
249
  if (IsHostDependence)
277
13
    doOnHostDependence(Work);
278
236
  else
279
236
    doOnEachDeviceDependence(Work);
280
249
}
281
282
873
bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
283
284
447
Action *OffloadAction::getHostDependence() const {
285
447
  assert(hasHostDependence() && "Host dependence does not exist!");
286
447
  assert(!getInputs().empty() && "No dependencies for offload action??");
287
447
  return HostTC ? getInputs().front() : 
nullptr0
;
288
447
}
289
290
bool OffloadAction::hasSingleDeviceDependence(
291
1.07k
    bool DoNotConsiderHostActions) const {
292
1.07k
  if (DoNotConsiderHostActions)
293
424
    return getInputs().size() == (HostTC ? 
250
:
1374
);
294
654
  return !HostTC && 
getInputs().size() == 1629
;
295
1.07k
}
296
297
Action *
298
213
OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
299
213
  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
300
213
         "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
213
  return HostTC ? 
getInputs()[1]26
:
getInputs().front()187
;
304
213
}
305
306
void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
307
                                           const char *BoundArch,
308
1.03k
                                           OffloadKind OKind) {
309
1.03k
  DeviceActions.push_back(&A);
310
1.03k
  DeviceToolChains.push_back(&TC);
311
1.03k
  DeviceBoundArchs.push_back(BoundArch);
312
1.03k
  DeviceOffloadKinds.push_back(OKind);
313
1.03k
}
314
315
void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
316
                                           const char *BoundArch,
317
15
                                           unsigned OffloadKindMask) {
318
15
  DeviceActions.push_back(&A);
319
15
  DeviceToolChains.push_back(&TC);
320
15
  DeviceBoundArchs.push_back(BoundArch);
321
322
  // Add each active offloading kind from a mask.
323
15
  for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP})
324
45
    if (OKind & OffloadKindMask)
325
15
      DeviceOffloadKinds.push_back(OKind);
326
15
}
327
328
OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
329
                                              const char *BoundArch,
330
                                              const DeviceDependences &DDeps)
331
258
    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
332
258
  for (auto K : DDeps.getOffloadKinds())
333
259
    HostOffloadKinds |= K;
334
258
}
335
336
0
void JobAction::anchor() {}
337
338
JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
339
120k
    : Action(Kind, Input, Type) {}
340
341
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
342
8.17k
    : Action(Kind, Inputs, Type) {}
343
344
0
void PreprocessJobAction::anchor() {}
345
346
PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
347
47.9k
    : JobAction(PreprocessJobClass, Input, OutputType) {}
348
349
0
void PrecompileJobAction::anchor() {}
350
351
PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
352
123
    : JobAction(PrecompileJobClass, Input, OutputType) {}
353
354
PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
355
                                         types::ID OutputType)
356
0
    : JobAction(Kind, Input, OutputType) {
357
0
  assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
358
0
}
359
360
0
void ExtractAPIJobAction::anchor() {}
361
362
ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)
363
22
    : JobAction(ExtractAPIJobClass, Inputs, OutputType) {}
364
365
0
void AnalyzeJobAction::anchor() {}
366
367
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
368
57
    : JobAction(AnalyzeJobClass, Input, OutputType) {}
369
370
0
void MigrateJobAction::anchor() {}
371
372
MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
373
0
    : JobAction(MigrateJobClass, Input, OutputType) {}
374
375
0
void CompileJobAction::anchor() {}
376
377
CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
378
45.8k
    : JobAction(CompileJobClass, Input, OutputType) {}
379
380
0
void BackendJobAction::anchor() {}
381
382
BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
383
13.9k
    : JobAction(BackendJobClass, Input, OutputType) {}
384
385
0
void AssembleJobAction::anchor() {}
386
387
AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
388
12.2k
    : JobAction(AssembleJobClass, Input, OutputType) {}
389
390
0
void IfsMergeJobAction::anchor() {}
391
392
IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
393
23
    : JobAction(IfsMergeJobClass, Inputs, Type) {}
394
395
0
void LinkJobAction::anchor() {}
396
397
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
398
7.97k
    : JobAction(LinkJobClass, Inputs, Type) {}
399
400
0
void LipoJobAction::anchor() {}
401
402
LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
403
29
    : JobAction(LipoJobClass, Inputs, Type) {}
404
405
0
void DsymutilJobAction::anchor() {}
406
407
DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
408
71
    : JobAction(DsymutilJobClass, Inputs, Type) {}
409
410
0
void VerifyJobAction::anchor() {}
411
412
VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
413
                                 types::ID Type)
414
5
    : JobAction(Kind, Input, Type) {
415
5
  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
416
5
         "ActionClass is not a valid VerifyJobAction");
417
5
}
418
419
0
void VerifyDebugInfoJobAction::anchor() {}
420
421
VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
422
                                                   types::ID Type)
423
3
    : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
424
425
0
void VerifyPCHJobAction::anchor() {}
426
427
VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
428
2
    : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
429
430
0
void OffloadBundlingJobAction::anchor() {}
431
432
OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
433
43
    : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
434
435
0
void OffloadUnbundlingJobAction::anchor() {}
436
437
OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
438
54
    : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
439
440
0
void OffloadPackagerJobAction::anchor() {}
441
442
OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,
443
                                                   types::ID Type)
444
15
    : JobAction(OffloadPackagerJobClass, Inputs, Type) {}
445
446
0
void LinkerWrapperJobAction::anchor() {}
447
448
LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,
449
                                               types::ID Type)
450
13
    : JobAction(LinkerWrapperJobClass, Inputs, Type) {}
451
452
0
void StaticLibJobAction::anchor() {}
453
454
StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)
455
12
    : JobAction(StaticLibJobClass, Inputs, Type) {}
456
457
0
void BinaryAnalyzeJobAction::anchor() {}
458
459
BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action *Input, types::ID Type)
460
3
    : JobAction(BinaryAnalyzeJobClass, Input, Type) {}