Skip to content

Commit 0459985

Browse files
committed
Add begin_apply, abort_apply, and end_apply instructions to allow
yield_once coroutines to be executed.
1 parent aff4573 commit 0459985

File tree

18 files changed

+621
-61
lines changed

18 files changed

+621
-61
lines changed

docs/SIL.rst

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,10 @@ Currently, a coroutine may not have normal results.
604604

605605
Coroutine functions may be used in many of the same ways as normal
606606
function values. However, they cannot be called with the standard
607-
``apply`` or ``try_apply`` instructions.
607+
``apply`` or ``try_apply`` instructions. A non-throwing yield-once
608+
coroutine can be called with the ``begin_apply`` instruction. There
609+
is no support yet for calling a throwing yield-once coroutine or for
610+
calling a yield-many coroutine of any kind.
608611

609612
Coroutines may contain the special ``yield`` and ``unwind`` instructions.
610613

@@ -3137,6 +3140,102 @@ If the callee is generic, all of its generic parameters must be bound by the
31373140
given substitution list. The arguments and return value is
31383141
given with these generic substitutions applied.
31393142

3143+
begin_apply
3144+
```````````
3145+
::
3146+
3147+
sil-instruction ::= 'begin_apply' '[nothrow]'? sil-value
3148+
sil-apply-substitution-list?
3149+
'(' (sil-value (',' sil-value)*)? ')'
3150+
':' sil-type
3151+
3152+
(%anyAddr, %float, %token) = begin_apply %0() : $@yield_once () -> (@yields @inout %Any, @yields Float)
3153+
// %anyAddr : $*Any
3154+
// %float : $Float
3155+
// %token is a token
3156+
3157+
Transfers control to coroutine ``%0``, passing it the given arguments.
3158+
The rules for the application generally follow the rules for ``apply``,
3159+
except:
3160+
3161+
- the callee value must have a ``yield_once`` coroutine type,
3162+
3163+
- control returns to this function not when the coroutine performs a
3164+
``return``, but when it performs a ``yield`, and
3165+
3166+
- the instruction results are derived from the yields of the coroutine
3167+
instead of its normal results.
3168+
3169+
The final result of a ``begin_apply`` is a "token", a special value which
3170+
can only be used as the operand of an ``end_apply`` or ``abort_apply``
3171+
instruction. Before this second instruction is executed, the coroutine
3172+
is said to be "suspended", and the token represents a reference to its
3173+
suspended activation record.
3174+
3175+
The other results of the instruction correspond to the yields in the
3176+
coroutine type. In general, the rules of a yield are similar to the rules
3177+
for a parameter, interpreted as if the coroutine caller (the one
3178+
executing the ``begin_apply``) were being "called" by the ``yield``:
3179+
3180+
- If a yield has an indirect convention, the corresponding result will
3181+
have an address type; otherwise it has an object type. For example,
3182+
a result corresponding to an ``@in Any`` yield will have type ``$Any``.
3183+
3184+
- The convention attributes are the same as the parameter convention
3185+
attributes, interpreted as if the ``yield`` were the "call" and the
3186+
``begin_apply`` marked the entry to the "callee". For example,
3187+
an ``@in Any`` yield transferrs ownership of the ``Any`` value
3188+
reference from the coroutine to the caller, which must destroy
3189+
or move the value from that position before ending or aborting the
3190+
coroutine.
3191+
3192+
A ``begin_apply`` must be uniquely either ended or aborted before
3193+
exiting the function or looping to an earlier portion of the function.
3194+
3195+
When throwing coroutines are supported, there will need to be a
3196+
``try_begin_apply`` instruction.
3197+
3198+
abort_apply
3199+
```````````
3200+
::
3201+
3202+
sil-instruction ::= 'abort_apply' sil-value
3203+
3204+
abort_apply %token
3205+
3206+
Aborts the given coroutine activation, which is currently suspended at
3207+
a ``yield`` instruction. Transfers control to the coroutine and takes
3208+
the ``unwind`` path from the ``yield``. Control is transferred back
3209+
when the coroutine reaches an ``unwind`` instruction.
3210+
3211+
The operand must always be the token result of a ``begin_apply``
3212+
instruction, which is why it need not specify a type.
3213+
3214+
Throwing coroutines will not require a new instruction for aborting
3215+
a coroutine; a coroutine is not allowed to throw when it is being aborted.
3216+
3217+
end_apply
3218+
`````````
3219+
::
3220+
3221+
sil-instruction ::= 'end_apply' sil-value
3222+
3223+
end_apply %token
3224+
3225+
Ends the given coroutine activation, which is currently suspended at
3226+
a ``yield`` instruction. Transfers control to the coroutine and takes
3227+
the ``resume`` path from the ``yield``. Control is transferred back
3228+
when the coroutine reaches a ``return`` instruction.
3229+
3230+
The operand must always be the token result of a ``begin_apply``
3231+
instruction, which is why it need not specify a type.
3232+
3233+
``end_apply`` currently has no instruction results. If coroutines were
3234+
allowed to have normal results, they would be producted by ``end_apply``.
3235+
3236+
When throwing coroutines are supported, there will need to be a
3237+
``try_end_apply`` instruction.
3238+
31403239
partial_apply
31413240
`````````````
31423241
::

include/swift/SIL/SILBuilder.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,25 @@ class SILBuilder {
381381
SpecializationInfo));
382382
}
383383

384+
BeginApplyInst *createBeginApply(
385+
SILLocation Loc, SILValue Fn, SubstitutionList Subs,
386+
ArrayRef<SILValue> Args, bool isNonThrowing,
387+
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
388+
return insert(BeginApplyInst::create(getSILDebugLocation(Loc), Fn, Subs,
389+
Args, isNonThrowing, silConv, *F,
390+
OpenedArchetypes, SpecializationInfo));
391+
}
392+
393+
AbortApplyInst *createAbortApply(SILLocation loc, SILValue beginApply) {
394+
return insert(new (getModule()) AbortApplyInst(getSILDebugLocation(loc),
395+
beginApply));
396+
}
397+
398+
EndApplyInst *createEndApply(SILLocation loc, SILValue beginApply) {
399+
return insert(new (getModule()) EndApplyInst(getSILDebugLocation(loc),
400+
beginApply));
401+
}
402+
384403
BuiltinInst *createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy,
385404
SubstitutionList Subs,
386405
ArrayRef<SILValue> Args) {

include/swift/SIL/SILCloner.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,39 @@ SILCloner<ImplClass>::visitPartialApplyInst(PartialApplyInst *Inst) {
614614
getBuilder())));
615615
}
616616

617+
template<typename ImplClass>
618+
void
619+
SILCloner<ImplClass>::visitBeginApplyInst(BeginApplyInst *Inst) {
620+
auto Args = getOpValueArray<8>(Inst->getArguments());
621+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
622+
doPostProcess(Inst,
623+
getBuilder().createBeginApply(getOpLocation(Inst->getLoc()),
624+
getOpValue(Inst->getCallee()),
625+
getOpSubstitutions(Inst->getSubstitutions()),
626+
Args,
627+
Inst->isNonThrowing(),
628+
GenericSpecializationInformation::create(
629+
Inst, getBuilder())));
630+
}
631+
632+
template<typename ImplClass>
633+
void
634+
SILCloner<ImplClass>::visitAbortApplyInst(AbortApplyInst *Inst) {
635+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
636+
doPostProcess(Inst,
637+
getBuilder().createAbortApply(getOpLocation(Inst->getLoc()),
638+
getOpValue(Inst->getOperand())));
639+
}
640+
641+
template<typename ImplClass>
642+
void
643+
SILCloner<ImplClass>::visitEndApplyInst(EndApplyInst *Inst) {
644+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
645+
doPostProcess(Inst,
646+
getBuilder().createEndApply(getOpLocation(Inst->getLoc()),
647+
getOpValue(Inst->getOperand())));
648+
}
649+
617650
template<typename ImplClass>
618651
void
619652
SILCloner<ImplClass>::visitFunctionRefInst(FunctionRefInst *Inst) {

0 commit comments

Comments
 (0)