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 namespace { 219 // Make sure to call coro.delete on scope exit. 220 struct CallCoroDelete final : public EHScopeStack::Cleanup { 221 Stmt *Deallocate; 222 223 // TODO: Wrap deallocate in if(coro.free(...)) Deallocate. 224 void Emit(CodeGenFunction &CGF, Flags) override { 225 // Note: That deallocation will be emitted twice: once for a normal exit and 226 // once for exceptional exit. This usage is safe because Deallocate does not 227 // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr() 228 // builds a single call to a deallocation function which is safe to emit 229 // multiple times. 230 CGF.EmitStmt(Deallocate); 231 } 232 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {} 233 }; 234 } 235 236 void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { 237 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); 238 auto &TI = CGM.getContext().getTargetInfo(); 239 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth(); 240 241 auto *FinalBB = createBasicBlock("coro.final"); 242 auto *RetBB = createBasicBlock("coro.ret"); 243 244 auto *CoroId = Builder.CreateCall( 245 CGM.getIntrinsic(llvm::Intrinsic::coro_id), 246 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr}); 247 createCoroData(*this, CurCoro, CoroId); 248 CurCoro.Data->SuspendBB = RetBB; 249 250 auto *AllocateCall = EmitScalarExpr(S.getAllocate()); 251 252 // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided. 253 if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) { 254 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure"); 255 auto *InitBB = createBasicBlock("coro.init"); 256 257 // See if allocation was successful. 258 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy); 259 auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr); 260 Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB); 261 262 // If not, return OnAllocFailure object. 263 EmitBlock(RetOnFailureBB); 264 EmitStmt(RetOnAllocFailure); 265 266 EmitBlock(InitBB); 267 } 268 269 CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB); 270 { 271 CodeGenFunction::RunCleanupsScope ResumeScope(*this); 272 EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate()); 273 274 EmitStmt(S.getPromiseDeclStmt()); 275 276 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB); 277 278 // FIXME: Emit initial suspend and more before the body. 279 280 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; 281 EmitStmt(S.getBody()); 282 283 // See if we need to generate final suspend. 284 const bool CanFallthrough = Builder.GetInsertBlock(); 285 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0; 286 if (CanFallthrough || HasCoreturns) { 287 EmitBlock(FinalBB); 288 // FIXME: Emit final suspend. 289 } 290 } 291 292 EmitBlock(RetBB); 293 294 // FIXME: Emit return for the coroutine return object. 295 } 296 297 // Emit coroutine intrinsic and patch up arguments of the token type. 298 RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, 299 unsigned int IID) { 300 SmallVector<llvm::Value *, 8> Args; 301 switch (IID) { 302 default: 303 break; 304 // The following three intrinsics take a token parameter referring to a token 305 // returned by earlier call to @llvm.coro.id. Since we cannot represent it in 306 // builtins, we patch it up here. 307 case llvm::Intrinsic::coro_alloc: 308 case llvm::Intrinsic::coro_begin: 309 case llvm::Intrinsic::coro_free: { 310 if (CurCoro.Data && CurCoro.Data->CoroId) { 311 Args.push_back(CurCoro.Data->CoroId); 312 break; 313 } 314 CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" 315 " been used earlier in this function"); 316 // Fallthrough to the next case to add TokenNone as the first argument. 317 } 318 // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first 319 // argument. 320 case llvm::Intrinsic::coro_suspend: 321 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext())); 322 break; 323 } 324 for (auto &Arg : E->arguments()) 325 Args.push_back(EmitScalarExpr(Arg)); 326 327 llvm::Value *F = CGM.getIntrinsic(IID); 328 llvm::CallInst *Call = Builder.CreateCall(F, Args); 329 330 // If we see @llvm.coro.id remember it in the CoroData. We will update 331 // coro.alloc, coro.begin and coro.free intrinsics to refer to it. 332 if (IID == llvm::Intrinsic::coro_id) { 333 createCoroData(*this, CurCoro, Call, E); 334 } 335 return RValue::get(Call); 336 } 337