mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[concurrency] SILGen: emit @asyncHandler functions.
An asyncHandler function is split into two functions:
1. The asyncHandler body function: it contains the body of the function, but is emitted as an async function.
2. The original function: it just contains
_runAsyncHandler(operation: asyncHandlerBodyFunction)
rdar://problem/71247879
This commit is contained in:
@@ -517,11 +517,11 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
|
||||
fd->getResultInterfaceType(), fd->hasThrows(), fd->getThrowsLoc());
|
||||
prepareEpilog(true, fd->hasThrows(), CleanupLocation(fd));
|
||||
|
||||
if (fd->isAsyncHandler()) {
|
||||
// Async handlers are need to have their bodies emitted into a
|
||||
// detached task.
|
||||
// FIXME: Actually implement these properly.
|
||||
B.createBuiltinTrap(fd->getTypecheckedBody());
|
||||
if (fd->isAsyncHandler() &&
|
||||
// If F.isAsync() we are emitting the asyncHandler body and not the
|
||||
// original asyncHandler.
|
||||
!F.isAsync()) {
|
||||
emitAsyncHandler(fd);
|
||||
} else {
|
||||
emitStmt(fd->getTypecheckedBody());
|
||||
}
|
||||
@@ -531,6 +531,58 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
|
||||
mergeCleanupBlocks();
|
||||
}
|
||||
|
||||
/// An asyncHandler function is split into two functions:
|
||||
/// 1. The asyncHandler body function: it contains the body of the function, but
|
||||
/// is emitted as an async function.
|
||||
/// 2. The original function: it just contains
|
||||
/// _runAsyncHandler(operation: asyncHandlerBodyFunction)
|
||||
void SILGenFunction::emitAsyncHandler(FuncDecl *fd) {
|
||||
|
||||
// 1. step: create the asyncHandler body function
|
||||
//
|
||||
auto origFnTy = F.getLoweredFunctionType();
|
||||
assert(!F.isAsync() && "an asyncHandler function cannot be async");
|
||||
|
||||
// The body function type is the same as the original type, just with "async".
|
||||
auto bodyFnTy = origFnTy->getWithExtInfo(origFnTy->getExtInfo().withAsync());
|
||||
|
||||
SILDeclRef constant(fd, SILDeclRef::Kind::Func);
|
||||
std::string name = constant.mangle(SILDeclRef::ManglingKind::AsyncHandlerBody);
|
||||
SILLocation loc = F.getLocation();
|
||||
SILGenFunctionBuilder builder(*this);
|
||||
|
||||
SILFunction *bodyFn = builder.createFunction(
|
||||
SILLinkage::Hidden, name, bodyFnTy, F.getGenericEnvironment(),
|
||||
loc, F.isBare(), F.isTransparent(),
|
||||
F.isSerialized(), IsNotDynamic, ProfileCounter(), IsNotThunk,
|
||||
F.getClassSubclassScope(), F.getInlineStrategy(), F.getEffectsKind());
|
||||
bodyFn->setDebugScope(new (getModule()) SILDebugScope(loc, bodyFn));
|
||||
|
||||
SILGenFunction(SGM, *bodyFn, fd).emitFunction(fd);
|
||||
|
||||
// 2. step: emit the original asyncHandler function
|
||||
//
|
||||
Scope scope(*this, loc);
|
||||
|
||||
// %bodyFnRef = partial_apply %bodyFn(%originalArg0, %originalArg1, ...)
|
||||
//
|
||||
SmallVector<ManagedValue, 4> managedArgs;
|
||||
for (SILValue arg : F.getArguments()) {
|
||||
ManagedValue argVal = ManagedValue(arg, CleanupHandle::invalid());
|
||||
managedArgs.push_back(argVal.copy(*this, loc));
|
||||
}
|
||||
auto *bodyFnRef = B.createFunctionRef(loc, bodyFn);
|
||||
ManagedValue bodyFnValue =
|
||||
B.createPartialApply(loc, bodyFnRef, F.getForwardingSubstitutionMap(),
|
||||
managedArgs, ParameterConvention::Direct_Guaranteed);
|
||||
|
||||
// apply %_runAsyncHandler(%bodyFnValue)
|
||||
//
|
||||
FuncDecl *asyncHandlerDecl = SGM.getRunAsyncHandler();
|
||||
emitApplyOfLibraryIntrinsic(loc, asyncHandlerDecl, SubstitutionMap(),
|
||||
{ bodyFnValue }, SGFContext());
|
||||
}
|
||||
|
||||
void SILGenFunction::emitClosure(AbstractClosureExpr *ace) {
|
||||
MagicFunctionName = SILGenModule::getMagicFunctionName(ace);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user