Autodiff Coverage for full test suite

Coverage Report

Created: 2023-11-30 18:54

/Volumes/compiler/apple/swift/lib/SIL/IR/SILSymbolVisitor.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- SILSymbolVisitor.cpp ---------------------------------------------===//
2
//
3
// This source file is part of the Swift.org open source project
4
//
5
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6
// Licensed under Apache License v2.0 with Runtime Library Exception
7
//
8
// See https://swift.org/LICENSE.txt for license information
9
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
//
11
//===----------------------------------------------------------------------===//
12
//
13
//  This file implements liker symbol enumeration for SILSymbolVisitor.
14
//
15
//===----------------------------------------------------------------------===//
16
17
#include "swift/SIL/SILSymbolVisitor.h"
18
19
#include "swift/AST/ASTContext.h"
20
#include "swift/AST/ASTMangler.h"
21
#include "swift/AST/Decl.h"
22
#include "swift/AST/Expr.h"
23
#include "swift/AST/FileUnit.h"
24
#include "swift/AST/ParameterList.h"
25
#include "swift/AST/PropertyWrappers.h"
26
#include "swift/AST/SynthesizedFileUnit.h"
27
#include "swift/Basic/Defer.h"
28
#include "swift/ClangImporter/ClangModule.h"
29
#include "swift/SIL/FormalLinkage.h"
30
#include "swift/SIL/SILLinkage.h"
31
#include "swift/SIL/SILModule.h"
32
#include "swift/SIL/SILVTableVisitor.h"
33
#include "swift/SIL/SILWitnessTable.h"
34
#include "swift/SIL/SILWitnessVisitor.h"
35
36
using namespace swift;
37
38
133k
static bool requiresLinkerDirective(Decl *D) {
39
133k
  for (auto *attr : D->getAttrs()) {
40
69.4k
    if (auto *ODA = dyn_cast<OriginallyDefinedInAttr>(attr)) {
41
81
      auto Active = ODA->isActivePlatform(D->getASTContext());
42
81
      if (Active.has_value())
43
57
        return true;
44
81
    }
45
69.4k
  }
46
133k
  return false;
47
133k
}
48
49
30.6k
static bool isGlobalOrStaticVar(VarDecl *VD) {
50
30.6k
  return VD->isStatic() || VD->getDeclContext()->isModuleScopeContext();
51
30.6k
}
52
53
using DynamicKind = SILSymbolVisitor::DynamicKind;
54
55
119k
static llvm::Optional<DynamicKind> getDynamicKind(ValueDecl *VD) {
56
119k
  if (VD->shouldUseNativeMethodReplacement())
57
1.67k
    return DynamicKind::Replaceable;
58
59
118k
  if (VD->getDynamicallyReplacedDecl())
60
1.07k
    return DynamicKind::Replacement;
61
62
116k
  return llvm::None;
63
118k
}
64
65
class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
66
  SILSymbolVisitor &Visitor;
67
  const SILSymbolVisitorContext &Ctx;
68
  llvm::SmallVector<Decl *, 4> DeclStack;
69
70
  /// A set of original function and derivative configuration pairs for which
71
  /// derivative symbols have been emitted.
72
  ///
73
  /// Used to deduplicate derivative symbol emission for `@differentiable` and
74
  /// `@derivative` attributes.
75
  llvm::DenseSet<std::pair<AbstractFunctionDecl *, AutoDiffConfig>>
76
      AddedDerivatives;
77
78
24.6k
  void addMainIfNecessary(FileUnit *file) {
79
    // Make sure to only add the main symbol for the module that we're emitting
80
    // TBD for, and not for any statically linked libraries.
81
24.6k
    if (!file->hasEntryPoint() || file->getParentModule() != Ctx.getModule())
82
8.70k
      return;
83
84
15.9k
    auto entryPointSymbol =
85
15.9k
        file->getParentModule()->getASTContext().getEntryPointFunctionName();
86
87
15.9k
    if (auto *decl = file->getMainDecl()) {
88
1.23k
      addFunction(SILDeclRef::getMainDeclEntryPoint(decl),
89
1.23k
                  /*ignoreLinkage=*/true);
90
1.23k
      return;
91
1.23k
    }
92
93
14.7k
    auto declRef = SILDeclRef::getMainFileEntryPoint(file);
94
14.7k
    Visitor.addFunction(entryPointSymbol, declRef);
95
14.7k
  }
96
97
  /// Emits the given `SILDeclRef` to the downstream visitor as long as the
98
  /// entity has the required linkage.
99
  ///
100
  /// FIXME: The need for an ignoreLinkage flag here possibly indicates that
101
  ///        there is something broken about the linkage computation below.
102
139k
  void addFunction(SILDeclRef declRef, bool ignoreLinkage = false) {
103
139k
    if (!ignoreLinkage) {
104
137k
      auto linkage = effectiveLinkageForClassMember(
105
137k
          declRef.getLinkage(ForDefinition), declRef.getSubclassScope());
106
137k
      if (Ctx.getOpts().PublicSymbolsOnly && linkage != SILLinkage::Public)
107
54.5k
        return;
108
137k
    }
109
110
85.0k
    Visitor.addFunction(declRef);
111
85.0k
  }
112
113
2.39k
  void addAsyncFunctionPointer(SILDeclRef declRef) {
114
2.39k
    auto silLinkage = effectiveLinkageForClassMember(
115
2.39k
        declRef.getLinkage(ForDefinition), declRef.getSubclassScope());
116
2.39k
    if (Ctx.getOpts().PublicSymbolsOnly && silLinkage != SILLinkage::Public)
117
717
      return;
118
119
1.67k
    Visitor.addAsyncFunctionPointer(declRef);
120
1.67k
  }
