Skip to content

Commit f9f3f53

Browse files
committed
[ownership] Add support for adding {end,abort}_apply to the regular user list of owned parameters passed as guaranteed parameters to a begin_apply.
This just follows automagically from the recent work that I did with introducing BorrowScopeIntroducingOperands. I confirmed locally that the negative tests do not fail as expected when visiting the destroys of the guaranteed parameters.
1 parent 59a57ed commit f9f3f53

File tree

3 files changed

+208
-0
lines changed

3 files changed

+208
-0
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ struct BorrowScopeOperandKind {
205205

206206
enum Kind : UnderlyingKindTy {
207207
BeginBorrow = UnderlyingKindTy(SILInstructionKind::BeginBorrowInst),
208+
BeginApply = UnderlyingKindTy(SILInstructionKind::BeginApplyInst),
208209
};
209210

210211
Kind value;
@@ -220,6 +221,8 @@ struct BorrowScopeOperandKind {
220221
return None;
221222
case SILInstructionKind::BeginBorrowInst:
222223
return BorrowScopeOperandKind(BeginBorrow);
224+
case SILInstructionKind::BeginApplyInst:
225+
return BorrowScopeOperandKind(BeginApply);
223226
}
224227
}
225228

@@ -255,6 +258,13 @@ struct BorrowScopeOperand {
255258
}
256259
}
257260
return;
261+
case BorrowScopeOperandKind::BeginApply: {
262+
auto *user = cast<BeginApplyInst>(op->getUser());
263+
for (auto *use : user->getTokenResult()->getUses()) {
264+
func(use);
265+
}
266+
return;
267+
}
258268
}
259269
llvm_unreachable("Covered switch isn't covered");
260270
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// RUN: %target-sil-opt -sil-ownership-verifier-enable-testing -enable-sil-verify-all=0 -o /dev/null 2>&1 %s | %FileCheck %s
2+
// REQUIRES: asserts
3+
4+
// This file tests that when we emit an error, it is a true negative. This is
5+
// done by parsing the emitted output from the ownership verifier.
6+
7+
import Builtin
8+
9+
10+
sil [ossa] @coroutine_callee : $@yield_once (@guaranteed Builtin.NativeObject) -> () {
11+
bb0(%0 : @guaranteed $Builtin.NativeObject):
12+
yield (), resume bb1, unwind bb2
13+
14+
bb1:
15+
%r = tuple ()
16+
return %r : $()
17+
18+
bb2:
19+
unwind
20+
}
21+
22+
// CHECK-LABEL: Function: 'destroy_value_before_end_borrow'
23+
// CHECK: Found use after free?!
24+
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
25+
// CHECK: Consuming User: destroy_value %0 : $Builtin.NativeObject
26+
// CHECK: Non Consuming User: end_borrow %1 : $Builtin.NativeObject
27+
// CHECK: Block: bb0
28+
sil [ossa] @destroy_value_before_end_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
29+
bb0(%0 : @owned $Builtin.NativeObject):
30+
%1 = begin_borrow %0 : $Builtin.NativeObject
31+
destroy_value %0 : $Builtin.NativeObject
32+
end_borrow %1 : $Builtin.NativeObject
33+
%9999 = tuple()
34+
return %9999 : $()
35+
}
36+
37+
// CHECK-LABEL: Function: 'destroy_value_before_end_borrow_coroutine'
38+
// CHECK: Found use after free?!
39+
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
40+
// CHECK: Consuming User: destroy_value %0 : $Builtin.NativeObject
41+
// CHECK: Non Consuming User: end_apply %2
42+
// CHECK: Block: bb0
43+
sil [ossa] @destroy_value_before_end_borrow_coroutine : $@convention(thin) (@owned Builtin.NativeObject) -> () {
44+
bb0(%0 : @owned $Builtin.NativeObject):
45+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
46+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
47+
destroy_value %0 : $Builtin.NativeObject
48+
end_apply %token
49+
%r = tuple ()
50+
return %r : $()
51+
}
52+
53+
// CHECK-LABEL: Function: 'destroy_value_before_end_borrow_coroutine_2'
54+
// CHECK: Found use after free?!
55+
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
56+
// CHECK: Consuming User: destroy_value %0 : $Builtin.NativeObject
57+
// CHECK: Non Consuming User: abort_apply %2
58+
// CHECK: Block: bb0
59+
sil [ossa] @destroy_value_before_end_borrow_coroutine_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
60+
bb0(%0 : @owned $Builtin.NativeObject):
61+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
62+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
63+
destroy_value %0 : $Builtin.NativeObject
64+
abort_apply %token
65+
%r = tuple ()
66+
return %r : $()
67+
}
68+
69+
// CHECK-LABEL: Function: 'destroy_value_before_end_borrow_coroutine_3'
70+
// CHECK: Found use after free?!
71+
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
72+
// CHECK: Consuming User: destroy_value %0 : $Builtin.NativeObject
73+
// CHECK: Non Consuming User: abort_apply %2
74+
// CHECK: Block: bb1
75+
76+
// CHECK-LABEL: Function: 'destroy_value_before_end_borrow_coroutine_3'
77+
// CHECK: Found use after free due to unvisited non lifetime ending uses?!
78+
// CHECK: Value: %0 = argument of bb0 : $Builtin.NativeObject
79+
// CHECK: Remaining Users:
80+
// CHECK: User: abort_apply %2
81+
// CHECK: Block: bb1
82+
83+
sil [ossa] @destroy_value_before_end_borrow_coroutine_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
84+
bb0(%0 : @owned $Builtin.NativeObject):
85+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
86+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
87+
cond_br undef, bb1, bb2
88+
89+
bb1:
90+
destroy_value %0 : $Builtin.NativeObject
91+
abort_apply %token
92+
br bb3
93+
94+
bb2:
95+
end_apply %token
96+
destroy_value %0 : $Builtin.NativeObject
97+
br bb3
98+
99+
bb3:
100+
%r = tuple ()
101+
return %r : $()
102+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all=0 -o /dev/null 2>&1 %s
2+
3+
// REQUIRES: asserts
4+
5+
// This file has patterns in it that should not trigger the ownership verifier
6+
// so are considered positive checker patterns.
7+
8+
import Builtin
9+
10+
sil [ossa] @destroy_value_before_end_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
11+
bb0(%0 : @owned $Builtin.NativeObject):
12+
%1 = begin_borrow %0 : $Builtin.NativeObject
13+
end_borrow %1 : $Builtin.NativeObject
14+
destroy_value %0 : $Builtin.NativeObject
15+
%9999 = tuple()
16+
return %9999 : $()
17+
}
18+
19+
sil [ossa] @coroutine_callee : $@yield_once (@guaranteed Builtin.NativeObject) -> () {
20+
bb0(%0 : @guaranteed $Builtin.NativeObject):
21+
yield (), resume bb1, unwind bb2
22+
23+
bb1:
24+
%r = tuple ()
25+
return %r : $()
26+
27+
bb2:
28+
unwind
29+
}
30+
31+
sil [ossa] @destroy_value_before_end_borrow_coroutine : $@convention(thin) (@owned Builtin.NativeObject) -> () {
32+
bb0(%0 : @owned $Builtin.NativeObject):
33+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
34+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
35+
end_apply %token
36+
destroy_value %0 : $Builtin.NativeObject
37+
%r = tuple ()
38+
return %r : $()
39+
}
40+
41+
sil [ossa] @destroy_value_before_end_borrow_coroutine_1a : $@convention(thin) (@owned Builtin.NativeObject) -> () {
42+
bb0(%0 : @owned $Builtin.NativeObject):
43+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
44+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
45+
end_apply %token
46+
br bb1
47+
48+
bb1:
49+
destroy_value %0 : $Builtin.NativeObject
50+
%r = tuple ()
51+
return %r : $()
52+
}
53+
54+
sil [ossa] @destroy_value_before_end_borrow_coroutine_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
55+
bb0(%0 : @owned $Builtin.NativeObject):
56+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
57+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
58+
abort_apply %token
59+
destroy_value %0 : $Builtin.NativeObject
60+
%r = tuple ()
61+
return %r : $()
62+
}
63+
64+
sil [ossa] @destroy_value_before_end_borrow_coroutine_2b : $@convention(thin) (@owned Builtin.NativeObject) -> () {
65+
bb0(%0 : @owned $Builtin.NativeObject):
66+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
67+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
68+
abort_apply %token
69+
br bb1
70+
71+
bb1:
72+
destroy_value %0 : $Builtin.NativeObject
73+
%r = tuple ()
74+
return %r : $()
75+
}
76+
77+
sil [ossa] @positive_destroy_value_before_end_borrow_coroutine_3 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
78+
bb0(%0 : @owned $Builtin.NativeObject):
79+
%coro = function_ref @coroutine_callee : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
80+
%token = begin_apply %coro(%0) : $@yield_once @convention(thin) (@guaranteed Builtin.NativeObject) -> ()
81+
cond_br undef, bb1, bb2
82+
83+
bb1:
84+
abort_apply %token
85+
destroy_value %0 : $Builtin.NativeObject
86+
br bb3
87+
88+
bb2:
89+
end_apply %token
90+
destroy_value %0 : $Builtin.NativeObject
91+
br bb3
92+
93+
bb3:
94+
%r = tuple ()
95+
return %r : $()
96+
}

0 commit comments

Comments
 (0)