Skip to content

Commit d4757d4

Browse files
authored
Merge pull request #22857 from compnerd/foreign-imports
IRGen: lazy initialize ForeignClassMetadata
2 parents 993347d + 3f829c2 commit d4757d4

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

stdlib/public/runtime/Metadata.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,6 +3668,17 @@ class ForeignMetadataCacheEntry
36683668
state = PrivateMetadataState::NonTransitiveComplete;
36693669
}
36703670
} else {
3671+
if (candidate->getValueWitnesses() == nullptr) {
3672+
assert(isa<ForeignClassMetadata>(candidate) &&
3673+
"cannot set default value witnesses for non-class foreign types");
3674+
// Fill in the default VWT if it was not set in the candidate at build
3675+
// time.
3676+
#if SWIFT_OBJC_INTEROP
3677+
candidate->setValueWitnesses(&VALUE_WITNESS_SYM(BO));
3678+
#else
3679+
candidate->setValueWitnesses(&VALUE_WITNESS_SYM(Bo));
3680+
#endif
3681+
}
36713682
state = inferStateForMetadata(candidate);
36723683
}
36733684

test/IRGen/cf.sil

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %{python} %utils/chex.py < %s > %t/cf.sil
3-
// RUN: %target-swift-frontend -enable-objc-interop -sdk %S/Inputs %t/cf.sil -emit-ir -import-cf-types | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize %t/cf.sil -DINT=i%target-ptrsize
3+
// RUN: %target-swift-frontend -enable-objc-interop -sdk %S/Inputs %t/cf.sil -emit-ir -import-cf-types | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize %t/cf.sil -DINT=i%target-ptrsize -check-prefix CHECK-%target-import-type -check-prefix CHECK-%target-import-type-%target-ptrsize
44

55
// REQUIRES: CPU=i386 || CPU=x86_64
66

@@ -9,7 +9,14 @@
99
// CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type
1010
// CHECK: [[OBJC:%objc_object]] = type
1111

12-
// CHECK: @"$sSo17CCRefrigeratorRefaN" = linkonce_odr hidden constant <{ {{.*}} }> <{ i8** @"$sBOWV", [[INT]] 515, {{.*}}"$sSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null }>
12+
// CHECK: @"$sSo17CCRefrigeratorRefaN" = linkonce_odr hidden
13+
// CHECK-DIRECT-SAME: constant
14+
// CHECK-INDIRECT-SAME: global
15+
// CHECK-SAME: <{ {{.*}} }> <{
16+
// -- value witness table
17+
// CHECK-DIRECT-SAME: i8** @"$sBOWV",
18+
// CHECK-INDIRECT-SAME: i8** null,
19+
// CHECK-SAME: [[INT]] 515, {{.*}}"$sSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null }>
1320

1421
// CHECK: [[MUTABLE_REFRIGERATOR_NAME:@.*]] = private constant [52 x i8] c"CCMutableRefrigerator\00NCCMutableRefrigeratorRef\00St\00\00"
1522

@@ -21,7 +28,10 @@
2128
// CHECK-64-SAME: @"$sSo24CCMutableRefrigeratorRefaMr"
2229

2330
// CHECK-64: @"$sSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
24-
// CHECK-64-SAME: i8** @"$sBOWV", i64 515, {{.*}}"$sSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
31+
// -- value witness table
32+
// CHECK-DIRECT-64-SAME: i8** @"$sBOWV",
33+
// CHECK-INDIRECT-64-SAME: i8** null,
34+
// CHECK-64-SAME: i64 515, {{.*}}"$sSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
2535

2636
sil_stage canonical
2737

0 commit comments

Comments
 (0)