121
122
  void addAutoDiffLinearMapFunction(AbstractFunctionDecl *original,
123
                                    const AutoDiffConfig &config,
124
784
                                    AutoDiffLinearMapKind kind) {
125
784
    auto &ctx = original->getASTContext();
126
784
    auto declRef =
127
784
        SILDeclRef(original).asForeign(requiresForeignEntryPoint(original));
128
129
    // Linear maps are public only when the original function is serialized. So
130
    // if we're only including public symbols and it's not serialized, bail.
131
784
    if (Ctx.getOpts().PublicSymbolsOnly && !declRef.isSerialized())
132
712
      return;
133
134
    // Differential functions are emitted only when forward-mode is enabled.
135
72
    if (kind == AutoDiffLinearMapKind::Differential &&
136
72
        !ctx.LangOpts.hasFeature(Feature::ForwardModeDifferentiation))
137
36
      return;
138
139
36
    auto *loweredParamIndices = autodiff::getLoweredParameterIndices(
140
36
        config.parameterIndices,
141
36
        original->getInterfaceType()->castTo<AnyFunctionType>());
142
36
    Mangle::ASTMangler mangler;
143
36
    AutoDiffConfig silConfig{
144
36
        loweredParamIndices, config.resultIndices,
145
36
        autodiff::getDifferentiabilityWitnessGenericSignature(
146
36
            original->getGenericSignature(),
147
36
            config.derivativeGenericSignature)};
148
36
    std::string linearMapName =
149
36
        mangler.mangleAutoDiffLinearMap(original, kind, silConfig);
150
151
    // TODO: Can we encode a linear map function in a SILDeclRef instead of
152
    //       doing a bespoke mangling here?
153
36
    Visitor.addFunction(linearMapName, declRef);
154
36
  }
155
156
  void
157
  addAutoDiffDerivativeFunction(AbstractFunctionDecl *original,
158
                                IndexSubset *parameterIndices,
159
                                GenericSignature derivativeGenericSignature,
160
784
                                AutoDiffDerivativeFunctionKind kind) {
161
784
    auto *assocFnId = AutoDiffDerivativeFunctionIdentifier::get(
162
784
        kind, parameterIndices,
163
784
        autodiff::getDifferentiabilityWitnessGenericSignature(
164
784
            original->getGenericSignature(), derivativeGenericSignature),
165
784
        original->getASTContext());
166
784
    auto declRef =
167
784
        SILDeclRef(original).asForeign(requiresForeignEntryPoint(original));
168
784
    addFunction(declRef.asAutoDiffDerivativeFunction(assocFnId));
169
784
  }
170
171
  void addDifferentiabilityWitness(
172
      AbstractFunctionDecl *original, DifferentiabilityKind kind,
173
      IndexSubset *astParameterIndices, IndexSubset *resultIndices,
174
392
      GenericSignature derivativeGenericSignature) {
175
392
    bool foreign = requiresForeignEntryPoint(original);
176
392
    auto declRef = SILDeclRef(original).asForeign(foreign);
177
178
    // Skip symbol emission for original functions that do not have public
179
    // linkage. Exclude original functions that require a foreign entry point
180
    // with `public_external` linkage.
181
392
    auto originalLinkage = declRef.getLinkage(ForDefinition);
182
392
    if (foreign)
183
0
      originalLinkage = stripExternalFromLinkage(originalLinkage);
184
392
    if (Ctx.getOpts().PublicSymbolsOnly &&
185
392
        originalLinkage != SILLinkage::Public)
186
104
      return;
187
188
288
    auto *silParamIndices = autodiff::getLoweredParameterIndices(
189
288
        astParameterIndices,
190
288
        original->getInterfaceType()->castTo<AnyFunctionType>());
191
192
288
    auto originalMangledName = declRef.mangle();
193
288
    AutoDiffConfig config{
194
288
        silParamIndices, resultIndices,
195
288
        autodiff::getDifferentiabilityWitnessGenericSignature(
196
288
            original->getGenericSignature(), derivativeGenericSignature)};
197
198
288
    Mangle::ASTMangler mangler;
199
288
    auto mangledName = mangler.mangleSILDifferentiabilityWitness(
200
288
        originalMangledName, kind, config);
201
202
    // TODO: Can we encode a differentiability witness function in a SILDeclRef
203
    //       instead of doing a bespoke mangling here?
204
288
    Visitor.addFunction(mangledName, declRef);
205
288
  }
206
207
  void addDerivativeConfiguration(DifferentiabilityKind diffKind,
208
                                  AbstractFunctionDecl *original,
209
472
                                  const AutoDiffConfig &config) {
210
472
    auto inserted = AddedDerivatives.insert({original, config});
211
472
    if (!inserted.second)
212
80
      return;
213
214
392
    addAutoDiffLinearMapFunction(original, config,
215
392
                                 AutoDiffLinearMapKind::Differential);
216
392
    addAutoDiffLinearMapFunction(original, config,
217
392
                                 AutoDiffLinearMapKind::Pullback);
218
392
    addAutoDiffDerivativeFunction(original, config.parameterIndices,
219
392
                                  config.derivativeGenericSignature,
220
392
                                  AutoDiffDerivativeFunctionKind::JVP);
221
392
    addAutoDiffDerivativeFunction(original, config.parameterIndices,
222
392
                                  config.derivativeGenericSignature,
223
392
                                  AutoDiffDerivativeFunctionKind::VJP);
224
392
    addDifferentiabilityWitness(original, diffKind, config.parameterIndices,
225
392
                                config.resultIndices,
226
392
                                config.derivativeGenericSignature);
227
392
  }
