Coverage Report

Created: 2020-09-15 12:33

/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
179k
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
0
50
0
  llvm_unreachable("invalid class");
51
0
}
52
53
4.58k
void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
54
  // Offload action set its own kinds on their dependences.
55
4.58k
  if (Kind == OffloadClass)
56
637
    return;
57
  // Unbundling actions use the host kinds.
58
3.94k
  if (Kind == OffloadUnbundlingJobClass)
59
54
    return;
60
3.89k
61
3.89k
  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
62
3.89k
         "Setting device kind to a different device??");
63
3.89k
  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
64
3.89k
  OffloadingDeviceKind = OKind;
65
3.89k
  OffloadingArch = OArch;
66
3.89k
67
3.89k
  for (auto *A : Inputs)
68
3.42k
    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
69
3.89k
}
70
71
155k
void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
72
  // Offload action set its own kinds on their dependences.
73
155k
  if (Kind == OffloadClass)
74
397
    return;
75
154k
76
154k
  assert(OffloadingDeviceKind == OFK_None &&
77
154k
         "Setting a host kind in a device action.");
78
154k
  ActiveOffloadKindMask |= OKinds;
79
154k
  OffloadingArch = OArch;
80
154k
81
154k
  for (auto *A : Inputs)
82
109k
    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
83
154k
}
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
379
107
    // TODO: Add other programming models here.
108
379
  }
109
379
110
379
  if (!ActiveOffloadKindMask)
111
137
    return {};
112
242
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
242
124
  // TODO: Add other programming models here.
125
242
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
24.5k
                                    bool CreatePrefixForHost) {
135
  // Don't generate prefix for host actions unless required.
136
24.5k
  if (!CreatePrefixForHost && 
(23.9k
Kind == OFK_None23.9k
||
Kind == OFK_Host1.28k
))
137
22.6k
    return {};
138
1.93k
139
1.93k
  std::string Res("-");
140
1.93k
  Res += GetOffloadKindName(Kind);
141
1.93k
  Res += "-";
142
1.93k
  Res += NormalizedTriple;
143
1.93k
  return Res;
144
1.93k
}
145
146
/// Return a string with the offload kind name. If that is not defined, we
147
/// assume 'host'.
148
122k
StringRef Action::GetOffloadKindName(OffloadKind Kind) {
149
122k
  switch (Kind) {
150
118k
  case OFK_None:
151
118k
  case OFK_Host:
152
118k
    return "host";
153
2.19k
  case OFK_Cuda:
154
2.19k
    return "cuda";
155
631
  case OFK_OpenMP:
156
631
    return "openmp";
157
1.27k
  case OFK_HIP:
158
1.27k
    return "hip";
159
0
160
    // TODO: Add other programming models here.
161
0
  }
162
0
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
47.3k
    : Action(InputClass, _Type), Input(_Input) {}
170
171
0
void BindArchAction::anchor() {}
172
173
BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
174
20.7k
    : 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
808
      DevToolChains(DDeps.getToolChains()) {
189
808
  auto &OKinds = DDeps.getOffloadKinds();
190
808
  auto &BArchs = DDeps.getBoundArchs();
191
808
192
  // If all inputs agree on the same kind, use it also for this action.
193
808
  if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
194
808
    OffloadingDeviceKind = OKinds.front();
195
808
196
  // If we have a single dependency, inherit the architecture from it.
197
808
  if (OKinds.size() == 1)
198
808
    OffloadingArch = BArchs.front();
199
808
200
  // Propagate info to the dependencies.
201
1.61k
  for (unsigned i = 0, e = getInputs().size(); i != e; 
++i808
)
202
808
    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
203
808
}
204
205
OffloadAction::OffloadAction(const HostDependence &HDep,
206
                             const DeviceDependences &DDeps)
207
    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
208
349
      DevToolChains(DDeps.getToolChains()) {
209
  // We use the kinds of the host dependence for this action.
210
349
  OffloadingArch = HDep.getBoundArch();
211
349
  ActiveOffloadKindMask = HDep.getOffloadKinds();
212
349
  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
213
349
                                             HDep.getBoundArch());
214
349
215
  // Add device inputs and propagate info to the device actions. Do work only if
216
  // we have dependencies.
217
698
  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; 
++i349
)
218
349
    if (auto *A = DDeps.getActions()[i]) {
219
349
      getInputs().push_back(A);
220
349
      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
221
349
                                    DDeps.getBoundArchs()[i]);
