File: | tools/clang/lib/CodeGen/CGCoroutine.cpp |
Warning: | line 191, column 5 Value stored to 'SuspendBlock' is never read |
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 "CGCleanup.h" |
15 | #include "CodeGenFunction.h" |
16 | #include "llvm/ADT/ScopeExit.h" |
17 | #include "clang/AST/StmtCXX.h" |
18 | #include "clang/AST/StmtVisitor.h" |
19 | |
20 | using namespace clang; |
21 | using namespace CodeGen; |
22 | |
23 | using llvm::Value; |
24 | using llvm::BasicBlock; |
25 | |
26 | namespace { |
27 | enum class AwaitKind { Init, Normal, Yield, Final }; |
28 | static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", "yield", |
29 | "final"}; |
30 | } |
31 | |
32 | struct clang::CodeGen::CGCoroData { |
33 | // What is the current await expression kind and how many |
34 | // await/yield expressions were encountered so far. |
35 | // These are used to generate pretty labels for await expressions in LLVM IR. |
36 | AwaitKind CurrentAwaitKind = AwaitKind::Init; |
37 | unsigned AwaitNum = 0; |
38 | unsigned YieldNum = 0; |
39 | |
40 | // How many co_return statements are in the coroutine. Used to decide whether |
41 | // we need to add co_return; equivalent at the end of the user authored body. |
42 | unsigned CoreturnCount = 0; |
43 | |
44 | // A branch to this block is emitted when coroutine needs to suspend. |
45 | llvm::BasicBlock *SuspendBB = nullptr; |
46 | |
47 | // Stores the jump destination just before the coroutine memory is freed. |
48 | // This is the destination that every suspend point jumps to for the cleanup |
49 | // branch. |
50 | CodeGenFunction::JumpDest CleanupJD; |
51 | |
52 | // Stores the jump destination just before the final suspend. The co_return |
53 | // statements jumps to this point after calling return_xxx promise member. |
54 | CodeGenFunction::JumpDest FinalJD; |
55 | |
56 | // Stores the llvm.coro.id emitted in the function so that we can supply it |
57 | // as the first argument to coro.begin, coro.alloc and coro.free intrinsics. |
58 | // Note: llvm.coro.id returns a token that cannot be directly expressed in a |
59 | // builtin. |
60 | llvm::CallInst *CoroId = nullptr; |
61 | |
62 | // Stores the llvm.coro.begin emitted in the function so that we can replace |
63 | // all coro.frame intrinsics with direct SSA value of coro.begin that returns |
64 | // the address of the coroutine frame of the current coroutine. |
65 | llvm::CallInst *CoroBegin = nullptr; |
66 | |
67 | // Stores the last emitted coro.free for the deallocate expressions, we use it |
68 | // to wrap dealloc code with if(auto mem = coro.free) dealloc(mem). |
69 | llvm::CallInst *LastCoroFree = nullptr; |
70 | |
71 | // If coro.id came from the builtin, remember the expression to give better |
72 | // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by |
73 | // EmitCoroutineBody. |
74 | CallExpr const *CoroIdExpr = nullptr; |
75 | }; |
76 | |
77 | // Defining these here allows to keep CGCoroData private to this file. |
78 | clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {} |
79 | CodeGenFunction::CGCoroInfo::~CGCoroInfo() {} |
80 | |
81 | static void createCoroData(CodeGenFunction &CGF, |
82 | CodeGenFunction::CGCoroInfo &CurCoro, |
83 | llvm::CallInst *CoroId, |
84 | CallExpr const *CoroIdExpr = nullptr) { |
85 | if (CurCoro.Data) { |
86 | if (CurCoro.Data->CoroIdExpr) |
87 | CGF.CGM.Error(CoroIdExpr->getLocStart(), |
88 | "only one __builtin_coro_id can be used in a function"); |
89 | else if (CoroIdExpr) |
90 | CGF.CGM.Error(CoroIdExpr->getLocStart(), |
91 | "__builtin_coro_id shall not be used in a C++ coroutine"); |
92 | else |
93 | llvm_unreachable("EmitCoroutineBodyStatement called twice?")::llvm::llvm_unreachable_internal("EmitCoroutineBodyStatement called twice?" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 93); |
94 | |
95 | return; |
96 | } |
97 | |
98 | CurCoro.Data = std::unique_ptr<CGCoroData>(new CGCoroData); |
99 | CurCoro.Data->CoroId = CoroId; |
100 | CurCoro.Data->CoroIdExpr = CoroIdExpr; |
101 | } |
102 | |
103 | // Synthesize a pretty name for a suspend point. |
104 | static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) { |
105 | unsigned No = 0; |
106 | switch (Kind) { |
107 | case AwaitKind::Init: |
108 | case AwaitKind::Final: |
109 | break; |
110 | case AwaitKind::Normal: |
111 | No = ++Coro.AwaitNum; |
112 | break; |
113 | case AwaitKind::Yield: |
114 | No = ++Coro.YieldNum; |
115 | break; |
116 | } |
117 | SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]); |
118 | if (No > 1) { |
119 | Twine(No).toVector(Prefix); |
120 | } |
121 | return Prefix; |
122 | } |
123 | |
124 | // Emit suspend expression which roughly looks like: |
125 | // |
126 | // auto && x = CommonExpr(); |
127 | // if (!x.await_ready()) { |
128 | // llvm_coro_save(); |
129 | // x.await_suspend(...); (*) |
130 | // llvm_coro_suspend(); (**) |
131 | // } |
132 | // x.await_resume(); |
133 | // |
134 | // where the result of the entire expression is the result of x.await_resume() |
135 | // |
136 | // (*) If x.await_suspend return type is bool, it allows to veto a suspend: |
137 | // if (x.await_suspend(...)) |
138 | // llvm_coro_suspend(); |
139 | // |
140 | // (**) llvm_coro_suspend() encodes three possible continuations as |
141 | // a switch instruction: |
142 | // |
143 | // %where-to = call i8 @llvm.coro.suspend(...) |
144 | // switch i8 %where-to, label %coro.ret [ ; jump to epilogue to suspend |
145 | // i8 0, label %yield.ready ; go here when resumed |
146 | // i8 1, label %yield.cleanup ; go here when destroyed |
147 | // ] |
148 | // |
149 | // See llvm's docs/Coroutines.rst for more details. |
150 | // |
151 | namespace { |
152 | struct LValueOrRValue { |
153 | LValue LV; |
154 | RValue RV; |
155 | }; |
156 | } |
157 | static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, |
158 | CoroutineSuspendExpr const &S, |
159 | AwaitKind Kind, AggValueSlot aggSlot, |
160 | bool ignoreResult, bool forLValue) { |
161 | auto *E = S.getCommonExpr(); |
162 | |
163 | auto Binder = |
164 | CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); |
165 | auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); |
166 | |
167 | auto Prefix = buildSuspendPrefixStr(Coro, Kind); |
168 | BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready")); |
169 | BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend")); |
170 | BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup")); |
171 | |
172 | // If expression is ready, no need to suspend. |
173 | CGF.EmitBranchOnBoolExpr(S.getReadyExpr(), ReadyBlock, SuspendBlock, 0); |
174 | |
175 | // Otherwise, emit suspend logic. |
176 | CGF.EmitBlock(SuspendBlock); |
177 | |
178 | auto &Builder = CGF.Builder; |
179 | llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save); |
180 | auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy); |
181 | auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr}); |
182 | |
183 | auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr()); |
184 | if (SuspendRet != nullptr) { |
185 | // Veto suspension if requested by bool returning await_suspend. |
186 | assert(SuspendRet->getType()->isIntegerTy(1) &&((SuspendRet->getType()->isIntegerTy(1) && "Sema should have already checked that it is void or bool" ) ? static_cast<void> (0) : __assert_fail ("SuspendRet->getType()->isIntegerTy(1) && \"Sema should have already checked that it is void or bool\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 187, __PRETTY_FUNCTION__)) |
187 | "Sema should have already checked that it is void or bool")((SuspendRet->getType()->isIntegerTy(1) && "Sema should have already checked that it is void or bool" ) ? static_cast<void> (0) : __assert_fail ("SuspendRet->getType()->isIntegerTy(1) && \"Sema should have already checked that it is void or bool\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 187, __PRETTY_FUNCTION__)); |
188 | BasicBlock *RealSuspendBlock = |
189 | CGF.createBasicBlock(Prefix + Twine(".suspend.bool")); |
190 | CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock); |
191 | SuspendBlock = RealSuspendBlock; |
Value stored to 'SuspendBlock' is never read | |
192 | CGF.EmitBlock(RealSuspendBlock); |
193 | } |
194 | |
195 | // Emit the suspend point. |
196 | const bool IsFinalSuspend = (Kind == AwaitKind::Final); |
197 | llvm::Function *CoroSuspend = |
198 | CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_suspend); |
199 | auto *SuspendResult = Builder.CreateCall( |
200 | CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)}); |
201 | |
202 | // Create a switch capturing three possible continuations. |
203 | auto *Switch = Builder.CreateSwitch(SuspendResult, Coro.SuspendBB, 2); |
204 | Switch->addCase(Builder.getInt8(0), ReadyBlock); |
205 | Switch->addCase(Builder.getInt8(1), CleanupBlock); |
206 | |
207 | // Emit cleanup for this suspend point. |
208 | CGF.EmitBlock(CleanupBlock); |
209 | CGF.EmitBranchThroughCleanup(Coro.CleanupJD); |
210 | |
211 | // Emit await_resume expression. |
212 | CGF.EmitBlock(ReadyBlock); |
213 | LValueOrRValue Res; |
214 | if (forLValue) |
215 | Res.LV = CGF.EmitLValue(S.getResumeExpr()); |
216 | else |
217 | Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult); |
218 | return Res; |
219 | } |
220 | |
221 | RValue CodeGenFunction::EmitCoawaitExpr(const CoawaitExpr &E, |
222 | AggValueSlot aggSlot, |
223 | bool ignoreResult) { |
224 | return emitSuspendExpression(*this, *CurCoro.Data, E, |
225 | CurCoro.Data->CurrentAwaitKind, aggSlot, |
226 | ignoreResult, /*forLValue*/false).RV; |
227 | } |
228 | RValue CodeGenFunction::EmitCoyieldExpr(const CoyieldExpr &E, |
229 | AggValueSlot aggSlot, |
230 | bool ignoreResult) { |
231 | return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield, |
232 | aggSlot, ignoreResult, /*forLValue*/false).RV; |
233 | } |
234 | |
235 | void CodeGenFunction::EmitCoreturnStmt(CoreturnStmt const &S) { |
236 | ++CurCoro.Data->CoreturnCount; |
237 | EmitStmt(S.getPromiseCall()); |
238 | EmitBranchThroughCleanup(CurCoro.Data->FinalJD); |
239 | } |
240 | |
241 | |
242 | #ifndef NDEBUG |
243 | static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, |
244 | const CoroutineSuspendExpr *E) { |
245 | const auto *RE = E->getResumeExpr(); |
246 | // Is it possible for RE to be a CXXBindTemporaryExpr wrapping |
247 | // a MemberCallExpr? |
248 | assert(isa<CallExpr>(RE) && "unexpected suspend expression type")((isa<CallExpr>(RE) && "unexpected suspend expression type" ) ? static_cast<void> (0) : __assert_fail ("isa<CallExpr>(RE) && \"unexpected suspend expression type\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 248, __PRETTY_FUNCTION__)); |
249 | return cast<CallExpr>(RE)->getCallReturnType(Ctx); |
250 | } |
251 | #endif |
252 | |
253 | LValue |
254 | CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) { |
255 | assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 257, __PRETTY_FUNCTION__)) |
256 | "Can't have a scalar return unless the return type is a "((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 257, __PRETTY_FUNCTION__)) |
257 | "reference type!")((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 257, __PRETTY_FUNCTION__)); |
258 | return emitSuspendExpression(*this, *CurCoro.Data, *E, |
259 | CurCoro.Data->CurrentAwaitKind, AggValueSlot::ignored(), |
260 | /*ignoreResult*/false, /*forLValue*/true).LV; |
261 | } |
262 | |
263 | LValue |
264 | CodeGenFunction::EmitCoyieldLValue(const CoyieldExpr *E) { |
265 | assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 267, __PRETTY_FUNCTION__)) |
266 | "Can't have a scalar return unless the return type is a "((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 267, __PRETTY_FUNCTION__)) |
267 | "reference type!")((getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType () && "Can't have a scalar return unless the return type is a " "reference type!") ? static_cast<void> (0) : __assert_fail ("getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && \"Can't have a scalar return unless the return type is a \" \"reference type!\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 267, __PRETTY_FUNCTION__)); |
268 | return emitSuspendExpression(*this, *CurCoro.Data, *E, |
269 | AwaitKind::Yield, AggValueSlot::ignored(), |
270 | /*ignoreResult*/false, /*forLValue*/true).LV; |
271 | } |
272 | |
273 | // Hunts for the parameter reference in the parameter copy/move declaration. |
274 | namespace { |
275 | struct GetParamRef : public StmtVisitor<GetParamRef> { |
276 | public: |
277 | DeclRefExpr *Expr = nullptr; |
278 | GetParamRef() {} |
279 | void VisitDeclRefExpr(DeclRefExpr *E) { |
280 | assert(Expr == nullptr && "multilple declref in param move")((Expr == nullptr && "multilple declref in param move" ) ? static_cast<void> (0) : __assert_fail ("Expr == nullptr && \"multilple declref in param move\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 280, __PRETTY_FUNCTION__)); |
281 | Expr = E; |
282 | } |
283 | void VisitStmt(Stmt *S) { |
284 | for (auto *C : S->children()) { |
285 | if (C) |
286 | Visit(C); |
287 | } |
288 | } |
289 | }; |
290 | } |
291 | |
292 | // This class replaces references to parameters to their copies by changing |
293 | // the addresses in CGF.LocalDeclMap and restoring back the original values in |
294 | // its destructor. |
295 | |
296 | namespace { |
297 | struct ParamReferenceReplacerRAII { |
298 | CodeGenFunction::DeclMapTy SavedLocals; |
299 | CodeGenFunction::DeclMapTy& LocalDeclMap; |
300 | |
301 | ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap) |
302 | : LocalDeclMap(LocalDeclMap) {} |
303 | |
304 | void addCopy(DeclStmt const *PM) { |
305 | // Figure out what param it refers to. |
306 | |
307 | assert(PM->isSingleDecl())((PM->isSingleDecl()) ? static_cast<void> (0) : __assert_fail ("PM->isSingleDecl()", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 307, __PRETTY_FUNCTION__)); |
308 | VarDecl const*VD = static_cast<VarDecl const*>(PM->getSingleDecl()); |
309 | Expr const *InitExpr = VD->getInit(); |
310 | GetParamRef Visitor; |
311 | Visitor.Visit(const_cast<Expr*>(InitExpr)); |
312 | assert(Visitor.Expr)((Visitor.Expr) ? static_cast<void> (0) : __assert_fail ("Visitor.Expr", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 312, __PRETTY_FUNCTION__)); |
313 | auto *DREOrig = cast<DeclRefExpr>(Visitor.Expr); |
314 | auto *PD = DREOrig->getDecl(); |
315 | |
316 | auto it = LocalDeclMap.find(PD); |
317 | assert(it != LocalDeclMap.end() && "parameter is not found")((it != LocalDeclMap.end() && "parameter is not found" ) ? static_cast<void> (0) : __assert_fail ("it != LocalDeclMap.end() && \"parameter is not found\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 317, __PRETTY_FUNCTION__)); |
318 | SavedLocals.insert({ PD, it->second }); |
319 | |
320 | auto copyIt = LocalDeclMap.find(VD); |
321 | assert(copyIt != LocalDeclMap.end() && "parameter copy is not found")((copyIt != LocalDeclMap.end() && "parameter copy is not found" ) ? static_cast<void> (0) : __assert_fail ("copyIt != LocalDeclMap.end() && \"parameter copy is not found\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 321, __PRETTY_FUNCTION__)); |
322 | it->second = copyIt->getSecond(); |
323 | } |
324 | |
325 | ~ParamReferenceReplacerRAII() { |
326 | for (auto&& SavedLocal : SavedLocals) { |
327 | LocalDeclMap.insert({SavedLocal.first, SavedLocal.second}); |
328 | } |
329 | } |
330 | }; |
331 | } |
332 | |
333 | // For WinEH exception representation backend needs to know what funclet coro.end |
334 | // belongs to. That information is passed in a funclet bundle. |
335 | static SmallVector<llvm::OperandBundleDef, 1> |
336 | getBundlesForCoroEnd(CodeGenFunction &CGF) { |
337 | SmallVector<llvm::OperandBundleDef, 1> BundleList; |
338 | |
339 | if (llvm::Instruction *EHPad = CGF.CurrentFuncletPad) |
340 | BundleList.emplace_back("funclet", EHPad); |
341 | |
342 | return BundleList; |
343 | } |
344 | |
345 | namespace { |
346 | // We will insert coro.end to cut any of the destructors for objects that |
347 | // do not need to be destroyed once the coroutine is resumed. |
348 | // See llvm/docs/Coroutines.rst for more details about coro.end. |
349 | struct CallCoroEnd final : public EHScopeStack::Cleanup { |
350 | void Emit(CodeGenFunction &CGF, Flags flags) override { |
351 | auto &CGM = CGF.CGM; |
352 | auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy); |
353 | llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end); |
354 | // See if we have a funclet bundle to associate coro.end with. (WinEH) |
355 | auto Bundles = getBundlesForCoroEnd(CGF); |
356 | auto *CoroEnd = CGF.Builder.CreateCall( |
357 | CoroEndFn, {NullPtr, CGF.Builder.getTrue()}, Bundles); |
358 | if (Bundles.empty()) { |
359 | // Otherwise, (landingpad model), create a conditional branch that leads |
360 | // either to a cleanup block or a block with EH resume instruction. |
361 | auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true); |
362 | auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont"); |
363 | CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB); |
364 | CGF.EmitBlock(CleanupContBB); |
365 | } |
366 | } |
367 | }; |
368 | } |
369 | |
370 | namespace { |
371 | // Make sure to call coro.delete on scope exit. |
372 | struct CallCoroDelete final : public EHScopeStack::Cleanup { |
373 | Stmt *Deallocate; |
374 | |
375 | // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;" |
376 | |
377 | // Note: That deallocation will be emitted twice: once for a normal exit and |
378 | // once for exceptional exit. This usage is safe because Deallocate does not |
379 | // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr() |
380 | // builds a single call to a deallocation function which is safe to emit |
381 | // multiple times. |
382 | void Emit(CodeGenFunction &CGF, Flags) override { |
383 | // Remember the current point, as we are going to emit deallocation code |
384 | // first to get to coro.free instruction that is an argument to a delete |
385 | // call. |
386 | BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock(); |
387 | |
388 | auto *FreeBB = CGF.createBasicBlock("coro.free"); |
389 | CGF.EmitBlock(FreeBB); |
390 | CGF.EmitStmt(Deallocate); |
391 | |
392 | auto *AfterFreeBB = CGF.createBasicBlock("after.coro.free"); |
393 | CGF.EmitBlock(AfterFreeBB); |
394 | |
395 | // We should have captured coro.free from the emission of deallocate. |
396 | auto *CoroFree = CGF.CurCoro.Data->LastCoroFree; |
397 | if (!CoroFree) { |
398 | CGF.CGM.Error(Deallocate->getLocStart(), |
399 | "Deallocation expressoin does not refer to coro.free"); |
400 | return; |
401 | } |
402 | |
403 | // Get back to the block we were originally and move coro.free there. |
404 | auto *InsertPt = SaveInsertBlock->getTerminator(); |
405 | CoroFree->moveBefore(InsertPt); |
406 | CGF.Builder.SetInsertPoint(InsertPt); |
407 | |
408 | // Add if (auto *mem = coro.free) Deallocate; |
409 | auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy); |
410 | auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr); |
411 | CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB); |
412 | |
413 | // No longer need old terminator. |
414 | InsertPt->eraseFromParent(); |
415 | CGF.Builder.SetInsertPoint(AfterFreeBB); |
416 | } |
417 | explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {} |
418 | }; |
419 | } |
420 | |
421 | namespace { |
422 | struct GetReturnObjectManager { |
423 | CodeGenFunction &CGF; |
424 | CGBuilderTy &Builder; |
425 | const CoroutineBodyStmt &S; |
426 | |
427 | Address GroActiveFlag; |
428 | CodeGenFunction::AutoVarEmission GroEmission; |
429 | |
430 | GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S) |
431 | : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()), |
432 | GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {} |
433 | |
434 | // The gro variable has to outlive coroutine frame and coroutine promise, but, |
435 | // it can only be initialized after coroutine promise was created, thus, we |
436 | // split its emission in two parts. EmitGroAlloca emits an alloca and sets up |
437 | // cleanups. Later when coroutine promise is available we initialize the gro |
438 | // and sets the flag that the cleanup is now active. |
439 | |
440 | void EmitGroAlloca() { |
441 | auto *GroDeclStmt = dyn_cast<DeclStmt>(S.getResultDecl()); |
442 | if (!GroDeclStmt) { |
443 | // If get_return_object returns void, no need to do an alloca. |
444 | return; |
445 | } |
446 | |
447 | auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl()); |
448 | |
449 | // Set GRO flag that it is not initialized yet |
450 | GroActiveFlag = |
451 | CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(), "gro.active"); |
452 | Builder.CreateStore(Builder.getFalse(), GroActiveFlag); |
453 | |
454 | GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl); |
455 | |
456 | // Remember the top of EHStack before emitting the cleanup. |
457 | auto old_top = CGF.EHStack.stable_begin(); |
458 | CGF.EmitAutoVarCleanups(GroEmission); |
459 | auto top = CGF.EHStack.stable_begin(); |
460 | |
461 | // Make the cleanup conditional on gro.active |
462 | for (auto b = CGF.EHStack.find(top), e = CGF.EHStack.find(old_top); |
463 | b != e; b++) { |
464 | if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*b)) { |
465 | assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?")((!Cleanup->hasActiveFlag() && "cleanup already has active flag?" ) ? static_cast<void> (0) : __assert_fail ("!Cleanup->hasActiveFlag() && \"cleanup already has active flag?\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/clang/lib/CodeGen/CGCoroutine.cpp" , 465, __PRETTY_FUNCTION__)); |
466 | Cleanup->setActiveFlag(GroActiveFlag); |
467 | Cleanup->setTestFlagInEHCleanup(); |
468 | Cleanup->setTestFlagInNormalCleanup(); |
469 | } |
470 | } |
471 | } |
472 | |
473 | void EmitGroInit() { |
474 | if (!GroActiveFlag.isValid()) { |
475 | // No Gro variable was allocated. Simply emit the call to |
476 | // get_return_object. |
477 | CGF.EmitStmt(S.getResultDecl()); |
478 | return; |
479 | } |
480 | |
481 | CGF.EmitAutoVarInit(GroEmission); |
482 | Builder.CreateStore(Builder.getTrue(), GroActiveFlag); |
483 | } |
484 | }; |
485 | } |
486 | |
487 | static void emitBodyAndFallthrough(CodeGenFunction &CGF, |
488 | const CoroutineBodyStmt &S, Stmt *Body) { |
489 | CGF.EmitStmt(Body); |
490 | const bool CanFallthrough = CGF.Builder.GetInsertBlock(); |
491 | if (CanFallthrough) |
492 | if (Stmt *OnFallthrough = S.getFallthroughHandler()) |
493 | CGF.EmitStmt(OnFallthrough); |
494 | } |
495 | |
496 | void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { |
497 | auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); |
498 | auto &TI = CGM.getContext().getTargetInfo(); |
499 | unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth(); |
500 | |
501 | auto *EntryBB = Builder.GetInsertBlock(); |
502 | auto *AllocBB = createBasicBlock("coro.alloc"); |
503 | auto *InitBB = createBasicBlock("coro.init"); |
504 | auto *FinalBB = createBasicBlock("coro.final"); |
505 | auto *RetBB = createBasicBlock("coro.ret"); |
506 | |
507 | auto *CoroId = Builder.CreateCall( |
508 | CGM.getIntrinsic(llvm::Intrinsic::coro_id), |
509 | {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr}); |
510 | createCoroData(*this, CurCoro, CoroId); |
511 | CurCoro.Data->SuspendBB = RetBB; |
512 | |
513 | // Backend is allowed to elide memory allocations, to help it, emit |
514 | // auto mem = coro.alloc() ? 0 : ... allocation code ...; |
515 | auto *CoroAlloc = Builder.CreateCall( |
516 | CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId}); |
517 | |
518 | Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB); |
519 | |
520 | EmitBlock(AllocBB); |
521 | auto *AllocateCall = EmitScalarExpr(S.getAllocate()); |
522 | auto *AllocOrInvokeContBB = Builder.GetInsertBlock(); |
523 | |
524 | // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided. |
525 | if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) { |
526 | auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure"); |
527 | |
528 | // See if allocation was successful. |
529 | auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy); |
530 | auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr); |
531 | Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB); |
532 | |
533 | // If not, return OnAllocFailure object. |
534 | EmitBlock(RetOnFailureBB); |
535 | EmitStmt(RetOnAllocFailure); |
536 | } |
537 | else { |
538 | Builder.CreateBr(InitBB); |
539 | } |
540 | |
541 | EmitBlock(InitBB); |
542 | |
543 | // Pass the result of the allocation to coro.begin. |
544 | auto *Phi = Builder.CreatePHI(VoidPtrTy, 2); |
545 | Phi->addIncoming(NullPtr, EntryBB); |
546 | Phi->addIncoming(AllocateCall, AllocOrInvokeContBB); |
547 | auto *CoroBegin = Builder.CreateCall( |
548 | CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi}); |
549 | CurCoro.Data->CoroBegin = CoroBegin; |
550 | |
551 | GetReturnObjectManager GroManager(*this, S); |
552 | GroManager.EmitGroAlloca(); |
553 | |
554 | CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB); |
555 | { |
556 | ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap); |
557 | CodeGenFunction::RunCleanupsScope ResumeScope(*this); |
558 | EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate()); |
559 | |
560 | // Create parameter copies. We do it before creating a promise, since an |
561 | // evolution of coroutine TS may allow promise constructor to observe |
562 | // parameter copies. |
563 | for (auto *PM : S.getParamMoves()) { |
564 | EmitStmt(PM); |
565 | ParamReplacer.addCopy(cast<DeclStmt>(PM)); |
566 | // TODO: if(CoroParam(...)) need to surround ctor and dtor |
567 | // for the copy, so that llvm can elide it if the copy is |
568 | // not needed. |
569 | } |
570 | |
571 | EmitStmt(S.getPromiseDeclStmt()); |
572 | |
573 | Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); |
574 | auto *PromiseAddrVoidPtr = |
575 | new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); |
576 | // Update CoroId to refer to the promise. We could not do it earlier because |
577 | // promise local variable was not emitted yet. |
578 | CoroId->setArgOperand(1, PromiseAddrVoidPtr); |
579 | |
580 | // Now we have the promise, initialize the GRO |
581 | GroManager.EmitGroInit(); |
582 | |
583 | EHStack.pushCleanup<CallCoroEnd>(EHCleanup); |
584 | |
585 | CurCoro.Data->CurrentAwaitKind = AwaitKind::Init; |
586 | EmitStmt(S.getInitSuspendStmt()); |
587 | CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB); |
588 | |
589 | CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal; |
590 | |
591 | if (auto *OnException = S.getExceptionHandler()) { |
592 | auto Loc = S.getLocStart(); |
593 | CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr, OnException); |
594 | auto *TryStmt = CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch); |
595 | |
596 | EnterCXXTryStmt(*TryStmt); |
597 | emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock()); |
598 | ExitCXXTryStmt(*TryStmt); |
599 | } |
600 | else { |
601 | emitBodyAndFallthrough(*this, S, S.getBody()); |
602 | } |
603 | |
604 | // See if we need to generate final suspend. |
605 | const bool CanFallthrough = Builder.GetInsertBlock(); |
606 | const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0; |
607 | if (CanFallthrough || HasCoreturns) { |
608 | EmitBlock(FinalBB); |
609 | CurCoro.Data->CurrentAwaitKind = AwaitKind::Final; |
610 | EmitStmt(S.getFinalSuspendStmt()); |
611 | } else { |
612 | // We don't need FinalBB. Emit it to make sure the block is deleted. |
613 | EmitBlock(FinalBB, /*IsFinished=*/true); |
614 | } |
615 | } |
616 | |
617 | EmitBlock(RetBB); |
618 | // Emit coro.end before getReturnStmt (and parameter destructors), since |
619 | // resume and destroy parts of the coroutine should not include them. |
620 | llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end); |
621 | Builder.CreateCall(CoroEnd, {NullPtr, Builder.getFalse()}); |
622 | |
623 | if (Stmt *Ret = S.getReturnStmt()) |
624 | EmitStmt(Ret); |
625 | } |
626 | |
627 | // Emit coroutine intrinsic and patch up arguments of the token type. |
628 | RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, |
629 | unsigned int IID) { |
630 | SmallVector<llvm::Value *, 8> Args; |
631 | switch (IID) { |
632 | default: |
633 | break; |
634 | // The coro.frame builtin is replaced with an SSA value of the coro.begin |
635 | // intrinsic. |
636 | case llvm::Intrinsic::coro_frame: { |
637 | if (CurCoro.Data && CurCoro.Data->CoroBegin) { |
638 | return RValue::get(CurCoro.Data->CoroBegin); |
639 | } |
640 | CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_begin " |
641 | "has been used earlier in this function"); |
642 | auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy()); |
643 | return RValue::get(NullPtr); |
644 | } |
645 | // The following three intrinsics take a token parameter referring to a token |
646 | // returned by earlier call to @llvm.coro.id. Since we cannot represent it in |
647 | // builtins, we patch it up here. |
648 | case llvm::Intrinsic::coro_alloc: |
649 | case llvm::Intrinsic::coro_begin: |
650 | case llvm::Intrinsic::coro_free: { |
651 | if (CurCoro.Data && CurCoro.Data->CoroId) { |
652 | Args.push_back(CurCoro.Data->CoroId); |
653 | break; |
654 | } |
655 | CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has" |
656 | " been used earlier in this function"); |
657 | // Fallthrough to the next case to add TokenNone as the first argument. |
658 | LLVM_FALLTHROUGH[[clang::fallthrough]]; |
659 | } |
660 | // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first |
661 | // argument. |
662 | case llvm::Intrinsic::coro_suspend: |
663 | Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext())); |
664 | break; |
665 | } |
666 | for (auto &Arg : E->arguments()) |
667 | Args.push_back(EmitScalarExpr(Arg)); |
668 | |
669 | llvm::Value *F = CGM.getIntrinsic(IID); |
670 | llvm::CallInst *Call = Builder.CreateCall(F, Args); |
671 | |
672 | // Note: The following code is to enable to emit coro.id and coro.begin by |
673 | // hand to experiment with coroutines in C. |
674 | // If we see @llvm.coro.id remember it in the CoroData. We will update |
675 | // coro.alloc, coro.begin and coro.free intrinsics to refer to it. |
676 | if (IID == llvm::Intrinsic::coro_id) { |
677 | createCoroData(*this, CurCoro, Call, E); |
678 | } |
679 | else if (IID == llvm::Intrinsic::coro_begin) { |
680 | if (CurCoro.Data) |
681 | CurCoro.Data->CoroBegin = Call; |
682 | } |
683 | else if (IID == llvm::Intrinsic::coro_free) { |
684 | // Remember the last coro_free as we need it to build the conditional |
685 | // deletion of the coroutine frame. |
686 | if (CurCoro.Data) |
687 | CurCoro.Data->LastCoroFree = Call; |
688 | } |
689 | return RValue::get(Call); |
690 | } |