1 //===----- CGCoroutine.cpp - Emit LLVM Code for C++ coroutines ------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This contains code dealing with C++ code generation of coroutines. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeGenFunction.h" 15 #include "llvm/ADT/ScopeExit.h" 16 #include "clang/AST/StmtCXX.h" 17 18 using namespace clang; 19 using namespace CodeGen; 20 21 using llvm::Value; 22 using llvm::BasicBlock; 23 24 namespace { 25 enum class AwaitKind { Init, Normal, Yield, Final }; 26 static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", "yield", 27 "final"}; 28 } 29 30 struct clang::CodeGen::CGCoroData { 31 // What is the current await expression kind and how many 32 // await/yield expressions were encountered so far. 33 // These are used to generate pretty labels for await expressions in LLVM IR. 34 AwaitKind CurrentAwaitKind = AwaitKind::Init; 35 unsigned AwaitNum = 0; 36 unsigned YieldNum = 0; 37 38 // How many co_return statements are in the coroutine. Used to decide whether 39 // we need to add co_return; equivalent at the end of the user authored body. 40 unsigned CoreturnCount = 0; 41 42 // A branch to this block is emitted when coroutine needs to suspend. 43 llvm::BasicBlock *SuspendBB = nullptr; 44 45 // Stores the jump destination just before the coroutine memory is freed. 46 // This is the destination that every suspend point jumps to for the cleanup 47 // branch. 48 CodeGenFunction::JumpDest CleanupJD; 49 50 // Stores the jump destination just before the final suspend. The co_return 51 // statements jumps to this point after calling return_xxx promise member. 52 CodeGenFunction::JumpDest FinalJD; 53 54 // Stores the llvm.coro.id emitted in the function so that we can supply it 55 // as the first argument to coro.begin, coro.alloc and coro.free intrinsics. 56 // Note: llvm.coro.id returns a token that cannot be directly expressed in a 57 // builtin. 58 llvm::CallInst *CoroId = nullptr; 59 60 // If coro.id came from the builtin, remember the expression to give better 61 // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by 62 // EmitCoroutineBody. 63 CallExpr const *CoroIdExpr = nullptr; 64 }; 65 66 // Defining these here allows to keep CGCoroData private to this file. 67 clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {} 68 CodeGenFunction::CGCoroInfo::~CGCoroInfo() {} 69 70 static void createCoroData(CodeGenFunction &CGF, 71 CodeGenFunction::CGCoroInfo &CurCoro, 72 llvm::CallInst *CoroId, 73 CallExpr const *CoroIdExpr = nullptr) { 74 if (CurCoro.Data) { 75 if (CurCoro.Data->CoroIdExpr) 76 CGF.CGM.Error(CoroIdExpr->getLocStart(), 77 "only one __builtin_coro_id can be used in a function"); 78 else if (CoroIdExpr) 79 CGF.CGM.Error(CoroIdExpr->getLocStart(), 80 "__builtin_coro_id shall not be used in a C++ coroutine"); 81 else 82 llvm_unreachable("EmitCoroutineBodyStatement called twice?"); 83 84 return; 85 } 86 87 CurCoro.Data = std::unique_ptr<CGCoroData>(new CGCoroData); 88 CurCoro.Data->CoroId = CoroId; 89 CurCoro.Data->CoroIdExpr = CoroIdExpr; 90 } 91 92 // Synthesize a pretty name for a suspend point. 93 static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { 94 unsigned No = 0; 95 switch (Kind) { 96 case AwaitKind::Init: 97 case AwaitKind::Final: 98 break; 99 case AwaitKind::Normal: 100 No = ++Coro.AwaitNum; 101 break; 102 case AwaitKind::Yield: 103 No = ++Coro.YieldNum; 104 break; 105 } 106 SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]); 107 if (No > 1) { 108 Twine(No).toVector(Prefix); 109 } 110 return Prefix; 111 } 112 113 // Emit suspend expression which roughly looks like: 114 // 115 // auto && x = CommonExpr(); 116 // if (!x.await_ready()) { 117 // llvm_coro_save(); 118 // x.await_suspend(...); (*) 119 // llvm_coro_suspend(); (**) 120 // } 121 // x.await_resume(); 122 // 123 // where the result of the entire expression is the result of x.await_resume() 124 // 125 // (*) If x.await_suspend return type is bool, it allows to veto a suspend: 126 // if (x.await_suspend(...)) 127 // llvm_coro_suspend(); 128 // 129 // (**) llvm_coro_suspend() encodes three possible continuations as 130 // a switch instruction: 131 // 132 // %where-to = call i8 @llvm.coro.suspend(...) 133 // switch i8 %where-to, label %coro.ret [ ; jump to epilogue to suspend 134 // i8 0, label %yield.ready ; go here when resumed 135 // i8 1, label %yield.cleanup ; go here when destroyed 136 // ] 137 // 138 // See llvm's docs/Coroutines.rst for more details. 139 // 140 static RValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, 141 CoroutineSuspendExpr const &S, 142 AwaitKind Kind, AggValueSlot aggSlot, 143 bool ignoreResult) { 144 auto *E = S.getCommonExpr(); 145 auto Binder = 146 CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); 147 auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); 148 149 auto Prefix = buildSuspendPrefixStr(Coro, Kind); 150 BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready")); 151 BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend")); 152 BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup")); 153 154 // If expression is ready, no need to suspend. 155 CGF.EmitBranchOnBoolExpr(S.getReadyExpr(), ReadyBlock, SuspendBlock, 0); 156 157 // Otherwise, emit suspend logic. 158 CGF.EmitBlock(SuspendBlock); 159 160 auto &Builder = CGF.Builder; 161 llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save); 162 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy); 163 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr}); 164 165 auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr()); 166 if (SuspendRet != nullptr) { 167 // Veto suspension if requested by bool returning await_suspend. 168 assert(SuspendRet->getType()->isIntegerTy(1) && 169 "Sema should have already checked that it is void or bool"); 170 BasicBlock *RealSuspendBlock = 171 CGF.createBasicBlock(Prefix + Twine(".suspend.bool")); 172 CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock); 173 SuspendBlock = RealSuspendBlock; 174 CGF.EmitBlock(RealSuspendBlock); 175 } 176 177 // Emit the suspend point. 178 const bool IsFinalSuspend = (Kind == AwaitKind::Final); 179 llvm::Function *CoroSuspend = 180 CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_suspend); 181 auto *SuspendResult = Builder.CreateCall( 182 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)}); 183 184 // Create a switch capturing three possible continuations. 185 auto *Switch = Builder.CreateSwitch(SuspendResult, Coro.SuspendBB, 2); 186 Switch->addCase(Builder.getInt8(0), ReadyBlock); 187 Switch->addCase(Builder.getInt8(1), CleanupBlock); 188 189 // Emit cleanup for this suspend point. 190 CGF.EmitBlock(CleanupBlock); 191 CGF.EmitBranchThroughCleanup(Coro.CleanupJD); 192 193 // Emit await_resume expression. 194 CGF.EmitBlock(ReadyBlock); 195 return CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult); 196 } 197 198 RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E, 199 AggValueSlot aggSlot, 200 bool ignoreResult) { 201 return emitSuspendExpression(*this, *CurCoro.Data, E, 202 CurCoro.Data->CurrentAwaitKind, aggSlot, 203 ignoreResult); 204 } 205 RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E, 206 AggValueSlot aggSlot, 207 bool ignoreResult) { 208 return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield, 209 aggSlot, ignoreResult); 210 } 211 212 void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { 213 ++CurCoro.Data->CoreturnCount; 214 EmitStmt(S.getPromiseCall()); 215 EmitBranchThroughCleanup(CurCoro.Data->FinalJD); 216 } 217 218 // For WinEH exception representation backend need to know what funclet coro.end 219 // belongs to. That information is passed in a funclet bundle. 220 static SmallVector<llvm::OperandBundleDef, 1> 221 getBundlesForCoroEnd(CodeGenFunction &CGF) { 222 SmallVector<llvm::OperandBundleDef, 1> BundleList; 223 224 if (llvm::Instruction *EHPad = CGF.CurrentFuncletPad) 225 BundleList.emplace_back("funclet", EHPad); 226 227 return BundleList; 228 } 229 230 namespace { 231 // We will insert coro.end to cut any of the destructors for objects that 232 // do not need to be destroyed once the coroutine is resumed. 233 // See llvm/docs/Coroutines.rst for more details about coro.end. 234 struct CallCoroEnd final : public EHScopeStack::Cleanup { 235 void Emit(CodeGenFunction &CGF, Flags flags) override { 236 auto &CGM = CGF.CGM; 237 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy); 238 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end); 239 // See if we have a funclet bundle to associate coro.end with. (WinEH) 240 auto Bundles = getBundlesForCoroEnd(CGF); 241 auto *CoroEnd = CGF.Builder.CreateCall( 242 CoroEndFn, {NullPtr, CGF.Builder.getTrue()}, Bundles); 243 if (Bundles.empty()) { 244 // Otherwise, (landingpad model), create a conditional branch that leads 245 // either to a cleanup block or a block with EH resume instruction. 246 auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true); 247 auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont"); 248 CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB); 249 CGF.EmitBlock(CleanupContBB); 250 } 251 } 252 }; 253 } 254 255 namespace { 256 // Make sure to call coro.delete on scope exit. 257 struct CallCoroDelete final : public EHScopeStack::Cleanup { 258 Stmt *Deallocate; 259 260 // TODO: Wrap deallocate in if(coro.free(...)) Deallocate. 261 void Emit(CodeGenFunction &CGF, Flags) override { 262 // Note: That deallocation will be emitted twice: once for a normal exit and 263 // once for exceptional exit. This usage is safe because Deallocate does not 264 // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr() 265 // builds a single call to a deallocation function which is safe to emit 266 // multiple times. 267 CGF.EmitStmt(Deallocate); 268 } 269 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {} 270 }; 271 } 272 273 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { 274 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); 275 auto &TI = CGM.getContext().getTargetInfo(); 276 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth(); 277 278 auto *FinalBB = createBasicBlock("coro.final"); 279 auto *RetBB = createBasicBlock("coro.ret"); 280 281 auto *CoroId = Builder.CreateCall( 282 CGM.getIntrinsic(llvm::Intrinsic::coro_id), 283 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr}); 284 createCoroData(*this, CurCoro, CoroId); 285 CurCoro.Data->SuspendBB = RetBB; 286 287 auto *AllocateCall = EmitScalarExpr(S.getAllocate()); 288 289 // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided. 290 if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) { 291 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure"); 292 auto *InitBB = createBasicBlock("coro.init"); 293 294 // See if allocation was successful. 295 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy); 296 auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr); 297 Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB); 298 299 // If not, return OnAllocFailure object. 300 EmitBlock(RetOnFailureBB); 301 EmitStmt(RetOnAllocFailure); 302 303 EmitBlock(InitBB); 304 } 305 306 CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB); 307 { 308 CodeGenFunction::RunCleanupsScope ResumeScope(*this); 309 EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate()); 310 311 EmitStmt(S.getPromiseDeclStmt()); 312 313 EHStack.pushCleanup<CallCoroEnd>(EHCleanup); 314 315 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB); 316 317 // FIXME: Emit initial suspend and more before the body. 318 319 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; 320 EmitStmt(S.getBody()); 321 322 // See if we need to generate final suspend. 323 const bool CanFallthrough = Builder.GetInsertBlock(); 324 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0; 325 if (CanFallthrough || HasCoreturns) { 326 EmitBlock(FinalBB); 327 // FIXME: Emit final suspend. 328 } 329 } 330 331 EmitBlock(RetBB); 332 llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end); 333 Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()}); 334 335 // FIXME: Emit return for the coroutine return object. 336 } 337 338 // Emit coroutine intrinsic and patch up arguments of the token type. 339 RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, 340 unsigned int IID) { 341 SmallVector<llvm::Value *, 8> Args; 342 switch (IID) { 343 default: 344 break; 345 // The following three intrinsics take a token parameter referring to a token 346 // returned by earlier call to @llvm.coro.id. Since we cannot represent it in 347 // builtins, we patch it up here. 348 case llvm::Intrinsic::coro_alloc: 349 case llvm::Intrinsic::coro_begin: 350 case llvm::Intrinsic::coro_free: { 351 if (CurCoro.Data && CurCoro.Data->CoroId) { 352 Args.push_back(CurCoro.Data->CoroId); 353 break; 354 } 355 CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" 356 " been used earlier in this function"); 357 // Fallthrough to the next case to add TokenNone as the first argument. 358 } 359 // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first 360 // argument. 361 case llvm::Intrinsic::coro_suspend: 362 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext())); 363 break; 364 } 365 for (auto &Arg : E->arguments()) 366 Args.push_back(EmitScalarExpr(Arg)); 367 368 llvm::Value *F = CGM.getIntrinsic(IID); 369 llvm::CallInst *Call = Builder.CreateCall(F, Args); 370 371 // If we see @llvm.coro.id remember it in the CoroData. We will update 372 // coro.alloc, coro.begin and coro.free intrinsics to refer to it. 373 if (IID == llvm::Intrinsic::coro_id) { 374 createCoroData(*this, CurCoro, Call, E); 375 } 376 return RValue::get(Call); 377 } 378