1
+ // ===--- SILGenLazyConformance.cpp ----------------------------------------===//
2
+ //
3
+ // This source file is part of the Swift.org open source project
4
+ //
5
+ // Copyright (c) 2014 - 2019 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
+ #include " SILGen.h"
14
+ #include " swift/AST/Decl.h"
15
+ #include " swift/AST/ProtocolConformance.h"
16
+ #include " swift/SIL/SILInstruction.h"
17
+ #include " swift/SIL/SILVisitor.h"
18
+
19
+ using namespace swift ;
20
+ using namespace swift ::Lowering;
21
+
22
+ void SILGenModule::useConformance (ProtocolConformanceRef conformanceRef) {
23
+ // We don't need to emit dependent conformances.
24
+ if (conformanceRef.isAbstract ())
25
+ return ;
26
+
27
+ auto conformance = conformanceRef.getConcrete ();
28
+ auto normal = dyn_cast<NormalProtocolConformance>(
29
+ conformance->getRootConformance ());
30
+ if (normal == nullptr )
31
+ return ;
32
+
33
+ // If we already emitted this witness table, we don't need to track the fact
34
+ // we need it.
35
+ if (emittedWitnessTables.count (normal))
36
+ return ;
37
+
38
+ // If we delayed emitting this witness table, force it.
39
+ auto foundDelayed = delayedConformances.find (normal);
40
+ if (foundDelayed != delayedConformances.end ()) {
41
+ forcedConformances.push_back (*foundDelayed);
42
+ delayedConformances.erase (foundDelayed);
43
+ return ;
44
+ }
45
+
46
+ // Otherwise, just remember the fact we used this conformance.
47
+ usedConformances.insert (normal);
48
+ }
49
+
50
+ void SILGenModule::useConformancesFromSubstitutions (
51
+ const SubstitutionMap subs) {
52
+ for (auto conf : subs.getConformances ())
53
+ useConformance (conf);
54
+ }
55
+
56
+ void SILGenModule::useConformancesFromType (CanType type) {
57
+ type.findIf ([&](Type t) -> bool {
58
+ auto *decl = t->getAnyNominal ();
59
+ if (!decl)
60
+ return false ;
61
+
62
+ if (isa<ProtocolDecl>(decl))
63
+ return false ;
64
+
65
+ auto *genericSig = decl->getGenericSignature ();
66
+ if (!genericSig)
67
+ return false ;
68
+
69
+ auto subMap = t->getContextSubstitutionMap (SwiftModule, decl);
70
+ useConformancesFromSubstitutions (subMap);
71
+ return false ;
72
+ });
73
+ }
74
+
75
+ // / A visitor class that tries to guess which SIL instructions can cause
76
+ // / IRGen to emit references to witness tables. This is used to emit
77
+ // / ClangImporter-synthesized conformances lazily.
78
+ // /
79
+ // / In the long run, we'll instead have IRGen directly ask SILGen to
80
+ // / generate a witness table when needed, so that we don't have to do
81
+ // / any "guessing" here.
82
+ class LazyConformanceEmitter : public SILInstructionVisitor <LazyConformanceEmitter> {
83
+ SILGenModule &SGM;
84
+
85
+ public:
86
+ LazyConformanceEmitter (SILGenModule &SGM) : SGM(SGM) {}
87
+
88
+ void visitAllocExistentialBoxInst (AllocExistentialBoxInst *AEBI) {
89
+ SGM.useConformancesFromType (AEBI->getFormalConcreteType ());
90
+ for (auto conformance : AEBI->getConformances ())
91
+ SGM.useConformance (conformance);
92
+ }
93
+
94
+ void visitAllocGlobalInst (AllocGlobalInst *AGI) {
95
+ SGM.useConformancesFromType (
96
+ AGI->getReferencedGlobal ()->getLoweredType ().getASTType ());
97
+ }
98
+
99
+ void visitAllocRefInst (AllocRefInst *ARI) {
100
+ SGM.useConformancesFromType (ARI->getType ().getASTType ());
101
+ }
102
+
103
+ void visitAllocStackInst (AllocStackInst *ASI) {
104
+ SGM.useConformancesFromType (ASI->getType ().getASTType ());
105
+ }
106
+
107
+ void visitAllocValueBufferInst (AllocValueBufferInst *AVBI) {
108
+ SGM.useConformancesFromType (AVBI->getType ().getASTType ());
109
+ }
110
+
111
+ void visitApplyInst (ApplyInst *AI) {
112
+ SGM.useConformancesFromSubstitutions (AI->getSubstitutionMap ());
113
+ }
114
+
115
+ void visitBeginApplyInst (BeginApplyInst *BAI) {
116
+ SGM.useConformancesFromSubstitutions (BAI->getSubstitutionMap ());
117
+ }
118
+
119
+ void visitBuiltinInst (BuiltinInst *BI) {
120
+ SGM.useConformancesFromSubstitutions (BI->getSubstitutions ());
121
+ }
122
+
123
+ void visitCheckedCastBranchInst (CheckedCastBranchInst *CCBI) {
124
+ SGM.useConformancesFromType (CCBI->getSourceType ());
125
+ SGM.useConformancesFromType (CCBI->getTargetType ());
126
+ }
127
+
128
+ void visitCheckedCastAddrBranchInst (CheckedCastAddrBranchInst *CCABI) {
129
+ SGM.useConformancesFromType (CCABI->getSourceType ());
130
+ SGM.useConformancesFromType (CCABI->getTargetType ());
131
+ }
132
+
133
+ void visitCheckedCastValueBranchInst (CheckedCastValueBranchInst *CCVBI) {
134
+ SGM.useConformancesFromType (CCVBI->getSourceType ());
135
+ SGM.useConformancesFromType (CCVBI->getTargetType ());
136
+ }
137
+
138
+ void visitCopyAddrInst (CopyAddrInst *CAI) {
139
+ SGM.useConformancesFromType (CAI->getSrc ()->getType ().getASTType ());
140
+ SGM.useConformancesFromType (CAI->getDest ()->getType ().getASTType ());
141
+ }
142
+
143
+ void visitCopyValueInst (CopyValueInst *CVI) {
144
+ SGM.useConformancesFromType (CVI->getOperand ()->getType ().getASTType ());
145
+ }
146
+
147
+ void visitDestroyAddrInst (DestroyAddrInst *DAI) {
148
+ SGM.useConformancesFromType (DAI->getOperand ()->getType ().getASTType ());
149
+ }
150
+
151
+ void visitDestroyValueInst (DestroyValueInst *DVI) {
152
+ SGM.useConformancesFromType (DVI->getOperand ()->getType ().getASTType ());
153
+ }
154
+
155
+ void visitGlobalAddrInst (GlobalAddrInst *GAI) {
156
+ SGM.useConformancesFromType (
157
+ GAI->getReferencedGlobal ()->getLoweredType ().getASTType ());
158
+ }
159
+
160
+ void visitGlobalValueInst (GlobalValueInst *GVI) {
161
+ SGM.useConformancesFromType (
162
+ GVI->getReferencedGlobal ()->getLoweredType ().getASTType ());
163
+ }
164
+
165
+ void visitKeyPathInst (KeyPathInst *KPI) {
166
+ SGM.useConformancesFromSubstitutions (KPI->getSubstitutions ());
167
+ }
168
+
169
+ void visitInitEnumDataAddrInst (InitEnumDataAddrInst *IEDAI) {
170
+ SGM.useConformancesFromType (
171
+ IEDAI->getOperand ()->getType ().getASTType ());
172
+ }
173
+
174
+ void visitInjectEnumAddrInst (InjectEnumAddrInst *IEAI) {
175
+ SGM.useConformancesFromType (IEAI->getOperand ()->getType ().getASTType ());
176
+ }
177
+
178
+ void visitInitExistentialAddrInst (InitExistentialAddrInst *IEAI) {
179
+ SGM.useConformancesFromType (IEAI->getFormalConcreteType ());
180
+ for (auto conformance : IEAI->getConformances ())
181
+ SGM.useConformance (conformance);
182
+ }
183
+
184
+ void visitInitExistentialMetatypeInst (InitExistentialMetatypeInst *IEMI) {
185
+ SGM.useConformancesFromType (IEMI->getOperand ()->getType ().getASTType ());
186
+ for (auto conformance : IEMI->getConformances ())
187
+ SGM.useConformance (conformance);
188
+ }
189
+
190
+ void visitInitExistentialRefInst (InitExistentialRefInst *IERI) {
191
+ SGM.useConformancesFromType (IERI->getFormalConcreteType ());
192
+ for (auto conformance : IERI->getConformances ())
193
+ SGM.useConformance (conformance);
194
+ }
195
+
196
+ void visitInitExistentialValueInst (InitExistentialValueInst *IEVI) {
197
+ SGM.useConformancesFromType (IEVI->getFormalConcreteType ());
198
+ for (auto conformance : IEVI->getConformances ())
199
+ SGM.useConformance (conformance);
200
+ }
201
+
202
+ void visitMetatypeInst (MetatypeInst *MI) {
203
+ SGM.useConformancesFromType (MI->getType ().getASTType ());
204
+ }
205
+
206
+ void visitPartialApplyInst (PartialApplyInst *PAI) {
207
+ SGM.useConformancesFromSubstitutions (PAI->getSubstitutionMap ());
208
+ }
209
+
210
+ void visitSelectEnumAddrInst (SelectEnumAddrInst *SEAI) {
211
+ SGM.useConformancesFromType (
212
+ SEAI->getEnumOperand ()->getType ().getASTType ());
213
+ }
214
+
215
+ void visitStructElementAddrInst (StructElementAddrInst *SEAI) {
216
+ SGM.useConformancesFromType (SEAI->getOperand ()->getType ().getASTType ());
217
+ }
218
+
219
+ void visitTryApplyInst (TryApplyInst *TAI) {
220
+ SGM.useConformancesFromSubstitutions (TAI->getSubstitutionMap ());
221
+ }
222
+
223
+ void visitTupleElementAddrInst (TupleElementAddrInst *TEAI) {
224
+ SGM.useConformancesFromType (TEAI->getOperand ()->getType ().getASTType ());
225
+ }
226
+
227
+ void visitUnconditionalCheckedCastInst (UnconditionalCheckedCastInst *UCCI) {
228
+ SGM.useConformancesFromType (UCCI->getSourceType ());
229
+ SGM.useConformancesFromType (UCCI->getTargetType ());
230
+ }
231
+
232
+ void visitUnconditionalCheckedCastAddrInst (UnconditionalCheckedCastAddrInst *UCCAI) {
233
+ SGM.useConformancesFromType (UCCAI->getSourceType ());
234
+ SGM.useConformancesFromType (UCCAI->getTargetType ());
235
+ }
236
+
237
+ void visitUncheckedTakeEnumDataAddrInst (UncheckedTakeEnumDataAddrInst *UTEDAI) {}
238
+
239
+ void visitWitnessMethodInst (WitnessMethodInst *WMI) {
240
+ SGM.useConformance (WMI->getConformance ());
241
+ }
242
+
243
+ void visitSILInstruction (SILInstruction *I) {}
244
+ };
245
+
246
+ void SILGenModule::emitLazyConformancesForFunction (SILFunction *F) {
247
+ LazyConformanceEmitter emitter (*this );
248
+
249
+ for (auto &BB : *F)
250
+ for (auto &I : BB)
251
+ emitter.visit (&I);
252
+ }
0 commit comments