@@ -205,18 +205,21 @@ static void emitMetadataCompletionFunction(IRGenModule &IGM,
205
205
IGF.Builder .CreateRet (returnValue);
206
206
}
207
207
208
- static bool needsForeignMetadataCompletionFunction (StructDecl *decl) {
208
+ static bool needsForeignMetadataCompletionFunction (IRGenModule &IGM,
209
+ StructDecl *decl) {
209
210
// Currently, foreign structs never need a completion function.
210
211
return false ;
211
212
}
212
213
213
- static bool needsForeignMetadataCompletionFunction (EnumDecl *decl) {
214
+ static bool needsForeignMetadataCompletionFunction (IRGenModule &IGM,
215
+ EnumDecl *decl) {
214
216
// Currently, foreign enums never need a completion function.
215
217
return false ;
216
218
}
217
219
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 ();
220
223
}
221
224
222
225
/* ****************************************************************************/
@@ -1171,7 +1174,7 @@ namespace {
1171
1174
}
1172
1175
1173
1176
bool needsForeignMetadataCompletionFunction () {
1174
- return ::needsForeignMetadataCompletionFunction (Type);
1177
+ return ::needsForeignMetadataCompletionFunction (IGM, Type);
1175
1178
}
1176
1179
1177
1180
// / Add an SingletonMetadataInitialization structure to the descriptor.
@@ -3804,7 +3807,7 @@ namespace {
3804
3807
}
3805
3808
3806
3809
bool needsMetadataCompletionFunction () {
3807
- return needsForeignMetadataCompletionFunction (Target);
3810
+ return needsForeignMetadataCompletionFunction (IGM, Target);
3808
3811
}
3809
3812
3810
3813
void createMetadataCompletionFunction () {
@@ -3837,10 +3840,19 @@ namespace {
3837
3840
public:
3838
3841
ForeignClassMetadataBuilder (IRGenModule &IGM, ClassDecl *target,
3839
3842
ConstantStructBuilder &B)
3840
- : ForeignMetadataBuilderBase(IGM, target, B) {}
3843
+ : ForeignMetadataBuilderBase(IGM, target, B) {
3844
+ if (IGM.getOptions ().LazyInitializeClassMetadata )
3845
+ CanBeConstant = false ;
3846
+ }
3841
3847
3842
3848
void emitInitializeMetadata (IRGenFunction &IGF, llvm::Value *metadata,
3843
3849
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
+
3844
3856
// Emit a reference to the superclass.
3845
3857
auto superclass = IGF.emitAbstractTypeMetadataRef (
3846
3858
Target->getSuperclass ()->getCanonicalType ());
@@ -3858,6 +3870,24 @@ namespace {
3858
3870
// Visitor methods.
3859
3871
3860
3872
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
+
3861
3891
// Without Objective-C interop, foreign classes must still use
3862
3892
// Swift native reference counting.
3863
3893
auto type = (IGM.ObjCInterop
0 commit comments