24
24
#include " swift/AST/ProtocolConformance.h"
25
25
#include " swift/AST/TypeMemberVisitor.h"
26
26
#include " swift/SIL/SILArgument.h"
27
+ #include " swift/SIL/SILVTableVisitor.h"
27
28
#include " swift/SIL/TypeLowering.h"
28
29
29
30
using namespace swift ;
@@ -146,154 +147,83 @@ bool SILGenModule::requiresObjCMethodEntryPoint(ConstructorDecl *constructor) {
146
147
namespace {
147
148
148
149
// / An ASTVisitor for populating SILVTable entries from ClassDecl members.
149
- class SILGenVTable : public Lowering ::ASTVisitor <SILGenVTable> {
150
+ class SILGenVTable : public SILVTableVisitor <SILGenVTable> {
150
151
public:
151
152
SILGenModule &SGM;
152
153
ClassDecl *theClass;
153
154
std::vector<SILVTable::Entry> vtableEntries;
154
155
155
156
SILGenVTable (SILGenModule &SGM, ClassDecl *theClass)
156
157
: SGM(SGM), theClass(theClass)
157
- {
158
- // Populate the superclass members, if any.
159
- Type super = theClass->getSuperclass ();
160
- if (super && super->getClassOrBoundGenericClass ())
161
- visitAncestor (super->getClassOrBoundGenericClass ());
162
- }
158
+ { }
163
159
164
- ~SILGenVTable () {
165
- // Create the vtable.
166
- SILVTable::create (SGM.M , theClass, vtableEntries);
167
- }
160
+ void emitVTable () {
161
+ // Populate the superclass members, if any.
162
+ visitAncestor (theClass);
168
163
169
- void visitAncestor (ClassDecl *ancestor) {
170
- // Recursively visit all our ancestors.
171
- Type super = ancestor->getSuperclass ();
172
- if (super && super->getClassOrBoundGenericClass ())
173
- visitAncestor (super->getClassOrBoundGenericClass ());
174
-
175
- // Only visit the members for a class defined natively.
176
- if (!ancestor->hasClangNode ()) {
177
- for (auto member : ancestor->getMembers ())
178
- visit (member);
179
- }
180
- }
164
+ auto *dtor = theClass->getDestructor ();
165
+ assert (dtor);
181
166
182
- // Add an entry to the vtable.
183
- void addEntry (SILDeclRef member) {
184
- // / Get the function to reference from the vtable.
185
- auto getVtableEntry = [&](SILDeclRef entry) -> SILVTable::Entry {
186
- // If the member is dynamic, reference its dynamic dispatch thunk so that
187
- // it will be redispatched, funneling the method call through the runtime
188
- // hook point.
189
- // TODO: Dynamic thunks could conceivably require reabstraction too.
190
- if (member.getDecl ()->getAttrs ().hasAttribute <DynamicAttr>())
191
- return { entry,
192
- SGM.getDynamicThunk (member, SGM.Types .getConstantInfo (member)),
193
- SILLinkage::Public };
194
-
195
- // The derived method may require thunking to match up to the ABI of the
196
- // base method.
197
- SILLinkage implLinkage;
198
- SILFunction *implFn = SGM.emitVTableMethod (member, entry, implLinkage);
199
- return { entry, implFn, stripExternalFromLinkage (implLinkage) };
200
- };
201
-
202
- // Try to find an overridden entry.
203
- // NB: Mutates vtableEntries in-place
204
- // FIXME: O(n^2)
205
- if (auto overridden = member.getNextOverriddenVTableEntry ()) {
206
- for (SILVTable::Entry &entry : vtableEntries) {
207
- SILDeclRef ref = overridden;
208
-
209
- do {
210
- // Replace the overridden member.
211
- if (entry.Method == ref) {
212
- // The entry is keyed by the least derived method.
213
- entry = getVtableEntry (ref);
214
- return ;
215
- }
216
- } while ((ref = ref.getOverridden ()));
217
- }
218
- llvm_unreachable (" no overridden vtable entry?!" );
219
- }
167
+ // Add the deallocating destructor to the vtable just for the purpose
168
+ // that it is referenced and cannot be eliminated by dead function removal.
169
+ // In reality, the deallocating destructor is referenced directly from
170
+ // the HeapMetadata for the class.
171
+ if (!dtor->hasClangNode ())
172
+ addMethod (SILDeclRef (dtor, SILDeclRef::Kind::Deallocator));
220
173
221
- // If this is a final member and isn't overriding something, we don't need
222
- // to add it to the vtable.
223
- if (member.getDecl ()->isFinal ())
224
- return ;
225
- // If this is dynamic and isn't overriding a non-dynamic method, it'll
226
- // always be accessed by objc_msgSend, so we don't need to add it to the
227
- // vtable.
228
- if (member.getDecl ()->getAttrs ().hasAttribute <DynamicAttr>())
229
- return ;
174
+ if (SGM.requiresIVarDestroyer (theClass))
175
+ addMethod (SILDeclRef (theClass, SILDeclRef::Kind::IVarDestroyer));
230
176
231
- // Otherwise, introduce a new vtable entry .
232
- vtableEntries. push_back ( getVtableEntry (member) );
177
+ // Create the vtable.
178
+ SILVTable::create (SGM. M , theClass, vtableEntries );
233
179
}
234
180
235
- // Default for members that don't require vtable entries.
236
- void visitDecl (Decl*) {}
237
-
238
- void visitFuncDecl (FuncDecl *fd) {
239
- // ObjC decls don't go in vtables.
240
- if (fd->hasClangNode ())
241
- return ;
242
-
243
- // Observers don't get separate vtable entries.
244
- if (fd->isObservingAccessor ())
245
- return ;
181
+ void visitAncestor (ClassDecl *ancestor) {
182
+ auto superTy = ancestor->getSuperclass ();
183
+ if (superTy)
184
+ visitAncestor (superTy->getClassOrBoundGenericClass ());
246
185
247
- addEntry ( SILDeclRef (fd) );
186
+ addVTableEntries (ancestor );
248
187
}
249
188
250
- void visitConstructorDecl (ConstructorDecl *cd) {
251
- // Stub constructors don't get an entry, unless they were synthesized to
252
- // override a non-required designated initializer in the superclass.
253
- if (cd->hasStubImplementation () && !cd->getOverriddenDecl ())
254
- return ;
255
-
256
- // Required constructors (or overrides thereof) have their allocating entry
257
- // point in the vtable.
258
- bool isRequired = false ;
259
- auto override = cd;
260
- while (override ) {
261
- if (override ->isRequired ()) {
262
- isRequired = true ;
263
- break ;
264
- }
265
- override = override ->getOverriddenDecl ();
189
+ SILVTable::Entry getVTableEntry (SILDeclRef baseRef, SILDeclRef declRef) {
190
+ // If the member is dynamic, reference its dynamic dispatch thunk so that
191
+ // it will be redispatched, funneling the method call through the runtime
192
+ // hook point.
193
+ // TODO: Dynamic thunks could conceivably require reabstraction too.
194
+ if (declRef.getDecl ()->isDynamic ()) {
195
+ return { baseRef,
196
+ SGM.getDynamicThunk (declRef, SGM.Types .getConstantInfo (declRef)),
197
+ SILLinkage::Public };
266
198
}
267
- if (isRequired) {
268
- addEntry (SILDeclRef (cd, SILDeclRef::Kind::Allocator));
269
- }
270
-
271
- // All constructors have their initializing constructor in the
272
- // vtable, which can be used by a convenience initializer.
273
- addEntry (SILDeclRef (cd, SILDeclRef::Kind::Initializer));
274
- }
275
199
276
- void visitVarDecl (VarDecl *vd) {
277
- // Note: dynamically-dispatched properties have their getter and setter
278
- // added to the vtable when they are visited.
200
+ // The derived method may require thunking to match up to the ABI of the
201
+ // base method.
202
+ SILLinkage implLinkage;
203
+ SILFunction *implFn = SGM.emitVTableMethod (declRef, baseRef, implLinkage);
204
+ return { baseRef, implFn, stripExternalFromLinkage (implLinkage) };
279
205
}
280
206
281
- void visitDestructorDecl (DestructorDecl *dd) {
282
- if (dd->getParent ()->getAsClassOrClassExtensionContext () == theClass) {
283
- // Add the deallocating destructor to the vtable just for the purpose
284
- // that it is referenced and cannot be eliminated by dead function removal.
285
- // In reality, the deallocating destructor is referenced directly from
286
- // the HeapMetadata for the class.
287
- addEntry (SILDeclRef (dd, SILDeclRef::Kind::Deallocator));
288
-
289
- if (SGM.requiresIVarDestroyer (theClass))
290
- addEntry (SILDeclRef (theClass, SILDeclRef::Kind::IVarDestroyer));
207
+ // Try to find an overridden entry.
208
+ void addMethodOverride (SILDeclRef baseRef, SILDeclRef declRef) {
209
+ // NB: Mutates vtableEntries in-place
210
+ // FIXME: O(n^2)
211
+ for (SILVTable::Entry &entry : vtableEntries) {
212
+ // Replace the overridden member.
213
+ if (entry.Method == baseRef) {
214
+ // The entry is keyed by the least derived method.
215
+ entry = getVTableEntry (baseRef, declRef);
216
+ return ;
217
+ }
291
218
}
219
+ baseRef.dump ();
220
+ declRef.dump ();
221
+ llvm_unreachable (" no overridden vtable entry?!" );
292
222
}
293
223
294
- void visitSubscriptDecl (SubscriptDecl *sd) {
295
- // Note: dynamically-dispatched properties have their getter and setter
296
- // added to the vtable when they are visited.
224
+ // Add an entry to the vtable.
225
+ void addMethod (SILDeclRef member) {
226
+ vtableEntries. push_back ( getVTableEntry (member, member));
297
227
}
298
228
};
299
229
@@ -319,24 +249,22 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
319
249
public:
320
250
SILGenModule &SGM;
321
251
NominalTypeDecl *theType;
322
- Optional<SILGenVTable> genVTable;
323
252
324
253
SILGenType (SILGenModule &SGM, NominalTypeDecl *theType)
325
254
: SGM(SGM), theType(theType) {}
326
255
327
256
// / Emit SIL functions for all the members of the type.
328
257
void emitType () {
329
- // Start building a vtable if this is a class.
330
- if (auto theClass = dyn_cast<ClassDecl>(theType))
331
- genVTable.emplace (SGM, theClass);
332
-
333
- for (Decl *member : theType->getMembers ()) {
334
- if (genVTable)
335
- genVTable->visit (member);
336
-
258
+ for (Decl *member : theType->getMembers ())
337
259
visit (member);
260
+
261
+ // Build a vtable if this is a class.
262
+ if (auto theClass = dyn_cast<ClassDecl>(theType)) {
263
+ SILGenVTable genVTable (SGM, theClass);
264
+ genVTable.emitVTable ();
338
265
}
339
266
267
+ // Build a default witness table if this is a protocol.
340
268
if (auto protocol = dyn_cast<ProtocolDecl>(theType)) {
341
269
if (!protocol->isObjC ())
342
270
SGM.emitDefaultWitnessTable (protocol);
0 commit comments