@@ -636,40 +636,92 @@ Coroutine Types
636
636
637
637
A coroutine is a function which can suspend itself and return control to
638
638
its caller without terminating the function. That is, it does not need to
639
- obey a strict stack discipline.
640
-
641
- SIL supports two kinds of coroutine: ``@yield_many `` and ``@yield_once ``.
642
- Either of these attributes may be written before a function type to
643
- indicate that it is a coroutine type.
644
-
645
- A coroutine type may declare any number of *yielded values *, which is to
639
+ obey a strict stack discipline. Different kinds of coroutines in SIL have
640
+ different representations, reflecting the different capabilities and
641
+ structural constraints of different language-level features:
642
+
643
+ Yielding Coroutines
644
+ ...................
645
+
646
+ Some kinds of coroutine have control flow that is tightly integrated with
647
+ their callers, and pass information back and forth between caller and callee
648
+ in a structured way. *Generalized accessors * and generators in Swift fit this
649
+ description: a ``read `` or ``modify `` accessor coroutine projects a single
650
+ value, yields ownership of that one value temporarily to the caller, and then
651
+ takes ownership back when resumed, allowing the coroutine to clean up resources
652
+ or otherwise react to mutations done by the caller. *Generators * similarly
653
+ yield a stream of values one at a time to their caller, temporarily yielding
654
+ ownership of each value in turn to the caller. The tight coupling of the
655
+ caller's control flow with these coroutines allows the caller to *borrow *
656
+ values produced by the coroutine, where a normal function return would need to
657
+ transfer ownership of its return value, since a normal function's context
658
+ ceases to exist and be able to maintain ownership of the value after it
659
+ returns.
660
+
661
+ To support these concepts, SIL supports two kinds of *yielding coroutine *:
662
+ ``@yield_many `` and ``@yield_once ``. Either of these attributes may be
663
+ written before a function type to indicate that it is a yielding coroutine type.
664
+
665
+ A yielding coroutine type may declare any number of *yielded values *, which is to
646
666
say, values which are provided to the caller at a yield point. Yielded
647
667
values are written in the result list of a function type, prefixed by
648
668
the ``@yields `` attribute. A yielded value may have a convention attribute,
649
669
taken from the set of parameter attributes and interpreted as if the yield
650
670
site were calling back to the calling function.
651
671
652
- Currently, a coroutine may not have normal results.
672
+ Currently, a yielding coroutine may not have normal results.
653
673
654
- Coroutine functions may be used in many of the same ways as normal
674
+ Yielding coroutine functions may be used in many of the same ways as normal
655
675
function values. However, they cannot be called with the standard
656
676
``apply `` or ``try_apply `` instructions. A non-throwing yield-once
657
677
coroutine can be called with the ``begin_apply `` instruction. There
658
678
is no support yet for calling a throwing yield-once coroutine or for
659
679
calling a yield-many coroutine of any kind.
660
680
661
- Coroutines may contain the special ``yield `` and ``unwind `` instructions.
681
+ Yielding coroutines may contain the special ``yield `` and ``unwind ``
682
+ instructions.
662
683
663
684
A ``@yield_many `` coroutine may yield as many times as it desires.
664
685
A ``@yield_once `` coroutine may yield exactly once before returning,
665
686
although it may also ``throw `` before reaching that point.
666
687
667
- This coroutine representation is well-suited to coroutines whose control
668
- flow is tightly integrated with their callers and which intend to pass
669
- information back and forth. This matches the needs of generalized
670
- accessor and generator features in Swift. It is not a particularly good
671
- match for ``async ``/``await ``-style features; a simpler representation
672
- would probably do fine for that.
688
+ Async Coroutines
689
+ ................
690
+
691
+ ``async `` coroutines are quite different from yielding coroutines.
692
+ Async coroutines are almost like threads in that they
693
+ have largely independent execution contexts, and do not generally directly
694
+ transfer values between each other without going through synchronization
695
+ abstractions. Unlike ``@yield_once `` or ``@yield_many `` coroutine functions, an
696
+ individual async function does not represent an entire coroutine unto itself,
697
+ but is an individual unit of code that may run inside an async coroutine.
698
+ Unlike preemptive threads, async functions have explicit *suspend points * where
699
+ they allow their coroutine's execution to be suspended so that a different
700
+ coroutine may run.
701
+
702
+ In SIL, a function type has the ``@async `` attribute to
703
+ indicate it may contain suspend points. Being ``@async `` is orthogonal to being
704
+ a yielding coroutine--the ``@async `` attribute can be applied
705
+ both to functions and to both kinds of yielding coroutine. ``@async `` functions
706
+ can only be called from other ``@async `` functions, but otherwise can be
707
+ invoked with the normal ``apply `` and ``try_apply `` instructions (or
708
+ ``begin_apply `` if they are yielding coroutines). An ``@async `` function may
709
+ only use the special ``yield `` and ``unwind `` instructions if it is
710
+ a yielding coroutine in addition to being async.
711
+
712
+ ``@async `` functions may
713
+ express primitive suspend points by using the ``begin_async_continuation[_addr] `` and
714
+ ``await_async_continuation `` instructions. ``begin_async_continuation[_addr] ``
715
+ creates a *continuation * value that can be used to resume the coroutine when it
716
+ suspends, feeding a value back into the currently-running function or causing
717
+ it to fail with an error when it resumes. The resulting continuation value can
718
+ then be passed into a completion handler, registered with an event loop, or
719
+ scheduled by some other mechanism. The ``await_continuation `` instruction
720
+ suspends execution of the coroutine until the continuation is invoked to resume
721
+ it. All continuation values must be used to resume the async coroutine exactly
722
+ once. It is undefined behavior to attempt to resume the same continuation more
723
+ than once. Failing to resume a continuation will leave the coroutine stuck in
724
+ the suspended state, leaking any memory or other resources it owns.
673
725
674
726
Properties of Types
675
727
```````````````````
@@ -2608,6 +2660,76 @@ undefined behavior if the global variable has already been initialized.
2608
2660
2609
2661
The type operand must be a lowered object type.
2610
2662
2663
+ begin_async_continuation
2664
+ ````````````````````````
2665
+
2666
+ ::
2667
+
2668
+ sil-instruction ::= 'begin_async_continuation' '[throws]'? sil-type
2669
+
2670
+ %0 = begin_async_continuation $T
2671
+ %0 = begin_async_continuation [throws] $U
2672
+
2673
+ Begins a suspension of an ``@async `` function. This instruction can only be
2674
+ used inside an ``@async `` function. The result of the instruction is an
2675
+ ``UnsafeContinuation<T> `` value, where ``T `` is the formal type argument to the
2676
+ instruction, or an ``UnsafeThrowingContinuation<T> `` if the instruction
2677
+ carries the ``[throws] `` attribute. ``T `` must be a loadable type.
2678
+ The continuation must be consumed by a ``await_async_continuation `` terminator
2679
+ on all paths. Between ``begin_async_continuation `` and
2680
+ ``await_async_continuation ``, the following restrictions apply:
2681
+
2682
+ - The function cannot ``return ``, ``throw ``, ``yield ``, or ``unwind ``.
2683
+ - There cannot be nested suspend points; namely, the function cannot call
2684
+ another ``@async `` function, nor can it initiate another suspend point with
2685
+ ``begin_async_continuation ``.
2686
+
2687
+ The function suspends execution when the matching ``await_async_continuation ``
2688
+ terminator is reached, and resumes execution when the continuation is resumed.
2689
+ The continuation resumption operation takes a value of type ``T `` which is
2690
+ passed back into the function when it resumes execution in the ``await_async_continuation `` instruction's
2691
+ ``resume `` successor block. If the instruction
2692
+ has the ``[throws] `` attribute, it can also be resumed in an error state, in
2693
+ which case the matching ``await_async_continuation `` instruction must also
2694
+ have an ``error `` successor.
2695
+
2696
+ Within the enclosing SIL function, the result continuation is consumed by the
2697
+ ``await_async_continuation ``, and cannot be referenced after the
2698
+ ``await_async_continuation `` executes. Dynamically, the continuation value must
2699
+ be resumed exactly once in the course of the program's execution; it is
2700
+ undefined behavior to resume the continuation more than once. Conversely,
2701
+ failing to resume the continuation will leave the suspended async coroutine
2702
+ hung in its suspended state, leaking any resources it may be holding.
2703
+
2704
+ begin_async_continuation_addr
2705
+ `````````````````````````````
2706
+
2707
+ ::
2708
+
2709
+ sil-instruction ::= 'begin_async_continuation_addr' '[throws]'? sil-type ',' sil-operand
2710
+
2711
+ %1 = begin_async_continuation_addr $T, %0 : $*T
2712
+ %1 = begin_async_continuation_addr [throws] $U, %0 : $*U
2713
+
2714
+ Begins a suspension of an ``@async `` function, like ``begin_async_continuation ``,
2715
+ while binding a specific memory location to the resulting continuation for
2716
+ receiving the value the continuation is resumed with. The operand must be an
2717
+ address whose type is the maximally-abstracted lowered type of the formal
2718
+ resume type. The memory must be uninitialized, and must remain valid until the
2719
+ matching ``await_async_continuation `` instruction(s) consuming the result
2720
+ continuation have executed. The behavior is otherwise the same as
2721
+ ``begin_async_continuation ``, and the same restrictions apply on code appearing
2722
+ between ``begin_async_continuation_addr `` and ``await_async_continuation `` as
2723
+ apply between ``begin_async_continuation `` and ``await_async_continuation ``.
2724
+ Additionally, the state of the memory referenced by the operand is indefinite
2725
+ between the execution of ``begin_async_continuation_addr `` and
2726
+ ``await_async_continuation ``, and it is undefined behavior to read or modify
2727
+ the memory during this time. After the ``await_async_continuation `` resumes
2728
+ normally to its ``resume `` successor, the memory referenced by the operand
2729
+ is initialized with the resume value, and that value is then owned by the
2730
+ current function. If ``await_async_continuation `` instead resumes to
2731
+ its ``error `` successor, then the memory remains uninitialized.
2732
+
2611
2733
dealloc_stack
2612
2734
`````````````
2613
2735
::
@@ -5870,7 +5992,7 @@ yield
5870
5992
sil-yield-values ::= '(' (sil-operand (',' sil-operand)*)? ')'
5871
5993
5872
5994
Temporarily suspends the current function and provides the given
5873
- values to the calling function. The current function must be a coroutine,
5995
+ values to the calling function. The current function must be a yielding coroutine,
5874
5996
and the yield values must match the yield types of the coroutine.
5875
5997
If the calling function resumes the coroutine normally, control passes to
5876
5998
the ``resume `` destination. If the calling function aborts the coroutine,
@@ -5898,7 +6020,7 @@ unwind
5898
6020
5899
6021
Exits the current function and returns control to the calling function,
5900
6022
completing an unwind from a ``yield ``. The current function must be a
5901
- coroutine.
6023
+ yielding coroutine.
5902
6024
5903
6025
``unwind `` is only permitted in blocks reachable from the ``unwind `` edges
5904
6026
of ``yield `` instructions.
@@ -6230,6 +6352,54 @@ destination (if it returns with ``throw``).
6230
6352
6231
6353
The rules on generic substitutions are identical to those of ``apply ``.
6232
6354
6355
+ await_async_continuation
6356
+ ````````````````````````
6357
+
6358
+ ::
6359
+
6360
+ sil-terminator ::= 'await_async_continuation' sil-value
6361
+ ',' 'resume' sil-identifier
6362
+ (',' 'error' sil-identifier)?
6363
+
6364
+ await_async_continuation %0 : $UnsafeContinuation<T>, resume bb1
6365
+ await_async_continuation %0 : $UnsafeThrowingContinuation<T>, resume bb1, error bb2
6366
+
6367
+ bb1(%1 : $T):
6368
+ bb2(%2 : $Error):
6369
+
6370
+ Suspends execution of an ``@async `` function until the continuation operation
6371
+ is resumed. The continuation must be the result of a
6372
+ ``begin_async_continuation `` or ``begin_async_continuation_addr ``
6373
+ instruction within the same function; see the documentation for
6374
+ ``begin_async_continuation `` for discussion of further constraints on the
6375
+ IR between ``begin_async_continuation[_addr] `` and ``await_async_continuation ``.
6376
+ This terminator can only appear inside an ``@async `` function. The
6377
+ instruction must always have a ``resume `` successor, but must have an
6378
+ ``error `` successor if and only if the operand is an
6379
+ ``UnsafeThrowingContinuation<T> ``.
6380
+
6381
+ If the operand is the result of a
6382
+ ``begin_async_continuation `` instruction, then the ``resume `` successor block
6383
+ must take an argument whose type is the maximally-abstracted lowered type
6384
+ of ``T ``, matching the type argument of the ``Unsafe[Throwing]Continuation<T> ``
6385
+ operand. The value of the ``resume `` argument is owned by the current
6386
+ function. If the operand is the result of a ``begin_async_continuation_addr ``
6387
+ instruction, then the ``resume `` successor block must *not * take an argument;
6388
+ the resume value will be written to the memory referenced by the operand to the
6389
+ ``begin_async_continuation_addr `` instruction, after which point the value in
6390
+ that memory becomes owned by the current function. With either variant,
6391
+ if the ``await_async_continuation `` instruction has an ``error `` successor block,
6392
+ the ``error `` block must take a single ``Error `` argument, and that argument
6393
+ is owned by the enclosing function. The memory referenced by a
6394
+ ``begin_async_continuation_addr `` instruction remains uninitialized when
6395
+ ``await_async_continuation `` resumes on the ``error `` successor.
6396
+
6397
+ It is possible for a continuation to be resumed before ``await_async_continuation ``.
6398
+ In this case, the resume operation returns immediately, and
6399
+ ``await_async_continuation `` immediately transfers control to its ``resume ``
6400
+ or ``error `` successor block, with the resume or error value that the
6401
+ continuation was resumed with.
6402
+
6233
6403
Differentiable Programming
6234
6404
~~~~~~~~~~~~~~~~~~~~~~~~~~
6235
6405
0 commit comments