228
229
125k
  void addOpaqueResultIfNecessary(ValueDecl *VD) {
230
125k
    if (auto opaqueResult = VD->getOpaqueResultTypeDecl()) {
231
522
      Visitor.addOpaqueTypeDescriptor(opaqueResult);
232
522
      assert(opaqueResult->getNamingDecl() == VD);
233
522
      if (auto dynKind = getDynamicKind(VD)) {
234
156
        Visitor.addOpaqueTypeDescriptorAccessor(opaqueResult, *dynKind);
235
156
      }
236
522
    }
237
125k
  }
238
239
27.3k
  void addConformances(const IterableDeclContext *IDC) {
240
27.3k
    for (auto conformance :
241
36.5k
         IDC->getLocalConformances(ConformanceLookupKind::NonInherited)) {
242
36.5k
      auto protocol = conformance->getProtocol();
243
36.5k
      if (canSkipNominal(protocol))
244
1.63k
        continue;
245
246
34.8k
      auto needsWTable =
247
34.8k
          Lowering::TypeConverter::protocolRequiresWitnessTable(protocol);
248
34.8k
      if (!needsWTable)
249
1.52k
        continue;
250
251
      // Only root conformances get symbols; the others get any public symbols
252
      // from their parent conformances.
253
33.3k
      auto rootConformance = dyn_cast<RootProtocolConformance>(conformance);
254
33.3k
      if (!rootConformance) {
255
0
        continue;
256
0
      }
257
258
      // We cannot emit the witness table symbol if the protocol is imported
259
      // from another module and it's resilient, because initialization of that
260
      // protocol is necessary in this case
261
33.3k
      if (!rootConformance->getProtocol()->isResilient(
262
33.3k
              IDC->getAsGenericContext()->getParentModule(),
263
33.3k
              ResilienceExpansion::Maximal))
264
2.76k
        Visitor.addProtocolWitnessTable(rootConformance);
265
33.3k
      Visitor.addProtocolConformanceDescriptor(rootConformance);
266
267
      // FIXME: the logic around visibility in extensions is confusing, and
268
      // sometimes witness thunks need to be manually made public.
269
270
33.3k
      auto conformanceIsFixed =
271
33.3k
          SILWitnessTable::conformanceIsSerialized(rootConformance);
272
33.3k
      auto addSymbolIfNecessary = [&](ValueDecl *requirementDecl,
273
38.1k
                                      ValueDecl *witnessDecl) {
274
38.1k
        auto witnessRef = SILDeclRef(witnessDecl);
275
38.1k
        if (Ctx.getOpts().PublicSymbolsOnly) {
276
38.1k
          if (!conformanceIsFixed)
277
2.21k
            return;
278
279
35.9k
          if (!isa<SelfProtocolConformance>(rootConformance) &&
280
35.9k
              !fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef)) {
281
35.9k
            return;
282
35.9k
          }
283
35.9k
        }
284
285
24
        Visitor.addProtocolWitnessThunk(rootConformance, requirementDecl);
286
24
      };
287
288
33.3k
      rootConformance->forEachValueWitness([&](ValueDecl *valueReq,
289
35.7k
                                               Witness witness) {
290
35.7k
        auto witnessDecl = witness.getDecl();
291
35.7k
        if (!witnessDecl)
292
3
          return;
293
294
35.7k
        if (isa<AbstractFunctionDecl>(valueReq)) {
295
19.8k
          addSymbolIfNecessary(valueReq, witnessDecl);
296
19.8k
        } else if (auto *storage = dyn_cast<AbstractStorageDecl>(valueReq)) {
297
15.9k
          if (auto witnessStorage =
298
15.9k
                  dyn_cast<AbstractStorageDecl>(witnessDecl)) {
299
18.2k
            storage->visitOpaqueAccessors([&](AccessorDecl *reqtAccessor) {
300
18.2k
              auto witnessAccessor = witnessStorage->getSynthesizedAccessor(
301
18.2k
                  reqtAccessor->getAccessorKind());
302
18.2k
              addSymbolIfNecessary(reqtAccessor, witnessAccessor);
303
18.2k
            });
304
15.9k
          } else if (isa<EnumElementDecl>(witnessDecl)) {
305
9
            auto getter = storage->getSynthesizedAccessor(AccessorKind::Get);
306
9
            addSymbolIfNecessary(getter, witnessDecl);
307
9
          }
308
15.9k
        }
309
35.7k
      }, /*useResolver=*/true);
310
33.3k
    }
311
27.3k
  }
312
313
11.5k
  bool addClassMetadata(ClassDecl *CD) {
314
11.5k
    if (canSkipNominal(CD))
315
6.74k
      return false;
316
317
4.78k
    auto &ctxt = CD->getASTContext();
318
4.78k
    auto isGeneric = CD->isGenericContext();
319
4.78k
    auto objCCompatible = ctxt.LangOpts.EnableObjCInterop && !isGeneric;
320
4.78k
    auto isObjC = objCCompatible && CD->isObjC();
321
322
    // Metaclasses and ObjC classes (duh) are an ObjC thing, and so are not
323
    // needed in build artifacts/for classes which can't touch ObjC.
324
4.78k
    if (objCCompatible) {
325
4.12k
      if (isObjC || CD->getMetaclassKind() == ClassDecl::MetaclassKind::ObjC)
326
666
        Visitor.addObjCInterface(CD);
327
3.45k
      else
328
3.45k
        Visitor.addSwiftMetaclassStub(CD);
329
4.12k
    }
330
331
    // Some members of classes get extra handling, beyond members of
332
    // struct/enums, so let's walk over them manually.
333
4.78k
    if (Ctx.getOpts().VisitMembers)
334
4.78k
      for (auto *var : CD->getStoredProperties())
335
4.26k
        Visitor.addFieldOffset(var);
336
337
4.78k
    visitNominalTypeDecl(CD);
338
339
4.78k
    bool resilientAncestry = CD->checkAncestry(AncestryFlags::ResilientOther);
340
341
    // Types with resilient superclasses have some extra symbols.
342
4.78k
    if (resilientAncestry || CD->hasResilientMetadata())
343
1.77k
      Visitor.addClassMetadataBaseOffset(CD);
344
345
4.78k
    auto &Ctx = CD->getASTContext();
346
4.78k
    if (Ctx.LangOpts.EnableObjCInterop && resilientAncestry)
347
336
      Visitor.addObjCResilientClassStub(CD);
348
349
4.78k
    return true;
350
11.5k
  }
