@@ -636,40 +636,92 @@ Coroutine Types
636636
637637A coroutine is a function which can suspend itself and return control to
638638its 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
646666say, values which are provided to the caller at a yield point. Yielded
647667values are written in the result list of a function type, prefixed by
648668the ``@yields `` attribute. A yielded value may have a convention attribute,
649669taken from the set of parameter attributes and interpreted as if the yield
650670site were calling back to the calling function.
651671
652- Currently, a coroutine may not have normal results.
672+ Currently, a yielding coroutine may not have normal results.
653673
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
655675function values. However, they cannot be called with the standard
656676``apply `` or ``try_apply `` instructions. A non-throwing yield-once
657677coroutine can be called with the ``begin_apply `` instruction. There
658678is no support yet for calling a throwing yield-once coroutine or for
659679calling a yield-many coroutine of any kind.
660680
661- Coroutines may contain the special ``yield `` and ``unwind `` instructions.
681+ Yielding coroutines may contain the special ``yield `` and ``unwind ``
682+ instructions.
662683
663684A ``@yield_many `` coroutine may yield as many times as it desires.
664685A ``@yield_once `` coroutine may yield exactly once before returning,
665686although it may also ``throw `` before reaching that point.
666687
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.
673725
674726Properties of Types
675727```````````````````
@@ -2608,6 +2660,76 @@ undefined behavior if the global variable has already been initialized.
26082660
26092661The type operand must be a lowered object type.
26102662
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+
26112733dealloc_stack
26122734`````````````
26132735::
@@ -5870,7 +5992,7 @@ yield
58705992 sil-yield-values ::= '(' (sil-operand (',' sil-operand)*)? ')'
58715993
58725994Temporarily 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,
58745996and the yield values must match the yield types of the coroutine.
58755997If the calling function resumes the coroutine normally, control passes to
58765998the ``resume `` destination. If the calling function aborts the coroutine,
@@ -5898,7 +6020,7 @@ unwind
58986020
58996021Exits the current function and returns control to the calling function,
59006022completing an unwind from a ``yield ``. The current function must be a
5901- coroutine.
6023+ yielding coroutine.
59026024
59036025``unwind `` is only permitted in blocks reachable from the ``unwind `` edges
59046026of ``yield `` instructions.
@@ -6230,6 +6352,54 @@ destination (if it returns with ``throw``).
62306352
62316353The rules on generic substitutions are identical to those of ``apply ``.
62326354
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+
62336403Differentiable Programming
62346404~~~~~~~~~~~~~~~~~~~~~~~~~~
62356405
0 commit comments