@@ -517,11 +517,11 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
517
517
fd->getResultInterfaceType (), fd->hasThrows (), fd->getThrowsLoc ());
518
518
prepareEpilog (true , fd->hasThrows (), CleanupLocation (fd));
519
519
520
- if (fd->isAsyncHandler ()) {
521
- // Async handlers are need to have their bodies emitted into a
522
- // detached task .
523
- // FIXME: Actually implement these properly.
524
- B. createBuiltinTrap (fd-> getTypecheckedBody () );
520
+ if (fd->isAsyncHandler () &&
521
+ // If F.isAsync() we are emitting the asyncHandler body and not the
522
+ // original asyncHandler .
523
+ !F. isAsync ()) {
524
+ emitAsyncHandler (fd);
525
525
} else {
526
526
emitStmt (fd->getTypecheckedBody ());
527
527
}
@@ -531,6 +531,58 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
531
531
mergeCleanupBlocks ();
532
532
}
533
533
534
+ // / An asyncHandler function is split into two functions:
535
+ // / 1. The asyncHandler body function: it contains the body of the function, but
536
+ // / is emitted as an async function.
537
+ // / 2. The original function: it just contains
538
+ // / _runAsyncHandler(operation: asyncHandlerBodyFunction)
539
+ void SILGenFunction::emitAsyncHandler (FuncDecl *fd) {
540
+
541
+ // 1. step: create the asyncHandler body function
542
+ //
543
+ auto origFnTy = F.getLoweredFunctionType ();
544
+ assert (!F.isAsync () && " an asyncHandler function cannot be async" );
545
+
546
+ // The body function type is the same as the original type, just with "async".
547
+ auto bodyFnTy = origFnTy->getWithExtInfo (origFnTy->getExtInfo ().withAsync ());
548
+
549
+ SILDeclRef constant (fd, SILDeclRef::Kind::Func);
550
+ std::string name = constant.mangle (SILDeclRef::ManglingKind::AsyncHandlerBody);
551
+ SILLocation loc = F.getLocation ();
552
+ SILGenFunctionBuilder builder (*this );
553
+
554
+ SILFunction *bodyFn = builder.createFunction (
555
+ SILLinkage::Hidden, name, bodyFnTy, F.getGenericEnvironment (),
556
+ loc, F.isBare (), F.isTransparent (),
557
+ F.isSerialized (), IsNotDynamic, ProfileCounter (), IsNotThunk,
558
+ F.getClassSubclassScope (), F.getInlineStrategy (), F.getEffectsKind ());
559
+ bodyFn->setDebugScope (new (getModule ()) SILDebugScope (loc, bodyFn));
560
+
561
+ SILGenFunction (SGM, *bodyFn, fd).emitFunction (fd);
562
+
563
+ // 2. step: emit the original asyncHandler function
564
+ //
565
+ Scope scope (*this , loc);
566
+
567
+ // %bodyFnRef = partial_apply %bodyFn(%originalArg0, %originalArg1, ...)
568
+ //
569
+ SmallVector<ManagedValue, 4 > managedArgs;
570
+ for (SILValue arg : F.getArguments ()) {
571
+ ManagedValue argVal = ManagedValue (arg, CleanupHandle::invalid ());
572
+ managedArgs.push_back (argVal.copy (*this , loc));
573
+ }
574
+ auto *bodyFnRef = B.createFunctionRef (loc, bodyFn);
575
+ ManagedValue bodyFnValue =
576
+ B.createPartialApply (loc, bodyFnRef, F.getForwardingSubstitutionMap (),
577
+ managedArgs, ParameterConvention::Direct_Guaranteed);
578
+
579
+ // apply %_runAsyncHandler(%bodyFnValue)
580
+ //
581
+ FuncDecl *asyncHandlerDecl = SGM.getRunAsyncHandler ();
582
+ emitApplyOfLibraryIntrinsic (loc, asyncHandlerDecl, SubstitutionMap (),
583
+ { bodyFnValue }, SGFContext ());
584
+ }
585
+
534
586
void SILGenFunction::emitClosure (AbstractClosureExpr *ace) {
535
587
MagicFunctionName = SILGenModule::getMagicFunctionName (ace);
536
588
0 commit comments