Skip to content

Commit 99d43a2

Browse files
authored
Merge pull request #5031 from eeckstein/fix-linker-error-3.0
Always ensure that we generate code for referenced transparent functions.
2 parents 221417b + a6c1e44 commit 99d43a2

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,30 @@ class ExternalFunctionDefinitionsElimination : FunctionLivenessComputation {
468468
/// Therefore there is no need for a liveness computation.
469469
/// The next line can be just replaced by:
470470
/// return false;
471+
472+
// Keep all transparent functions alive. This is important because we have
473+
// to generate code for transparent functions.
474+
// Here we handle the special case if a transparent function is referenced
475+
// from a non-externally-available function (i.e. a function for which we
476+
// generate code). And those function is only reachable through a
477+
// vtable/witness-table. In such a case we would not visit the transparent
478+
// function in findAliveFunctions() because we don't consider vtables/
479+
// witness-tables as anchors.
480+
for (SILFunction &F : *Module) {
481+
if (isAvailableExternally(F.getLinkage()))
482+
continue;
483+
484+
for (SILBasicBlock &BB : F) {
485+
for (SILInstruction &I : BB) {
486+
if (auto *FRI = dyn_cast<FunctionRefInst>(&I)) {
487+
SILFunction *RefF = FRI->getReferencedFunction();
488+
if (RefF->isTransparent() && RefF->isFragile())
489+
ensureAlive(RefF);
490+
}
491+
}
492+
}
493+
}
494+
471495
return FunctionLivenessComputation::findAliveFunctions();
472496
}
473497

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -external-func-definition-elim | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
import SwiftShims
8+
9+
10+
public class X {
11+
func testit() -> () -> ()
12+
deinit
13+
init()
14+
}
15+
16+
// Check if we keep the body of the externally available transparent function.
17+
18+
// CHECK-LABEL: sil public_external [transparent] [fragile] @imported_transparent_func : $@convention(thin) () -> () {
19+
sil public_external [transparent] [fragile] @imported_transparent_func : $@convention(thin) () -> () {
20+
bb0:
21+
%r = tuple ()
22+
return %r : $()
23+
}
24+
25+
26+
sil private @_TFC4test1X6testitfT_FT_T_ : $@convention(method) (@guaranteed X) -> @owned @callee_owned () -> () {
27+
bb0(%0 : $X):
28+
%6 = function_ref @imported_transparent_func : $@convention(thin) () -> ()
29+
%7 = thin_to_thick_function %6 : $@convention(thin) () -> () to $@callee_owned () -> ()
30+
return %7 : $@callee_owned () -> ()
31+
}
32+
33+
sil @_TFC4test1XD : $@convention(method) (@owned X) -> ()
34+
35+
sil_vtable X {
36+
#X.testit!1: _TFC4test1X6testitfT_FT_T_
37+
#X.deinit!deallocator: _TFC4test1XD
38+
}
39+

0 commit comments

Comments
 (0)