351
352
94.6k
  void addMethodIfNecessary(FuncDecl *FD) {
353
94.6k
    auto CD = dyn_cast<ClassDecl>(FD->getDeclContext());
354
94.6k
    if (!CD)
355
70.4k
      return;
356
357
    // If we're already visiting the parent ClassDecl then this was handled by
358
    // its vtable visitor.
359
24.2k
    if (llvm::find(DeclStack, CD) != DeclStack.end())
360
24.1k
      return;
361
362
102
    SILDeclRef method = SILDeclRef(FD);
363
102
    if (Ctx.getOpts().VirtualFunctionElimination ||
364
102
        CD->hasResilientMetadata()) {
365
36
      Visitor.addDispatchThunk(method);
366
36
    }
367
102
    Visitor.addMethodDescriptor(method);
368
102
  }
369
370
  /// Returns `true` if the neither the nominal nor its members have any symbols
371
  /// that need to be visited because it has non-public linkage.
372
98.3k
  bool canSkipNominal(const NominalTypeDecl *NTD) {
373
98.3k
    if (!Ctx.getOpts().PublicSymbolsOnly)
374
0
      return false;
375
376
    // Don't skip nominals from clang modules; they have PublicNonUnique
377
    // linkage.
378
98.3k
    if (isa<ClangModuleUnit>(NTD->getDeclContext()->getModuleScopeContext()))
379
420
      return false;
380
381
97.9k
    return getDeclLinkage(NTD) != FormalLinkage::PublicUnique;
382
98.3k
  }
383
384
public:
385
  SILSymbolVisitorImpl(SILSymbolVisitor &Visitor,
386
                       const SILSymbolVisitorContext &Ctx)
387
23.7k
      : Visitor{Visitor}, Ctx{Ctx} {}
388
389
236k
  void visit(Decl *D) {
390
236k
    DeclStack.push_back(D);
391
236k
    SWIFT_DEFER { DeclStack.pop_back(); };
392
393
236k
    if (!Visitor.willVisitDecl(D))
394
507
      return;
395
235k
    ASTVisitor::visit(D);
396
235k
    Visitor.didVisitDecl(D);
397
235k
  }
398
399
24.2k
  void visit(FileUnit *file) {
400
24.6k
    auto visitFile = [this](FileUnit *file) {
401
24.6k
      SmallVector<Decl *, 16> decls;
402
24.6k
      file->getTopLevelDeclsWithAuxiliaryDecls(decls);
403
404
24.6k
      addMainIfNecessary(file);
405
406
257k
      for (auto D : decls) {
407
257k
        if (Ctx.getOpts().LinkerDirectivesOnly && !requiresLinkerDirective(D))
408
133k
          continue;
409
410
123k
        visit(D);
411
123k
      }
412
24.6k
    };
413
414
24.2k
    visitFile(file);
415
416
    // Visit synthesized file, if it exists.
417
24.2k
    if (auto *synthesizedFile = file->getSynthesizedFile())
418
402
      visitFile(synthesizedFile);
419
24.2k
  }
420
421
122k
  void visitDefaultArguments(ValueDecl *VD, ParameterList *PL) {
422
122k
    auto moduleDecl = VD->getModuleContext();
423
    // Check if symbols should be more visible than their declared access level.
424
    // In case of `package` access level, the symbol should be visible by an
425
    // external module in the same package, thus the default argument should be
426
    // generated and its linkage emitted.
427
122k
    auto shouldGenerateDefaultArgs = moduleDecl->isTestingEnabled() ||
428
122k
                                     moduleDecl->arePrivateImportsEnabled() ||
429
122k
                                     VD->getFormalAccess() == AccessLevel::Package;
430
122k
    if (Ctx.getOpts().PublicSymbolsOnly && !shouldGenerateDefaultArgs)
431
105k
      return;
432
433
    // In Swift 3 (or under -enable-testing), default arguments (of public
434
    // functions) are public symbols, as the default values are computed at the
435
    // call site.
436
16.8k
    auto index = 0;
437
16.8k
    for (auto *param : *PL) {
438
5.61k
      if (param->isDefaultArgument())
439
693
        addFunction(SILDeclRef::getDefaultArgGenerator(VD, index));
440
5.61k
      ++index;
441
5.61k
    }
442
16.8k
  }
443
444
119k
  void visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
445
    // Add exported prespecialized symbols.
446
119k
    for (auto *attr : AFD->getAttrs().getAttributes<SpecializeAttr>()) {
447
1.32k
      if (!attr->isExported())
448
216
        continue;
449
450
1.10k
      auto specializedSignature = attr->getSpecializedSignature(AFD);
451
1.10k
      auto erasedSignature =
452
1.10k
          specializedSignature.typeErased(attr->getTypeErasedParams());
453
454
1.10k
      if (auto *targetFun = attr->getTargetFunctionDecl(AFD)) {
455
462
        addFunction(SILDeclRef(targetFun, erasedSignature),
456
462
                    /*ignoreLinkage=*/true);
457
645
      } else {
458
645
        addFunction(SILDeclRef(AFD, erasedSignature), /*ignoreLinkage=*/true);
459
645
      }
460
1.10k
    }
461
462
119k
    addFunction(SILDeclRef(AFD));
