Skip to content

Commit f0dd884

Browse files
committed
Runtime: Fill in the value witness table of a class when doing singleton metadata initialization
On Windows the image format does not support cross-image absolute data symbol references. One case where we emit these is in class metadata, because the value witness table always points at the value witness table for Builtin.NativeObject, defined in the runtime. Instead, fill in the value witness table at runtime when doing singleton metadata initialization. Another change that will come later is to force use of singleton metadata initialization on Windows, even if the class is otherwise completely fixed.
1 parent 4af53c5 commit f0dd884

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,17 +2478,6 @@ namespace {
24782478
B.add(metadata);
24792479
}
24802480

2481-
/// The runtime provides a value witness table for Builtin.NativeObject.
2482-
void addValueWitnessTable() {
2483-
ClassDecl *cls = Target;
2484-
2485-
auto type = (cls->checkObjCAncestry() != ObjCClassKind::NonObjC
2486-
? IGM.Context.TheUnknownObjectType
2487-
: IGM.Context.TheNativeObjectType);
2488-
auto wtable = IGM.getAddrOfValueWitnessTable(type);
2489-
B.add(wtable);
2490-
}
2491-
24922481
void addDestructorFunction() {
24932482
if (auto ptr = getAddrOfDestructorFunction(IGM, Target)) {
24942483
B.add(*ptr);
@@ -2658,6 +2647,14 @@ namespace {
26582647
B.addInt(IGM.SizeTy, getClassFieldOffset(IGM, baseType, var).getValue());
26592648
}
26602649

2650+
void addValueWitnessTable() {
2651+
auto type = (Target->checkObjCAncestry() != ObjCClassKind::NonObjC
2652+
? IGM.Context.TheUnknownObjectType
2653+
: IGM.Context.TheNativeObjectType);
2654+
auto wtable = IGM.getAddrOfValueWitnessTable(type);
2655+
B.add(wtable);
2656+
}
2657+
26612658
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
26622659
llvm_unreachable("Fixed class metadata cannot have missing members");
26632660
}
@@ -2691,6 +2688,11 @@ namespace {
26912688
B.addInt(IGM.SizeTy, 0);
26922689
}
26932690

2691+
void addValueWitnessTable() {
2692+
// The runtime fills in the value witness table for us.
2693+
B.add(llvm::ConstantPointerNull::get(IGM.WitnessTablePtrTy));
2694+
}
2695+
26942696
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
26952697
for (unsigned i = 0,
26962698
e = placeholder->getNumberOfFieldOffsetVectorEntries();

stdlib/public/runtime/Metadata.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,29 @@ Metadata *TargetSingletonMetadataInitialization<InProcess>::allocate(
8989
auto *classDescription = cast<ClassDescriptor>(description);
9090
return swift_relocateClassMetadata(classDescription, pattern);
9191
}
92-
return IncompleteMetadata.get();
92+
93+
// Otherwise, we have a static template that we can initialize in-place.
94+
auto *metadata = IncompleteMetadata.get();
95+
96+
// If this is a class, we have to initialize the value witness table early
97+
// so that two-phase initialization can proceed as if this metadata is
98+
// complete for layout purposes when it appears as part of an aggregate type.
99+
if (auto *classMetadata = dyn_cast<ClassMetadata>(metadata)) {
100+
auto *fullMetadata = asFullMetadata(metadata);
101+
102+
// Begin by initializing the value witness table; everything else is
103+
// initialized by swift_initClassMetadata().
104+
#if SWIFT_OBJC_INTEROP
105+
fullMetadata->ValueWitnesses =
106+
(classMetadata->Flags & ClassFlags::UsesSwiftRefcounting)
107+
? &VALUE_WITNESS_SYM(Bo)
108+
: &VALUE_WITNESS_SYM(BO);
109+
#else
110+
fullMetadata->ValueWitnesses = &VALUE_WITNESS_SYM(Bo);
111+
#endif
112+
}
113+
114+
return metadata;
93115
}
94116

95117
/// Copy the generic arguments into place in a newly-allocated metadata.

test/IRGen/dllimport.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,12 @@ public func g() {
4242
// CHECK-NO-OPT-DAG: declare dllimport %swift.refcounted* @swift_retain(%swift.refcounted* returned)
4343
// CHECK-NO-OPT-DAG: @"$s9dllexport1pMp" = external dllimport global %swift.protocol
4444
// CHECK-NO-OPT-DAG: @"$sytN" = external dllimport global %swift.full_type
45-
// CHECK-NO-OPT-DAG: @"$sBoWV" = external dllimport global i8*
4645
// CHECK-NO-OPT-DAG: declare dllimport swiftcc i8* @"$s9dllexport2ciAA1cCvau"()
4746
// CHECK-NO-OPT-DAG: declare dllimport swiftcc %swift.refcounted* @"$s9dllexport1cCfd"(%T9dllexport1cC* swiftself)
4847
// CHECK-NO-OPT-DAG: declare dllimport swiftcc %swift.metadata_response @"$s9dllexport1cCMa"(i32)
4948
// CHECK-NO-OPT-DAG: declare dllimport void @swift_deallocClassInstance(%swift.refcounted*, i32, i32)
5049

5150
// CHECK-OPT-DAG: declare dllimport %swift.refcounted* @swift_retain(%swift.refcounted* returned) local_unnamed_addr
52-
// CHECK-OPT-DAG: @"$sBoWV" = external dllimport global i8*
5351
// CHECK-OPT-DAG: @"__imp_$s9dllexport1pMp" = external externally_initialized constant %swift.protocol*
5452
// CHECK-OPT-DAG: declare dllimport swiftcc i8* @"$s9dllexport2ciAA1cCvau"()
5553
// CHECK-OPT-DAG: declare dllimport swiftcc %swift.metadata_response @"$s9dllexport1cCMa"(i32)

test/IRGen/generic_vtable.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public class Concrete : Derived<Int> {
3838
//// Type metadata for 'Base' has a static vtable.
3939

4040
// CHECK-LABEL: @"$s14generic_vtable4BaseCMf" = internal global
41+
// -- destructor
42+
// CHECK-SAME: void (%T14generic_vtable4BaseC*)* @"$s14generic_vtable4BaseCfD"
43+
// -- value witness table
44+
// CHECK-SAME: i8** @"$sBoWV"
4145
// -- vtable entry for 'm1()'
4246
// CHECK-SAME: void (%T14generic_vtable4BaseC*)* @"$s14generic_vtable4BaseC2m1yyF"
4347
// -- vtable entry for 'm2()'
@@ -110,6 +114,10 @@ public class Concrete : Derived<Int> {
110114
//// Type metadata for 'Concrete' has a static vtable.
111115

112116
// CHECK-LABEL: @"$s14generic_vtable8ConcreteCMf" = internal global <{{.*}}> <{
117+
// -- destructor
118+
// CHECK-SAME: void (%T14generic_vtable8ConcreteC*)* @"$s14generic_vtable8ConcreteCfD",
119+
// -- value witness table is filled in at runtime
120+
// CHECK-SAME: i8** null,
113121
// -- nominal type descriptor
114122
// CHECK-SAME: @"$s14generic_vtable8ConcreteCMn",
115123
// -- vtable entry for 'm1()'

0 commit comments

Comments
 (0)