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