463
464
119k
    if (auto dynKind = getDynamicKind(AFD)) {
465
      // Add the global function pointer for a dynamically replaceable function.
466
2.58k
      Visitor.addDynamicFunction(AFD, *dynKind);
467
2.58k
    }
468
469
119k
    if (AFD->getAttrs().hasAttribute<CDeclAttr>()) {
470
      // A @_cdecl("...") function has an extra symbol, with the name from the
471
      // attribute.
472
234
      addFunction(SILDeclRef(AFD).asForeign());
473
234
    }
474
475
119k
    if (auto distributedThunk = AFD->getDistributedThunk()) {
476
60
      auto thunk = SILDeclRef(distributedThunk).asDistributed();
477
60
      addFunction(thunk);
478
60
      addAsyncFunctionPointer(thunk);
479
60
    }
480
481
    // Add derivative function symbols.
482
119k
    for (const auto *differentiableAttr :
483
119k
           AFD->getAttrs().getAttributes<DifferentiableAttr>()) {
484
276
      auto *resultIndices = autodiff::getFunctionSemanticResultIndices(
485
276
        AFD,
486
276
        differentiableAttr->getParameterIndices());
487
276
      addDerivativeConfiguration(
488
276
          differentiableAttr->getDifferentiabilityKind(), AFD,
489
276
          AutoDiffConfig(differentiableAttr->getParameterIndices(),
490
276
                         resultIndices,
491
276
                         differentiableAttr->getDerivativeGenericSignature()));
492
276
    }
493
494
119k
    for (const auto *derivativeAttr :
495
119k
         AFD->getAttrs().getAttributes<DerivativeAttr>()) {
496
172
      auto *resultIndices = autodiff::getFunctionSemanticResultIndices(
497
172
        derivativeAttr->getOriginalFunction(AFD->getASTContext()),
498
172
        derivativeAttr->getParameterIndices());
499
172
      addDerivativeConfiguration(
500
172
          DifferentiabilityKind::Reverse,
501
172
          derivativeAttr->getOriginalFunction(AFD->getASTContext()),
502
172
          AutoDiffConfig(derivativeAttr->getParameterIndices(),
503
172
                         resultIndices,
504
172
                         AFD->getGenericSignature()));
505
172
    }
506
507
119k
    visitDefaultArguments(AFD, AFD->getParameters());
508
509
119k
    if (AFD->hasAsync()) {
510
2.32k
      addAsyncFunctionPointer(SILDeclRef(AFD));
511
2.32k
    }
512
513
    // Skip non objc compatible methods or non-public methods.
514
119k
    if (isa<DestructorDecl>(AFD) || !AFD->isObjC() ||
515
119k
        AFD->getFormalAccess() != AccessLevel::Public)
516
118k
      return;
517
1.06k
    Visitor.addObjCMethod(AFD);
518
1.06k
  }
519
520
94.6k
  void visitFuncDecl(FuncDecl *FD) {
521
    // If there's an opaque return type, its descriptor is exported.
522
94.6k
    addOpaqueResultIfNecessary(FD);
523
94.6k
    visitAbstractFunctionDecl(FD);
524
94.6k
    addMethodIfNecessary(FD);
525
94.6k
  }
526
527
0
  void visitAccessorDecl(AccessorDecl *AD) {
528
0
    llvm_unreachable("should not see an accessor here");
529
0
  }
530
531
31.2k
  void visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
532
    // Add the property descriptor if the decl needs it.
533
31.2k
    if (ASD->exportsPropertyDescriptor()) {
534
11.7k
      Visitor.addPropertyDescriptor(ASD);
535
11.7k
    }
536
537
    // ...and the opaque result decl if it has one.
538
31.2k
    addOpaqueResultIfNecessary(ASD);
539
540
    // Explicitly look at each accessor here: see visitAccessorDecl.
541
46.7k
    ASD->visitEmittedAccessors([&](AccessorDecl *accessor) {
542
46.7k
      visitFuncDecl(accessor);
543
46.7k
    });
544
545
    // Add derivative function symbols.
546
31.2k
    for (const auto *differentiableAttr :
547
31.2k
         ASD->getAttrs().getAttributes<DifferentiableAttr>()) {
548
      // FIXME: handle other accessors
549
24
      auto accessorDecl = ASD->getOpaqueAccessor(AccessorKind::Get);
550
24
      addDerivativeConfiguration(
551
24
          differentiableAttr->getDifferentiabilityKind(),
552
24
          accessorDecl,
553
24
          AutoDiffConfig(differentiableAttr->getParameterIndices(),
554
24
                         autodiff::getFunctionSemanticResultIndices(accessorDecl,
555
24
                                                                    differentiableAttr->getParameterIndices()),
556
24
                         differentiableAttr->getDerivativeGenericSignature()));
557
24
    }
558
31.2k
  }
559
560
30.3k
  void visitVarDecl(VarDecl *VD) {
561
    // Variables inside non-resilient modules have some additional symbols.
562
30.3k
    if (!VD->isResilient()) {
563
      // Non-global variables might have an explicit initializer symbol in
564
      // non-resilient modules.
565
25.9k
      if (VD->getAttrs().hasAttribute<HasInitialValueAttr>() &&
566
25.9k
          !isGlobalOrStaticVar(VD)) {
567
5.39k
        auto declRef =
568
5.39k
            SILDeclRef(VD, SILDeclRef::Kind::StoredPropertyInitializer);
569
        // Stored property initializers for public properties are public.
570
5.39k
        addFunction(declRef);
571
5.39k
      }
572
573
      // Statically/globally stored variables have some special handling.
574
25.9k
      if (VD->hasStorage() && isGlobalOrStaticVar(VD)) {
575
7.44k
        if (!Ctx.getOpts().PublicSymbolsOnly ||
576
7.44k
            getDeclLinkage(VD) == FormalLinkage::PublicUnique) {
577
624
          Visitor.addGlobalVar(VD);
578
624
        }
579
580
7.44k
        if (VD->isLazilyInitializedGlobal())
581
1.65k
          addFunction(SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor));
582
7.44k
      }
583
584
      // Wrapped non-static member properties may have a backing initializer.
585
25.9k
      auto initInfo = VD->getPropertyWrapperInitializerInfo();
586
25.9k
      if (initInfo.hasInitFromWrappedValue() && !VD->isStatic()) {
587
9
        addFunction(SILDeclRef(
588
9
            VD, SILDeclRef::Kind::PropertyWrapperBackingInitializer));
589
9
      }
590
25.9k
    }
