Skip to content

Commit e6285b2

Browse files
committed
SILOptimizer: handle begin_apply in escape analysis
Just treat begin_apply conservatively. It's probably not worth adding much complexity for begin_apply to the analysis as co-routines are often inlined anyway. Fixes a miscompile. https://bugs.swift.org/browse/SR-10444 rdar://problem/49755264
1 parent cfc03f8 commit e6285b2

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

lib/SILOptimizer/Analysis/EscapeAnalysis.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,9 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
12161216
int RecursionDepth) {
12171217
ConnectionGraph *ConGraph = &FInfo->Graph;
12181218
FullApplySite FAS = FullApplySite::isa(I);
1219-
if (FAS) {
1219+
if (FAS &&
1220+
// We currently don't support co-routines. In most cases co-routines will be inlined anyway.
1221+
!isa<BeginApplyInst>(I)) {
12201222
ArraySemanticsCall ASC(FAS.getInstruction());
12211223
switch (ASC.getKind()) {
12221224
case ArrayCallKind::kArrayPropsIsNativeTypeChecked:

test/SILOptimizer/escape_analysis.sil

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,3 +1477,41 @@ bb0:
14771477
return %7 : $()
14781478
}
14791479

1480+
sil hidden [transparent] @test_modifier : $@yield_once @convention(thin) (@guaranteed Y) -> @yields @inout X {
1481+
bb0(%0 : $Y):
1482+
%2 = ref_element_addr %0 : $Y, #Y.x
1483+
yield %2 : $*X, resume bb1, unwind bb2
1484+
1485+
bb1:
1486+
%6 = tuple ()
1487+
return %6 : $()
1488+
1489+
bb2:
1490+
unwind
1491+
}
1492+
1493+
// Currently escape analysis treats co-routines conservatively.
1494+
// Ideally there should be a link from %0 -> %2 -> %4. But for now %2 (the
1495+
// begin_apply result) is just marked as escaping.
1496+
1497+
// CHECK-LABEL: CG of call_coroutine
1498+
// CHECK: Val %0 Esc: G, Succ: (%0.1)
1499+
// CHECK: Con %0.1 Esc: G, Succ: (%0.2)
1500+
// CHECK: Con %0.2 Esc: G, Succ:
1501+
// CHECK: Val %2 Esc: G, Succ: (%2.1)
1502+
// CHECK: Con %2.1 Esc: G, Succ: %4
1503+
// CHECK: Val %4 Esc: G, Succ:
1504+
// CHECK: End
1505+
sil @call_coroutine : $@convention(thin) () -> () {
1506+
bb0:
1507+
%0 = alloc_ref $Y
1508+
%1 = function_ref @test_modifier : $@convention(thin) @yield_once (@guaranteed Y) -> (@yields @inout X)
1509+
(%2, %3) = begin_apply %1(%0) : $@yield_once @convention(thin) (@guaranteed Y) -> @yields @inout X
1510+
%4 = alloc_ref $X
1511+
store %4 to %2 : $*X
1512+
end_apply %3
1513+
strong_release %0 : $Y
1514+
%7 = tuple ()
1515+
return %7 : $()
1516+
}
1517+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -O %s -o %t/a.out
3+
// RUN: %target-run %t/a.out | %FileCheck %s
4+
5+
// REQUIRES: executable_test
6+
7+
// Check that the compiled code does not crash because of a wrong
8+
// stack-promoted array.
9+
// End-to-end test for https://bugs.swift.org/browse/SR-10444
10+
11+
public struct Beta {
12+
var gamma: [Int]
13+
}
14+
15+
class Delta {
16+
var epislon: Beta? = Beta(gamma: [])
17+
18+
func main() {
19+
for _ in 1...100 {
20+
crash()
21+
}
22+
}
23+
24+
func crash() {
25+
epislon?.gamma = [0]
26+
}
27+
}
28+
29+
func testit() {
30+
Delta().main()
31+
}
32+
33+
testit()
34+
35+
// CHECK: ok
36+
print("ok")
37+

0 commit comments

Comments
 (0)