@@ -205,18 +205,21 @@ static void emitMetadataCompletionFunction(IRGenModule &IGM,
205205 IGF.Builder .CreateRet (returnValue);
206206}
207207
208- static bool needsForeignMetadataCompletionFunction (StructDecl *decl) {
208+ static bool needsForeignMetadataCompletionFunction (IRGenModule &IGM,
209+ StructDecl *decl) {
209210 // Currently, foreign structs never need a completion function.
210211 return false ;
211212}
212213
213- static bool needsForeignMetadataCompletionFunction (EnumDecl *decl) {
214+ static bool needsForeignMetadataCompletionFunction (IRGenModule &IGM,
215+ EnumDecl *decl) {
214216 // Currently, foreign enums never need a completion function.
215217 return false ;
216218}
217219
218- static bool needsForeignMetadataCompletionFunction (ClassDecl *decl) {
219- return decl->hasSuperclass ();
220+ static bool needsForeignMetadataCompletionFunction (IRGenModule &IGM,
221+ ClassDecl *decl) {
222+ return IGM.getOptions ().LazyInitializeClassMetadata || decl->hasSuperclass ();
220223}
221224
222225/* ****************************************************************************/
@@ -1171,7 +1174,7 @@ namespace {
11711174 }
11721175
11731176 bool needsForeignMetadataCompletionFunction () {
1174- return ::needsForeignMetadataCompletionFunction (Type);
1177+ return ::needsForeignMetadataCompletionFunction (IGM, Type);
11751178 }
11761179
11771180 // / Add an SingletonMetadataInitialization structure to the descriptor.
@@ -3804,7 +3807,7 @@ namespace {
38043807 }
38053808
38063809 bool needsMetadataCompletionFunction () {
3807- return needsForeignMetadataCompletionFunction (Target);
3810+ return needsForeignMetadataCompletionFunction (IGM, Target);
38083811 }
38093812
38103813 void createMetadataCompletionFunction () {
@@ -3837,10 +3840,19 @@ namespace {
38373840 public:
38383841 ForeignClassMetadataBuilder (IRGenModule &IGM, ClassDecl *target,
38393842 ConstantStructBuilder &B)
3840- : ForeignMetadataBuilderBase(IGM, target, B) {}
3843+ : ForeignMetadataBuilderBase(IGM, target, B) {
3844+ if (IGM.getOptions ().LazyInitializeClassMetadata )
3845+ CanBeConstant = false ;
3846+ }
38413847
38423848 void emitInitializeMetadata (IRGenFunction &IGF, llvm::Value *metadata,
38433849 MetadataDependencyCollector *collector) {
3850+ if (!Target->hasSuperclass ()) {
3851+ assert (IGM.getOptions ().LazyInitializeClassMetadata &&
3852+ " should have superclass if not lazy initializing class metadata" );
3853+ return ;
3854+ }
3855+
38443856 // Emit a reference to the superclass.
38453857 auto superclass = IGF.emitAbstractTypeMetadataRef (
38463858 Target->getSuperclass ()->getCanonicalType ());
@@ -3858,6 +3870,24 @@ namespace {
38583870 // Visitor methods.
38593871
38603872 void addValueWitnessTable () {
3873+ // The runtime will fill in the default VWT during allocation for the
3874+ // foreign class metadata.
3875+ //
3876+ // As of Swift 5.1, the runtime will fill in a default VWT during
3877+ // allocation of foreign class metadata. We rely on this for correctness
3878+ // on COFF, where we can't necessarily reference the stanard VWT from the
3879+ // metadata candidate, but it is a good optimization everywhere.
3880+ //
3881+ // The default VWT uses ObjC-compatible reference counting if ObjC interop
3882+ // is enabled and Swift-compatible reference counting otherwise. That is
3883+ // currently always good enough for foreign classes, so we can
3884+ // unconditionally rely on the default VWT.
3885+ //
3886+ // FIXME: take advantage of this on other targets when targeting a
3887+ // sufficiently recent runtime.
3888+ if (IGM.getOptions ().LazyInitializeClassMetadata )
3889+ return B.addNullPointer (IGM.WitnessTablePtrTy );
3890+
38613891 // Without Objective-C interop, foreign classes must still use
38623892 // Swift native reference counting.
38633893 auto type = (IGM.ObjCInterop
0 commit comments