Coverage Report

Created: 2020-11-24 06:42

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