@@ -2444,3 +2444,83 @@ IRGenFunction::createAsyncDispatchFn(const FunctionPointer &fnPtr,
24442444 Builder.CreateRetVoid ();
24452445 return dispatch;
24462446}
2447+
2448+ void IRGenFunction::emitSuspensionPoint (llvm::Value *toExecutor,
2449+ llvm::Value *asyncResume) {
2450+ // TODO: pointerauth
2451+
2452+ // Setup the suspend point.
2453+ SmallVector<llvm::Value *, 8 > arguments;
2454+ arguments.push_back (asyncResume);
2455+ auto resumeProjFn = getOrCreateResumeFromSuspensionFn ();
2456+ arguments.push_back (
2457+ Builder.CreateBitOrPointerCast (resumeProjFn, IGM.Int8PtrTy ));
2458+ llvm::Function *suspendFn = createAsyncSuspendFn ();
2459+ arguments.push_back (
2460+ Builder.CreateBitOrPointerCast (suspendFn, IGM.Int8PtrTy ));
2461+
2462+ arguments.push_back (asyncResume);
2463+ arguments.push_back (
2464+ Builder.CreateBitOrPointerCast (toExecutor, getAsyncExecutor ()->getType ()));
2465+ arguments.push_back (getAsyncTask ());
2466+ arguments.push_back (getAsyncExecutor ());
2467+ arguments.push_back (getAsyncContext ());
2468+
2469+ emitSuspendAsyncCall (arguments);
2470+ }
2471+
2472+ llvm::Function *IRGenFunction::getOrCreateResumeFromSuspensionFn () {
2473+ auto name = " __swift_async_resume_get_context" ;
2474+ return cast<llvm::Function>(IGM.getOrCreateHelperFunction (
2475+ name, IGM.Int8PtrTy , {IGM.Int8PtrTy },
2476+ [&](IRGenFunction &IGF) {
2477+ auto &Builder = IGF.Builder ;
2478+ Builder.CreateRet (&*IGF.CurFn ->arg_begin ());
2479+ },
2480+ false /* isNoInline*/ ));
2481+ }
2482+
2483+ llvm::Function *IRGenFunction::createAsyncSuspendFn () {
2484+ SmallVector<llvm::Type*, 8 > argTys;
2485+ argTys.push_back (IGM.Int8PtrTy ); // Resume function.
2486+ argTys.push_back (getAsyncExecutor ()->getType ()); // Executor to hop to.
2487+ argTys.push_back (getAsyncTask ()->getType ());
2488+ argTys.push_back (getAsyncExecutor ()->getType ());
2489+ argTys.push_back (getAsyncContext ()->getType ());
2490+ auto *suspendFnTy =
2491+ llvm::FunctionType::get (IGM.VoidTy , argTys, false /* vaargs*/ );
2492+
2493+ StringRef name = " __swift_suspend_point" ;
2494+ if (llvm::GlobalValue *F = IGM.Module .getNamedValue (name))
2495+ return cast<llvm::Function>(F);
2496+
2497+ llvm::Function *suspendFn =
2498+ llvm::Function::Create (suspendFnTy, llvm::Function::InternalLinkage,
2499+ name, &IGM.Module );
2500+ suspendFn->setCallingConv (IGM.DefaultCC );
2501+ suspendFn->setDoesNotThrow ();
2502+ IRGenFunction suspendIGF (IGM, suspendFn);
2503+ if (IGM.DebugInfo )
2504+ IGM.DebugInfo ->emitArtificialFunction (suspendIGF, suspendFn);
2505+ auto &Builder = suspendIGF.Builder ;
2506+
2507+ llvm::Value *resumeFunction = suspendFn->getArg (0 );
2508+ llvm::Value *targetExecutor = suspendFn->getArg (1 );
2509+ llvm::Value *task = suspendFn->getArg (2 );
2510+ llvm::Value *executor = suspendFn->getArg (3 );
2511+ llvm::Value *context = suspendFn->getArg (4 );
2512+
2513+ Alignment ptrAlign = IGM.getPointerAlignment ();
2514+ auto *resumeAddr = Builder.CreateStructGEP (task, 4 );
2515+ Builder.CreateStore (resumeFunction, Address (resumeAddr, ptrAlign));
2516+ auto *contextAddr = Builder.CreateStructGEP (task, 5 );
2517+ Builder.CreateStore (context, Address (contextAddr, ptrAlign));
2518+ auto *suspendCall = Builder.CreateCall (
2519+ IGM.getTaskSwitchFuncFn (),
2520+ { task, executor, targetExecutor });
2521+ suspendCall->setDoesNotThrow ();
2522+ suspendCall->setCallingConv (IGM.SwiftCC );
2523+ suspendCall->setTailCall ();
2524+ Builder.CreateRetVoid ();
2525+ return suspendFn;
2526+ }
0 commit comments