Skip to content

Commit 52a1f4d

Browse files
committed
[LifetimeCompletion] Handle endAsyncLetLifetime.
Handle it like an `end_borrow`.
1 parent 901d30d commit 52a1f4d

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

include/swift/SIL/OwnershipUseVisitor.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ bool OwnershipUseVisitor<Impl>::visitInnerBorrowScopeEnd(Operand *borrowEnd) {
303303
// [nonescaping] def.
304304
return handleUsePoint(borrowEnd, UseLifetimeConstraint::NonLifetimeEnding);
305305
}
306+
case OperandOwnership::InstantaneousUse: {
307+
auto builtinUser = dyn_cast<BuiltinInst>(borrowEnd->getUser());
308+
if (builtinUser && builtinUser->getBuiltinKind() ==
309+
BuiltinValueKind::EndAsyncLetLifetime) {
310+
return handleUsePoint(borrowEnd,
311+
UseLifetimeConstraint::NonLifetimeEnding);
312+
}
313+
LLVM_FALLTHROUGH;
314+
}
306315
default:
307316
llvm_unreachable("expected borrow scope end");
308317
}

test/SILOptimizer/ossa_lifetime_completion.sil

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ public enum FakeOptional<T> {
1717
case some(T)
1818
}
1919

20+
sil @swift_asyncLet_finish : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
21+
sil @swift_asyncLet_get : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
22+
23+
protocol Error {}
24+
25+
enum Optional<Wrapped> {
26+
case none
27+
case some(Wrapped)
28+
}
29+
2030
// CHECK-LABEL: begin running test 1 of 1 on eagerConsumneOwnedArg: ossa-lifetime-completion with: @argument
2131
// CHECK-LABEL: OSSA lifetime completion: %0 = argument of bb0 : $C
2232
// CHECK: sil [ossa] @eagerConsumneOwnedArg : $@convention(thin) (@owned C) -> () {
@@ -461,3 +471,30 @@ right:
461471
end_borrow %c : $C
462472
unreachable
463473
}
474+
475+
// Nothing to check here--the output is the same as the input. Verify that
476+
// completing the lifetime of a value used by a startAsyncLetWithLocalBuffer
477+
// doesn't crash when visiting an endAsyncLetLifetime.
478+
sil [ossa] @async_let : $@convention(thin) @async () -> () {
479+
bb0:
480+
%result_addr = alloc_stack $()
481+
%result_ptr = address_to_pointer %result_addr : $*() to $Builtin.RawPointer
482+
%task_options = enum $Optional<Builtin.RawPointer>, #Optional.none!enumelt
483+
%callee_pa = partial_apply [callee_guaranteed] undef() : $@convention(thin) @async @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
484+
%callee_noescape = convert_escape_to_noescape [not_guaranteed] %callee_pa : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
485+
to $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
486+
specify_test "ossa-lifetime-completion %callee_noescape"
487+
%async_let = builtin "startAsyncLetWithLocalBuffer"<()>(
488+
%task_options : $Optional<Builtin.RawPointer>,
489+
%callee_noescape : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>,
490+
%result_ptr : $Builtin.RawPointer
491+
) : $Builtin.RawPointer
492+
%get = function_ref @swift_asyncLet_get : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
493+
apply %get(%async_let, %result_ptr) : $@convention(thin) @async (Builtin.RawPointer, Builtin.RawPointer) -> ()
494+
builtin "endAsyncLetLifetime"(%async_let : $Builtin.RawPointer) : $()
495+
destroy_value %callee_noescape : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
496+
destroy_value %callee_pa : $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
497+
%retval = load [trivial] %result_addr : $*()
498+
dealloc_stack %result_addr : $*()
499+
return %retval : $()
500+
}

0 commit comments

Comments
 (0)