591
592
30.3k
    visitAbstractStorageDecl(VD);
593
30.3k
  }
594
595
912
  void visitSubscriptDecl(SubscriptDecl *SD) {
596
912
    visitDefaultArguments(SD, SD->getIndices());
597
912
    visitAbstractStorageDecl(SD);
598
912
  }
599
600
  template<typename NominalOrExtension>
601
26.2k
  void visitMembers(NominalOrExtension *D) {
602
26.2k
    if (!Ctx.getOpts().VisitMembers)
603
18
      return;
604
605
26.2k
    for (auto member : D->getABIMembers())
606
112k
      visit(member);
607
26.2k
  }
_ZN20SILSymbolVisitorImpl12visitMembersIN5swift15NominalTypeDeclEEEvPT_
Line
Count
Source
601
20.0k
  void visitMembers(NominalOrExtension *D) {
602
20.0k
    if (!Ctx.getOpts().VisitMembers)
603
18
      return;
604
605
20.0k
    for (auto member : D->getABIMembers())
606
96.0k
      visit(member);
607
20.0k
  }
_ZN20SILSymbolVisitorImpl12visitMembersIN5swift13ExtensionDeclEEEvPT_
Line
Count
Source
601
6.23k
  void visitMembers(NominalOrExtension *D) {
602
6.23k
    if (!Ctx.getOpts().VisitMembers)
603
0
      return;
604
605
6.23k
    for (auto member : D->getABIMembers())
606
16.1k
      visit(member);
607
6.23k
  }
608
609
36.5k
  void visitNominalTypeDecl(NominalTypeDecl *NTD) {
610
36.5k
    if (canSkipNominal(NTD))
611
16.4k
      return;
612
613
20.0k
    if (NTD->getASTContext().LangOpts.hasFeature(Feature::Embedded))
614
0
      return;
615
616
20.0k
    auto declaredType = NTD->getDeclaredType()->getCanonicalType();
617
618
20.0k
    if (!NTD->getObjCImplementationDecl()) {
619
20.0k
      Visitor.addNominalTypeDescriptor(NTD);
620
621
      // Generic types do not get metadata directly, only through the function.
622
20.0k
      if (!NTD->isGenericContext()) {
623
17.9k
        Visitor.addTypeMetadataAddress(declaredType);
624
17.9k
      }
625
20.0k
    }
626
20.0k
    Visitor.addTypeMetadataAccessFunction(declaredType);
627
628
    // There are symbols associated with any protocols this type conforms to.
629
20.0k
    addConformances(NTD);
630
631
20.0k
    visitMembers(NTD);
632
20.0k
  }
633
634
11.5k
  void visitClassDecl(ClassDecl *CD) {
635
11.5k
    if (!addClassMetadata(CD))
636
6.74k
      return;
637
638
    // Emit dispatch thunks for every new vtable entry.
639
4.77k
    struct VTableVisitor : public SILVTableVisitor<VTableVisitor> {
640
4.77k
      SILSymbolVisitor &Visitor;
641
4.77k
      ClassDecl *CD;
642
4.77k
      bool FirstTime = true;
643
4.77k
      bool VirtualFunctionElimination;
644
645
4.77k
    public:
646
4.77k
      VTableVisitor(SILSymbolVisitorImpl &V, ClassDecl *CD)
647
4.77k
          : Visitor{V.Visitor}, CD{CD},
648
4.77k
            VirtualFunctionElimination{
649
4.77k
                V.Ctx.getOpts().VirtualFunctionElimination} {}
650
651
13.4k
      void addMethod(SILDeclRef method) {
652
13.4k
        assert(method.getDecl()->getDeclContext() == CD);
653
654
        // If the class is itself resilient and has at least one vtable
655
        // entry, it has a method lookup function.
656
0
        bool hasLookupFunc =
657
13.4k
            VirtualFunctionElimination || CD->hasResilientMetadata();
658
13.4k
        if (FirstTime) {
659
3.74k
          FirstTime = false;
660
661
3.74k
          if (hasLookupFunc)
662
1.16k
            Visitor.addMethodLookupFunction(CD);
663
3.74k
        }
664
665
13.4k
        if (!Visitor.willVisitDecl(method.getDecl()))
666
0
          return;
667
13.4k
        if (hasLookupFunc)
668
4.28k
          Visitor.addDispatchThunk(method);
669
670
13.4k
        Visitor.addMethodDescriptor(method);
671
13.4k
        Visitor.didVisitDecl(method.getDecl());
672
13.4k
      }
673
674
4.77k
      void addMethodOverride(SILDeclRef baseRef, SILDeclRef derivedRef) {}
675
676
4.77k
      void addPlaceholder(MissingMemberDecl *) {}
677
678
4.77k
      void doIt() {
679
4.77k
        addVTableEntries(CD);
680
4.77k
      }
681
4.77k
    };
682
683
4.77k
    if (Ctx.getOpts().VisitMembers)
684
4.77k
      VTableVisitor(*this, CD).doIt();
685
4.77k
  }
