Skip to content

Commit 815d82c

Browse files
authored
Merge pull request #12894 from rjmccall/begin_apply
2 parents 8f63e6c + 0459985 commit 815d82c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+893
-165
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ Types
317317
type ::= 'BO' // Builtin.UnknownObject
318318
type ::= 'Bo' // Builtin.NativeObject
319319
type ::= 'Bp' // Builtin.RawPointer
320+
type ::= 'Bt' // Builtin.SILToken
320321
type ::= type 'Bv' NATURAL '_' // Builtin.Vec<n>x<type>
321322
type ::= 'Bw' // Builtin.Word
322323
type ::= function-signature 'c' // function type

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/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ class ASTContext {
573573
const CanType TheUnknownObjectType; /// Builtin.UnknownObject
574574
const CanType TheRawPointerType; /// Builtin.RawPointer
575575
const CanType TheUnsafeValueBufferType; /// Builtin.UnsafeValueBuffer
576+
const CanType TheSILTokenType; /// Builtin.SILToken
576577

577578
const CanType TheIEEE32Type; /// 32-bit IEEE floating point
578579
const CanType TheIEEE64Type; /// 64-bit IEEE floating point

include/swift/AST/TypeMatcher.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class TypeMatcher {
109109
TRIVIAL_CASE(BuiltinUnknownObjectType)
110110
TRIVIAL_CASE(BuiltinUnsafeValueBufferType)
111111
TRIVIAL_CASE(BuiltinVectorType)
112+
TRIVIAL_CASE(SILTokenType)
112113

113114
bool visitTupleType(CanTupleType firstTuple, Type secondType,
114115
Type sugaredFirstType) {

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ ABSTRACT_TYPE(AnyFunction, Type)
126126
ARTIFICIAL_TYPE(SILFunction, Type)
127127
ARTIFICIAL_TYPE(SILBlockStorage, Type)
128128
ARTIFICIAL_TYPE(SILBox, Type)
129+
ARTIFICIAL_TYPE(SILToken, Type)
129130
ABSTRACT_SUGARED_TYPE(SyntaxSugar, Type)
130131
SUGARED_TYPE(ArraySlice, SyntaxSugarType)
131132
SUGARED_TYPE(Optional, SyntaxSugarType)

include/swift/AST/Types.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3797,7 +3797,23 @@ class SILBlockStorageType : public TypeBase {
37973797
}
37983798
};
37993799
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBlockStorageType, Type)
3800-
3800+
3801+
/// A singleton 'token' type, which establishes a formal dependency
3802+
/// between two SIL nodes. A token 'value' cannot be abstracted in
3803+
/// SIL: it cannot be returned, yielded, or passed as a function or
3804+
/// block argument.
3805+
class SILTokenType final : public TypeBase {
3806+
friend class ASTContext;
3807+
SILTokenType(const ASTContext &C)
3808+
: TypeBase(TypeKind::SILToken, &C, RecursiveTypeProperties()) {}
3809+
public:
3810+
// The singleton instance of this type is ASTContext::TheSILTokenType.
3811+
3812+
static bool classof(const TypeBase *T) {
3813+
return T->getKind() == TypeKind::SILToken;
3814+
}
3815+
};
3816+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILTokenType, Type)
38013817

38023818
/// A type with a special syntax that is always sugar for a library type.
38033819
///

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)