Skip to content

Commit f1bce6d

Browse files
authored
Merge pull request #21476 from slavapestov/sil-witness-table-cleanup
Clean up SIL witness table deserialization
2 parents 117dc27 + 983e077 commit f1bce6d

File tree

11 files changed

+48
-87
lines changed

11 files changed

+48
-87
lines changed

include/swift/SIL/SILModule.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,11 +570,6 @@ class SILModule {
570570
/// hierarchy of \p Class.
571571
SILFunction *lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member);
572572

573-
// Given a protocol conformance, attempt to create a witness table declaration
574-
// for it.
575-
SILWitnessTable *
576-
createWitnessTableDeclaration(ProtocolConformance *C, SILLinkage linkage);
577-
578573
// Given a protocol, attempt to create a default witness table declaration
579574
// for it.
580575
SILDefaultWitnessTable *

lib/IRGen/IRGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) {
769769
}
770770

771771
void IRGenerator::addLazyWitnessTable(const ProtocolConformance *Conf) {
772-
if (SILWitnessTable *wt = SIL.lookUpWitnessTable(Conf)) {
772+
if (auto *wt = SIL.lookUpWitnessTable(Conf, /*deserializeLazily=*/false)) {
773773
// Add it to the queue if it hasn't already been put there.
774774
if (canEmitWitnessTableLazily(wt) &&
775775
LazilyEmittedWitnessTables.insert(wt).second) {

lib/ParseSIL/ParseSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6184,6 +6184,8 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) {
61846184

61856185
if (!wt)
61866186
wt = SILWitnessTable::create(M, *Linkage, theConformance);
6187+
else
6188+
wt->setLinkage(*Linkage);
61876189
wt->convertToDefinition(witnessEntries, conditionalConformances,
61886190
isSerialized);
61896191
BodyScope.reset();

lib/SIL/Linker.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ static bool mustDeserializeProtocolConformance(SILModule &M,
200200

201201
void SILLinkerVisitor::visitProtocolConformance(
202202
ProtocolConformanceRef ref, const Optional<SILDeclRef> &Member) {
203-
// If an abstract protocol conformance was passed in, just return false.
203+
// If an abstract protocol conformance was passed in, do nothing.
204204
if (ref.isAbstract())
205205
return;
206206

@@ -211,31 +211,16 @@ void SILLinkerVisitor::visitProtocolConformance(
211211

212212
if (!VisitedConformances.insert(C).second)
213213
return;
214-
215-
SILWitnessTable *WT = Mod.lookUpWitnessTable(C, true);
216-
217-
// If we don't find any witness table for the conformance, bail and return
218-
// false.
219-
if (!WT) {
220-
Mod.createWitnessTableDeclaration(
221-
C, getLinkageForProtocolConformance(
222-
C->getRootNormalConformance(), NotForDefinition));
223-
224-
// Adding the declaration may allow us to now deserialize the body.
225-
// Force the body if we must deserialize this witness table.
226-
if (mustDeserialize) {
227-
WT = Mod.lookUpWitnessTable(C, true);
228-
assert(WT && WT->isDefinition()
229-
&& "unable to deserialize witness table when we must?!");
230-
} else {
231-
return;
232-
}
233-
}
214+
215+
auto *WT = Mod.lookUpWitnessTable(C, mustDeserialize);
234216

235217
// If the looked up witness table is a declaration, there is nothing we can
236-
// do here. Just bail and return false.
237-
if (WT->isDeclaration())
218+
// do here.
219+
if (WT == nullptr || WT->isDeclaration()) {
220+
assert(!mustDeserialize &&
221+
"unable to deserialize witness table when we must?!");
238222
return;
223+
}
239224

240225
auto maybeVisitRelatedConformance = [&](ProtocolConformanceRef c) {
241226
// Formally all conformances referenced by a used conformance are used.

lib/SIL/SILInstructions.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -312,16 +312,6 @@ VarDecl *DebugValueAddrInst::getDecl() const {
312312
return getLoc().getAsASTNode<VarDecl>();
313313
}
314314

315-
static void declareWitnessTable(SILModule &Mod,
316-
ProtocolConformanceRef conformanceRef) {
317-
if (conformanceRef.isAbstract()) return;
318-
auto C = conformanceRef.getConcrete();
319-
if (!Mod.lookUpWitnessTable(C, false))
320-
Mod.createWitnessTableDeclaration(C,
321-
getLinkageForProtocolConformance(C->getRootNormalConformance(),
322-
NotForDefinition));
323-
}
324-
325315
AllocExistentialBoxInst *AllocExistentialBoxInst::create(
326316
SILDebugLocation Loc, SILType ExistentialType, CanType ConcreteType,
327317
ArrayRef<ProtocolConformanceRef> Conformances,
@@ -333,8 +323,6 @@ AllocExistentialBoxInst *AllocExistentialBoxInst::create(
333323
SILModule &Mod = F->getModule();
334324
auto Size = totalSizeToAlloc<swift::Operand>(TypeDependentOperands.size());
335325
auto Buffer = Mod.allocateInst(Size, alignof(AllocExistentialBoxInst));
336-
for (ProtocolConformanceRef C : Conformances)
337-
declareWitnessTable(Mod, C);
338326
return ::new (Buffer) AllocExistentialBoxInst(Loc,
339327
ExistentialType,
340328
ConcreteType,
@@ -1633,7 +1621,6 @@ WitnessMethodInst::create(SILDebugLocation Loc, CanType LookupType,
16331621
auto Size = totalSizeToAlloc<swift::Operand>(TypeDependentOperands.size());
16341622
auto Buffer = Mod.allocateInst(Size, alignof(WitnessMethodInst));
16351623

1636-
declareWitnessTable(Mod, Conformance);
16371624
return ::new (Buffer) WitnessMethodInst(Loc, LookupType, Conformance, Member,
16381625
Ty, TypeDependentOperands);
16391626
}
@@ -1667,8 +1654,6 @@ InitExistentialAddrInst *InitExistentialAddrInst::create(
16671654
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
16681655
void *Buffer = Mod.allocateInst(size,
16691656
alignof(InitExistentialAddrInst));
1670-
for (ProtocolConformanceRef C : Conformances)
1671-
declareWitnessTable(Mod, C);
16721657
return ::new (Buffer) InitExistentialAddrInst(Loc, Existential,
16731658
TypeDependentOperands,
16741659
ConcreteType,
@@ -1688,9 +1673,6 @@ InitExistentialValueInst *InitExistentialValueInst::create(
16881673
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
16891674

16901675
void *Buffer = Mod.allocateInst(size, alignof(InitExistentialRefInst));
1691-
for (ProtocolConformanceRef C : Conformances)
1692-
declareWitnessTable(Mod, C);
1693-
16941676
return ::new (Buffer)
16951677
InitExistentialValueInst(Loc, ExistentialType, ConcreteType, Instance,
16961678
TypeDependentOperands, Conformances);
@@ -1711,9 +1693,6 @@ InitExistentialRefInst::create(SILDebugLocation Loc, SILType ExistentialType,
17111693

17121694
void *Buffer = Mod.allocateInst(size,
17131695
alignof(InitExistentialRefInst));
1714-
for (ProtocolConformanceRef C : Conformances)
1715-
declareWitnessTable(Mod, C);
1716-
17171696
return ::new (Buffer) InitExistentialRefInst(Loc, ExistentialType,
17181697
ConcreteType,
17191698
Instance,
@@ -1746,9 +1725,6 @@ InitExistentialMetatypeInst *InitExistentialMetatypeInst::create(
17461725
1 + TypeDependentOperands.size(), conformances.size());
17471726

17481727
void *buffer = M.allocateInst(size, alignof(InitExistentialMetatypeInst));
1749-
for (ProtocolConformanceRef conformance : conformances)
1750-
declareWitnessTable(M, conformance);
1751-
17521728
return ::new (buffer) InitExistentialMetatypeInst(
17531729
Loc, existentialMetatypeType, metatype,
17541730
TypeDependentOperands, conformances);

lib/SIL/SILModule.cpp

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -143,19 +143,6 @@ void SILModule::deallocateInst(SILInstruction *I) {
143143
AlignedFree(I);
144144
}
145145

146-
SILWitnessTable *
147-
SILModule::createWitnessTableDeclaration(ProtocolConformance *C,
148-
SILLinkage linkage) {
149-
// If we are passed in a null conformance (a valid value), just return nullptr
150-
// since we cannot map a witness table to it.
151-
if (!C)
152-
return nullptr;
153-
154-
// Extract the root conformance.
155-
auto rootC = C->getRootConformance();
156-
return SILWitnessTable::create(*this, linkage, rootC);
157-
}
158-
159146
SILWitnessTable *
160147
SILModule::lookUpWitnessTable(ProtocolConformanceRef C,
161148
bool deserializeLazily) {
@@ -172,6 +159,8 @@ SILModule::lookUpWitnessTable(const ProtocolConformance *C,
172159
bool deserializeLazily) {
173160
assert(C && "null conformance passed to lookUpWitnessTable");
174161

162+
SILWitnessTable *wtable;
163+
175164
auto rootC = C->getRootConformance();
176165
// Attempt to lookup the witness table from the table.
177166
auto found = WitnessTableMap.find(rootC);
@@ -189,16 +178,24 @@ SILModule::lookUpWitnessTable(const ProtocolConformance *C,
189178
"Found witness table that is not"
190179
" in the witness table lookup cache.");
191180
#endif
192-
return nullptr;
193-
}
194181

195-
SILWitnessTable *wtable = found->second;
196-
assert(wtable != nullptr && "Should never map a conformance to a null witness"
197-
" table.");
182+
// If we don't have a witness table and we're not going to try
183+
// deserializing it, do not create a declaration.
184+
if (!deserializeLazily)
185+
return nullptr;
198186

199-
// If we have a definition, return it.
200-
if (wtable->isDefinition())
201-
return wtable;
187+
auto linkage = getLinkageForProtocolConformance(rootC, NotForDefinition);
188+
wtable = SILWitnessTable::create(*this, linkage,
189+
const_cast<RootProtocolConformance *>(rootC));
190+
} else {
191+
wtable = found->second;
192+
assert(wtable != nullptr && "Should never map a conformance to a null witness"
193+
" table.");
194+
195+
// If we have a definition, return it.
196+
if (wtable->isDefinition())
197+
return wtable;
198+
}
202199

203200
// If the module is at or past the Lowered stage, then we can't do any
204201
// further deserialization, since pre-IRGen SIL lowering changes the types

lib/SIL/SILVerifier.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,8 +2493,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
24932493
auto conformance = AMI->getConformance().getConcrete();
24942494
require(conformance->getType()->isEqual(AMI->getLookupType()),
24952495
"concrete type lookup requires conformance that matches type");
2496-
require(AMI->getModule().lookUpWitnessTable(conformance, false),
2497-
"Could not find witness table for conformance");
24982496
}
24992497

25002498
require(AMI->getMember().requiresNewWitnessTableEntry(),
@@ -3204,13 +3202,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
32043202
require(conformances[i].getRequirement() == protocols[i]->getDecl(),
32053203
"init_existential instruction must have conformances in "
32063204
"proper order");
3207-
3208-
if (conformances[i].isConcrete()) {
3209-
auto conformance = conformances[i].getConcrete();
3210-
require(F.getModule().lookUpWitnessTable(conformance, false),
3211-
"Could not find witness table for conformance.");
3212-
3213-
}
32143205
}
32153206
}
32163207

test/IRGen/existential_metatypes.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ bb3:
109109
return %9 : $()
110110
}
111111

112-
sil_witness_table Int: Kindable module existential_metatypes {
112+
sil_witness_table public_external Int: Kindable module existential_metatypes {
113113
method #Kindable.kind!getter.1: @int_kind_getter_witness
114114
}
115115

116-
sil_witness_table Float: Kindable module existential_metatypes {
116+
sil_witness_table public_external Float: Kindable module existential_metatypes {
117117
method #Kindable.kind!getter.1: @float_kind_getter_witness
118118
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-sil-opt %s -module-name=witness_table_redeclare | %target-sil-opt -module-name=witness_table_redeclare | %FileCheck %s
2+
3+
protocol P {}
4+
5+
struct S : P {}
6+
7+
sil_witness_table S: P module witness_table_redeclare
8+
9+
sil_witness_table S: P module witness_table_redeclare {}
10+
11+
// CHECK-LABEL: sil_witness_table S: P module witness_table_redeclare {
12+
// CHECK-NEXT: }

test/SIL/Serialization/Inputs/init_existential_inst_deserializes_witness_tables_input.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public struct X : P {
1313
public init() {}
1414
}
1515

16+
@inlinable
1617
public func whatShouldIDo(_ p : P) {
1718
p.doSomething()
1819
}

test/SILOptimizer/dead_witness_module.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
// DeadFunctionElimination may not remove a method from a witness table which
66
// is imported from another module.
77

8+
// FIXME: Ever since @usableFromInline began to be enforced, this test did not
9+
// test anything useful, and now the witness table is never deserialized at all.
10+
811
import TestModule
912

1013
testit(MyStruct())
1114

12-
// CHECK: sil_witness_table public_external MyStruct: Proto module TestModule
13-
// CHECK-NEXT: method #Proto.confx!1: {{.*}} : @$s{{.*}}confx{{.*}}FTW
15+
// CHECK-NOT: sil_witness_table MyStruct: Proto module TestModule

0 commit comments

Comments
 (0)