686
687
19.7k
  void visitConstructorDecl(ConstructorDecl *CD) {
688
19.7k
    if (CD->getParent()->getSelfClassDecl()) {
689
      // Class constructors come in two forms, allocating and non-allocating.
690
      // The default ValueDecl handling gives the allocating one, so we have to
691
      // manually include the non-allocating one.
692
4.98k
      addFunction(SILDeclRef(CD, SILDeclRef::Kind::Initializer));
693
4.98k
      if (CD->hasAsync()) {
694
9
        addAsyncFunctionPointer(SILDeclRef(CD, SILDeclRef::Kind::Initializer));
695
9
      }
696
4.98k
    }
697
698
19.7k
    visitAbstractFunctionDecl(CD);
699
19.7k
  }
700
701
4.84k
  void visitDestructorDecl(DestructorDecl *DD) {
702
    // Destructors come in two forms (deallocating and non-deallocating), like
703
    // constructors above. Classes use both but move only non-class nominal
704
    // types only use the deallocating one. This is the deallocating one:
705
4.84k
    visitAbstractFunctionDecl(DD);
706
707
4.84k
    if (auto parentClass = DD->getParent()->getSelfClassDecl()) {
708
      // But the non-deallocating one doesn't apply to some @objc classes.
709
4.78k
      if (!Lowering::usesObjCAllocator(parentClass)) {
710
4.23k
        addFunction(SILDeclRef(DD, SILDeclRef::Kind::Destroyer));
711
4.23k
      }
712
4.78k
    }
713
4.84k
  }
714
715
9.11k
  void visitExtensionDecl(ExtensionDecl *ED) {
716
9.11k
    auto nominal = ED->getExtendedNominal();
717
9.11k
    if (canSkipNominal(nominal))
718
2.87k
      return;
719
720
6.23k
    if (auto CD = dyn_cast_or_null<ClassDecl>(ED->getImplementedObjCDecl())) {
721
      // @_objcImplementation extensions generate the class metadata symbols.
722
12
      (void)addClassMetadata(CD);
723
12
    }
724
725
6.23k
    if (!isa<ProtocolDecl>(nominal)) {
726
5.58k
      addConformances(ED);
727
5.58k
    }
728
729
6.23k
    visitMembers(ED);
730
6.23k
  }
731
732
#ifndef NDEBUG
733
2.59k
  static bool isExpectedProtocolMember(const Decl *D) {
734
2.59k
    switch (D->getKind()) {
735
9
    case DeclKind::TypeAlias:
736
622
    case DeclKind::AssociatedType:
737
1.13k
    case DeclKind::Var:
738
1.16k
    case DeclKind::Subscript:
739
1.68k
    case DeclKind::PatternBinding:
740
2.52k
    case DeclKind::Func:
741
2.52k
    case DeclKind::Accessor:
742
2.59k
    case DeclKind::Constructor:
743
2.59k
    case DeclKind::Destructor:
744
2.59k
    case DeclKind::IfConfig:
745
2.59k
    case DeclKind::PoundDiagnostic:
746
2.59k
      return true;
747
0
    case DeclKind::OpaqueType:
748
0
    case DeclKind::Enum:
749
0
    case DeclKind::Struct:
750
0
    case DeclKind::Class:
751
0
    case DeclKind::Protocol:
752
0
    case DeclKind::GenericTypeParam:
753
0
    case DeclKind::Module:
754
0
    case DeclKind::Param:
755
0
    case DeclKind::EnumElement:
756
0
    case DeclKind::Extension:
757
0
    case DeclKind::TopLevelCode:
758
0
    case DeclKind::Import:
759
0
    case DeclKind::PrecedenceGroup:
760
0
    case DeclKind::MissingMember:
761
0
    case DeclKind::EnumCase:
762
0
    case DeclKind::InfixOperator:
763
0
    case DeclKind::PrefixOperator:
764
0
    case DeclKind::PostfixOperator:
765
0
    case DeclKind::Macro:
766
0
    case DeclKind::MacroExpansion:
767
0
      return false;
768
0
    case DeclKind::Missing:
769
0
      llvm_unreachable("missing decl should not show up here");
770
0
    case DeclKind::BuiltinTuple:
771
0
      llvm_unreachable("BuiltinTupleDecl should not show up here");
772
2.59k
    }
773
0
    llvm_unreachable("covered switch");
774
0
  }
