/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 | } |