Skip to content

Commit af8e173

Browse files
authored
Merge pull request #6428 from swiftix/wip-sr-3034
[sil-dead-function-elimination] Do not remove bodies of transparent functions referenced from vtables and witness tables
2 parents 509db74 + d3b2336 commit af8e173

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,47 @@ class ExternalFunctionDefinitionsElimination : FunctionLivenessComputation {
460460

461461
/// ExternalFunctionDefinitionsElimination pass does not take functions
462462
/// reachable via vtables and witness_tables into account when computing
463-
/// a function liveness information.
463+
/// a function liveness information. The only exceptions are external
464+
/// transparent functions, because bodies of external transparent functions
465+
/// should never be removed.
464466
void findAnchorsInTables() override {
467+
// Check vtable methods.
468+
for (SILVTable &vTable : Module->getVTableList()) {
469+
for (auto &entry : vTable.getEntries()) {
470+
SILFunction *F = entry.second;
471+
if (F->isTransparent() && isAvailableExternally(F->getLinkage()))
472+
ensureAlive(F);
473+
}
474+
}
475+
476+
// Check witness methods.
477+
for (SILWitnessTable &WT : Module->getWitnessTableList()) {
478+
bool tableIsAlive = isVisibleExternally(WT.getConformance()->getProtocol());
479+
for (const SILWitnessTable::Entry &entry : WT.getEntries()) {
480+
if (entry.getKind() != SILWitnessTable::Method)
481+
continue;
482+
483+
auto methodWitness = entry.getMethodWitness();
484+
SILFunction *F = methodWitness.Witness;
485+
if (!F)
486+
continue;
487+
if (F->isTransparent() && isAvailableExternally(F->getLinkage()))
488+
ensureAlive(F);
489+
}
490+
}
491+
492+
// Check default witness methods.
493+
for (SILDefaultWitnessTable &WT : Module->getDefaultWitnessTableList()) {
494+
for (const SILDefaultWitnessTable::Entry &entry : WT.getEntries()) {
495+
if (!entry.isValid())
496+
continue;
497+
498+
SILFunction *F = entry.getWitness();
499+
if (F->isTransparent() && isAvailableExternally(F->getLinkage()))
500+
ensureAlive(F);
501+
}
502+
}
503+
465504
}
466505

467506
bool findAliveFunctions() {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -external-func-definition-elim %s | %FileCheck %s
2+
3+
// Check that public_external transparent methods referenced from vtables
4+
// and witness tables are not removed by ExternalFunctionDefinitionsElimination.
5+
6+
sil_stage canonical
7+
8+
import Builtin
9+
import Swift
10+
import SwiftShims
11+
12+
private class Base {
13+
init()
14+
func foo()
15+
}
16+
17+
private class Derived : Base {
18+
}
19+
20+
sil private @BaseInit : $@convention(method) (@owned Base) -> @owned Base {
21+
bb0(%4 : $Base):
22+
return %4 : $Base
23+
}
24+
25+
sil private @DerivedInit : $@convention(method) (@owned Derived) -> @owned Derived {
26+
bb0(%4 : $Derived):
27+
return %4 : $Derived
28+
}
29+
30+
sil public_external [transparent] @foo : $@convention(method) (@guaranteed Base) -> () {
31+
bb0(%0 : $Base):
32+
%2 = tuple ()
33+
return %2 : $()
34+
} // end sil function 'foo'
35+
36+
37+
sil_vtable Base {
38+
#Base.init!initializer.1: BaseInit
39+
#Base.foo!1: foo
40+
}
41+
42+
sil_vtable Derived {
43+
#Base.init!initializer.1: DerivedInit
44+
#Base.foo!1: foo
45+
}
46+
47+
// CHECK-LABEL: sil public_external [transparent] @foo
48+
// CHECK: end sil function 'foo'
49+
50+
// CHECK-LABEL: sil_vtable Base
51+
// CHECK-: BaseInit
52+
53+
// CHECK-LABEL: sil_vtable Derived
54+
// CHECK: DerivedInit

0 commit comments

Comments
 (0)