775
#endif
776
777
4.66k
  void visitProtocolDecl(ProtocolDecl *PD) {
778
4.66k
    if (canSkipNominal(PD))
779
2.80k
      return;
780
781
1.86k
    if (!PD->isObjC() && !PD->isMarkerProtocol()) {
782
1.70k
      Visitor.addProtocolDescriptor(PD);
783
784
1.70k
      struct WitnessVisitor : public SILWitnessVisitor<WitnessVisitor> {
785
1.70k
        SILSymbolVisitor &Visitor;
786
1.70k
        ProtocolDecl *PD;
787
1.70k
        bool Resilient;
788
1.70k
        bool WitnessMethodElimination;
789
790
1.70k
      public:
791
1.70k
        WitnessVisitor(SILSymbolVisitorImpl &V, ProtocolDecl *PD)
792
1.70k
            : Visitor{V.Visitor}, PD{PD},
793
1.70k
              Resilient{PD->getParentModule()->isResilient()},
794
1.70k
              WitnessMethodElimination{
795
1.70k
                  V.Ctx.getOpts().WitnessMethodElimination} {}
796
797
2.17k
        void addMethod(SILDeclRef declRef) {
798
2.17k
          if (Resilient || WitnessMethodElimination) {
799
594
            Visitor.addDispatchThunk(declRef);
800
594
            Visitor.addMethodDescriptor(declRef);
801
594
          }
802
2.17k
        }
803
804
1.70k
        void addAssociatedType(AssociatedType associatedType) {
805
604
          Visitor.addAssociatedTypeDescriptor(associatedType.getAssociation());
806
604
        }
807
808
1.70k
        void addProtocolConformanceDescriptor() {
809
1.70k
          Visitor.addProtocolRequirementsBaseDescriptor(PD);
810
1.70k
        }
811
812
1.70k
        void addOutOfLineBaseProtocol(ProtocolDecl *proto) {
813
348
          Visitor.addBaseConformanceDescriptor(BaseConformance(PD, proto));
814
348
        }
815
816
1.70k
        void addAssociatedConformance(AssociatedConformance associatedConf) {
817
247
          Visitor.addAssociatedConformanceDescriptor(associatedConf);
818
247
        }
819
820
1.70k
        void addPlaceholder(MissingMemberDecl *decl) {}
821
822
1.70k
        void doIt() {
823
1.70k
          visitProtocolDecl(PD);
824
1.70k
        }
825
1.70k
      };
826
827
1.70k
      WitnessVisitor(*this, PD).doIt();
828
829
      // Include the self-conformance.
830
1.70k
      addConformances(PD);
831
1.70k
    }
832
833
1.86k
#ifndef NDEBUG
834
    // There are currently no symbols associated with the members of a protocol;
835
    // each conforming type has to handle them individually.
836
    // (NB. anything within an active IfConfigDecls also appears outside). Let's
837
    // assert this fact:
838
2.59k
    for (auto *member : PD->getMembers()) {
839
2.59k
      assert(isExpectedProtocolMember(member) &&
840
2.59k
             "unexpected member of protocol during TBD generation");
841
2.59k
    }
842
1.86k
#endif
843
1.86k
  }
844
845
8.99k
  void visitEnumDecl(EnumDecl *ED) {
846
8.99k
    visitNominalTypeDecl(ED);
847
8.99k
  }
848
849
4.03k
  void visitEnumElementDecl(EnumElementDecl *EED) {
850
4.03k
    if (EED->getParentEnum()->isResilient())
851
1.24k
      Visitor.addEnumCase(EED);
852
853
4.03k
    if (auto *PL = EED->getParameterList())
854
2.11k
      visitDefaultArguments(EED, PL);
855
4.03k
  }
856
857
#define UNINTERESTING_DECL(CLASS)                                              \
858
70.9k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl14visitValueDeclEPN5swift9ValueDeclE
Line
Count
Source
858
4.57k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl21visitTopLevelCodeDeclEPN5swift16TopLevelCodeDeclE
Line
Count
Source
858
28.9k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl15visitImportDeclEPN5swift10ImportDeclE
Line
Count
Source
858
7.47k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl17visitIfConfigDeclEPN5swift12IfConfigDeclE
Line
Count
Source
858
1.81k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl24visitPoundDiagnosticDeclEPN5swift19PoundDiagnosticDeclE
Line
Count
Source
858
3
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl24visitPrecedenceGroupDeclEPN5swift19PrecedenceGroupDeclE
Line
Count
Source
858
33
  void visit##CLASS##Decl(CLASS##Decl *) {}
Unexecuted instantiation: _ZN20SILSymbolVisitorImpl16visitMissingDeclEPN5swift11MissingDeclE
Unexecuted instantiation: _ZN20SILSymbolVisitorImpl22visitMissingMemberDeclEPN5swift17MissingMemberDeclE
_ZN20SILSymbolVisitorImpl23visitPatternBindingDeclEPN5swift18PatternBindingDeclE
Line
Count
Source
858
24.1k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl17visitEnumCaseDeclEPN5swift12EnumCaseDeclE
Line
Count
Source
858
3.80k
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl17visitOperatorDeclEPN5swift12OperatorDeclE
Line
Count
Source
858
132
  void visit##CLASS##Decl(CLASS##Decl *) {}
_ZN20SILSymbolVisitorImpl23visitMacroExpansionDeclEPN5swift18MacroExpansionDeclE
Line
Count
Source
858
21
  void visit##CLASS##Decl(CLASS##Decl *) {}
859
860
  UNINTERESTING_DECL(EnumCase)
861
  UNINTERESTING_DECL(IfConfig)
862
  UNINTERESTING_DECL(Import)
863
  UNINTERESTING_DECL(MacroExpansion)
864
  UNINTERESTING_DECL(Missing)
865
  UNINTERESTING_DECL(MissingMember)
866
  UNINTERESTING_DECL(Operator)
867
  UNINTERESTING_DECL(PatternBinding)
868
  UNINTERESTING_DECL(PoundDiagnostic)
869
  UNINTERESTING_DECL(PrecedenceGroup)
870
  UNINTERESTING_DECL(TopLevelCode)
871
  UNINTERESTING_DECL(Value)
872
873
#undef UNINTERESTING_DECL
874
};
875
876
302
void SILSymbolVisitor::visitDecl(Decl *D, const SILSymbolVisitorContext &ctx) {
877
302
  SILSymbolVisitorImpl(*this, ctx).visit(D);
878
302
}
879
880
void SILSymbolVisitor::visitFile(FileUnit *file,
881
14.6k
                                 const SILSymbolVisitorContext &ctx) {
882
14.6k
  SILSymbolVisitorImpl(*this, ctx).visit(file);
883
14.6k
}
884
885
void SILSymbolVisitor::visitModules(llvm::SmallVector<ModuleDecl *, 4> &modules,
886
8.73k
                                    const SILSymbolVisitorContext &ctx) {
887
8.73k
  auto impl = SILSymbolVisitorImpl(*this, ctx);
888
8.74k
  for (auto *M : modules) {
889
9.58k
    for (auto *file : M->getFiles()) {
890
9.58k
      impl.visit(file);
891
9.58k
    }
892
8.74k
  }
893
8.73k
}