222
349
    }
223
349
}
224
225
211
void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
226
211
  if (!HostTC)
227
108
    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.12k
    const OffloadActionWorkTy &Work) const {
235
1.12k
  auto I = getInputs().begin();
236
1.12k
  auto E = getInputs().end();
237
1.12k
  if (I == E)
238
0
    return;
239
1.12k
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.12k
  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
244
1.12k
         "Sizes of action dependences and toolchains are not consistent!");
245
1.12k
246
  // Skip host action
247
1.12k
  if (HostTC)
248
273
    ++I;
249
1.12k
250
1.12k
  auto TI = DevToolChains.begin();
251
2.24k
  for (; I != E; 
++I, ++TI1.12k
)
252
1.12k
    Work(*I, *TI, (*I)->getOffloadingArch());
253
1.12k
}
254
255
135
void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
256
135
  doOnHostDependence(Work);
257
135
  doOnEachDeviceDependence(Work);
258
135
}
259
260
void OffloadAction::doOnEachDependence(bool IsHostDependence,
261
322
                                       const OffloadActionWorkTy &Work) const {
262
322
  if (IsHostDependence)
263
76
    doOnHostDependence(Work);
264
246
  else
265
246
    doOnEachDeviceDependence(Work);
266
322
}
267
268
838
bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
269
270
362
Action *OffloadAction::getHostDependence() const {
271
362
  assert(hasHostDependence() && "Host dependence does not exist!");
272
362
  assert(!getInputs().empty() && "No dependencies for offload action??");
273
362
  return HostTC ? getInputs().front() : 
nullptr0
;
274
362
}
275
276
bool OffloadAction::hasSingleDeviceDependence(
277
1.28k
    bool DoNotConsiderHostActions) const {
278
1.28k
  if (DoNotConsiderHostActions)
279
519
    return getInputs().size() == (HostTC ? 
2391
:
1128
);
280
768
  return !HostTC && 
getInputs().size() == 1742
;
281
768
}
282
283
Action *
284
268
OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
285
268
  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
286
268
         "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()64
;
290
268
}
291
292
void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
293
                                           const char *BoundArch,
294
1.15k
                                           OffloadKind OKind) {
295
1.15k
  DeviceActions.push_back(&A);
296
1.15k
  DeviceToolChains.push_back(&TC);
297
1.15k
  DeviceBoundArchs.push_back(BoundArch);
298
1.15k
  DeviceOffloadKinds.push_back(OKind);
299
1.15k
}
300
301
OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
302
                                              const char *BoundArch,
303
                                              const DeviceDependences &DDeps)
304
258
    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
305
258
  for (auto K : DDeps.getOffloadKinds())
306
258
    HostOffloadKinds |= K;
307
258
}
308
309
0
void JobAction::anchor() {}
310
311
JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
312
103k
    : Action(Kind, Input, Type) {}
313
314
JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
315
7.23k
    : Action(Kind, Inputs, Type) {}
316
317
0
void PreprocessJobAction::anchor() {}
318
319
PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
320
42.5k
    : JobAction(PreprocessJobClass, Input, OutputType) {}
321
322
0
void PrecompileJobAction::anchor() {}
323
324
PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
325
72
    : 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
38.4k
    : JobAction(CompileJobClass, Input, OutputType) {}
354
355
0
void BackendJobAction::anchor() {}
356
357
BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
358
11.7k
    : JobAction(BackendJobClass, Input, OutputType) {}
359
360
0
void AssembleJobAction::anchor() {}
361
362
AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
363
10.6k
    : JobAction(AssembleJobClass, Input, OutputType) {}
364
365
0
void IfsMergeJobAction::anchor() {}
366
367
IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
368
21
    : JobAction(IfsMergeJobClass, Inputs, Type) {}
369
370
0
void LinkJobAction::anchor() {}
371
372
LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
373
7.01k
    : 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
87
    : 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
20
    : 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) {}