clang 23.0.0git
CGCoroutine.cpp
Go to the documentation of this file.
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 "CGDebugInfo.h"
15#include "CodeGenFunction.h"
16#include "clang/AST/StmtCXX.h"
18#include "llvm/ADT/ScopeExit.h"
19
20using namespace clang;
21using namespace CodeGen;
22
23using llvm::Value;
24using llvm::BasicBlock;
25
26namespace {
27enum class AwaitKind { Init, Normal, Yield, Final };
28static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", "yield",
29 "final"};
30}
31
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 // A branch to this block after final.cleanup or final.ready
47 llvm::BasicBlock *FinalExit = nullptr;
48
49 // The promise type's 'unhandled_exception' handler, if it defines one.
51
52 // A temporary i1 alloca that stores whether 'await_resume' threw an
53 // exception. If it did, 'true' is stored in this variable, and the coroutine
54 // body must be skipped. If the promise type does not define an exception
55 // handler, this is null.
56 llvm::Value *ResumeEHVar = nullptr;
57
58 // Stores the jump destination just before the coroutine memory is freed.
59 // This is the destination that every suspend point jumps to for the cleanup
60 // branch.
62
63 // Stores the jump destination just before the final suspend. The co_return
64 // statements jumps to this point after calling return_xxx promise member.
66
67 // A cleanup flag for the coroutine return value object when it is initialized
68 // directly by the get-return-object invocation. It models the standard's
69 // initial-await-resume-called guard for exceptions thrown during coroutine
70 // startup, before the initial await_resume starts.
72
73 // Stores the llvm.coro.id emitted in the function so that we can supply it
74 // as the first argument to coro.begin, coro.alloc and coro.free intrinsics.
75 // Note: llvm.coro.id returns a token that cannot be directly expressed in a
76 // builtin.
77 llvm::CallInst *CoroId = nullptr;
78
79 // Stores the llvm.coro.begin emitted in the function so that we can replace
80 // all coro.frame intrinsics with direct SSA value of coro.begin that returns
81 // the address of the coroutine frame of the current coroutine.
82 llvm::CallInst *CoroBegin = nullptr;
83
84 // Stores the last emitted coro.free for the deallocate expressions, we use it
85 // to wrap dealloc code with if(auto mem = coro.free) dealloc(mem).
86 llvm::CallInst *LastCoroFree = nullptr;
87
88 // If coro.id came from the builtin, remember the expression to give better
89 // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
90 // EmitCoroutineBody.
91 CallExpr const *CoroIdExpr = nullptr;
92};
93
94// Defining these here allows to keep CGCoroData private to this file.
97
100 llvm::CallInst *CoroId,
101 CallExpr const *CoroIdExpr = nullptr) {
102 if (CurCoro.Data) {
103 if (CurCoro.Data->CoroIdExpr)
104 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
105 "only one __builtin_coro_id can be used in a function");
106 else if (CoroIdExpr)
107 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
108 "__builtin_coro_id shall not be used in a C++ coroutine");
109 else
110 llvm_unreachable("EmitCoroutineBodyStatement called twice?");
111
112 return;
113 }
114
115 CurCoro.Data = std::make_unique<CGCoroData>();
116 CurCoro.Data->CoroId = CoroId;
117 CurCoro.Data->CoroIdExpr = CoroIdExpr;
118}
119
120// Synthesize a pretty name for a suspend point.
121static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) {
122 unsigned No = 0;
123 switch (Kind) {
124 case AwaitKind::Init:
125 case AwaitKind::Final:
126 break;
127 case AwaitKind::Normal:
128 No = ++Coro.AwaitNum;
129 break;
130 case AwaitKind::Yield:
131 No = ++Coro.YieldNum;
132 break;
133 }
134 SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]);
135 if (No > 1) {
136 Twine(No).toVector(Prefix);
137 }
138 return Prefix;
139}
140
141// Check if function can throw based on prototype noexcept, also works for
142// destructors which are implicitly noexcept but can be marked noexcept(false).
143static bool FunctionCanThrow(const FunctionDecl *D) {
144 const auto *Proto = D->getType()->getAs<FunctionProtoType>();
145 if (!Proto) {
146 // Function proto is not found, we conservatively assume throwing.
147 return true;
148 }
149 return !isNoexceptExceptionSpec(Proto->getExceptionSpecType()) ||
150 Proto->canThrow() != CT_Cannot;
151}
152
153static bool StmtCanThrow(const Stmt *S) {
154 if (const auto *CE = dyn_cast<CallExpr>(S)) {
155 const auto *Callee = CE->getDirectCallee();
156 if (!Callee)
157 // We don't have direct callee. Conservatively assume throwing.
158 return true;
159
160 if (FunctionCanThrow(Callee))
161 return true;
162
163 // Fall through to visit the children.
164 }
165
166 if (const auto *TE = dyn_cast<CXXBindTemporaryExpr>(S)) {
167 // Special handling of CXXBindTemporaryExpr here as calling of Dtor of the
168 // temporary is not part of `children()` as covered in the fall through.
169 // We need to mark entire statement as throwing if the destructor of the
170 // temporary throws.
171 const auto *Dtor = TE->getTemporary()->getDestructor();
172 if (FunctionCanThrow(Dtor))
173 return true;
174
175 // Fall through to visit the children.
176 }
177
178 for (const auto *child : S->children())
179 if (StmtCanThrow(child))
180 return true;
181
182 return false;
183}
184
185// Emit suspend expression which roughly looks like:
186//
187// auto && x = CommonExpr();
188// if (!x.await_ready()) {
189// llvm_coro_save();
190// llvm_coro_await_suspend(&x, frame, wrapper) (*) (**)
191// llvm_coro_suspend(); (***)
192// }
193// x.await_resume();
194//
195// where the result of the entire expression is the result of x.await_resume()
196//
197// (*) llvm_coro_await_suspend_{void, bool, handle} is lowered to
198// wrapper(&x, frame) when it's certain not to interfere with
199// coroutine transform. await_suspend expression is
200// asynchronous to the coroutine body and not all analyses
201// and transformations can handle it correctly at the moment.
202//
203// Wrapper function encapsulates x.await_suspend(...) call and looks like:
204//
205// auto __await_suspend_wrapper(auto& awaiter, void* frame) {
206// std::coroutine_handle<> handle(frame);
207// return awaiter.await_suspend(handle);
208// }
209//
210// (**) If x.await_suspend return type is bool, it allows to veto a suspend:
211// if (x.await_suspend(...))
212// llvm_coro_suspend();
213//
214// (***) llvm_coro_suspend() encodes three possible continuations as
215// a switch instruction:
216//
217// %where-to = call i8 @llvm.coro.suspend(...)
218// switch i8 %where-to, label %coro.ret [ ; jump to epilogue to suspend
219// i8 0, label %yield.ready ; go here when resumed
220// i8 1, label %yield.cleanup ; go here when destroyed
221// ]
222//
223// See llvm's docs/Coroutines.md for more details.
224//
225namespace {
226 struct LValueOrRValue {
227 LValue LV;
228 RValue RV;
229 };
230}
231static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro,
232 CoroutineSuspendExpr const &S,
233 AwaitKind Kind, AggValueSlot aggSlot,
234 bool ignoreResult, bool forLValue) {
235 auto *E = S.getCommonExpr();
236
237 auto CommonBinder =
239 llvm::scope_exit UnbindCommonOnExit([&] { CommonBinder.unbind(CGF); });
240
241 auto Prefix = buildSuspendPrefixStr(Coro, Kind);
242 BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready"));
243 BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend"));
244 BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup"));
245
246 // If expression is ready, no need to suspend.
247 CGF.EmitBranchOnBoolExpr(S.getReadyExpr(), ReadyBlock, SuspendBlock, 0);
248
249 // Otherwise, emit suspend logic.
250 CGF.EmitBlock(SuspendBlock);
251
252 auto &Builder = CGF.Builder;
253 llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save);
254 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
255 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
256
257 auto SuspendWrapper = CodeGenFunction(CGF.CGM).generateAwaitSuspendWrapper(
258 CGF.CurFn->getName(), Prefix, S);
259
260 CGF.CurCoro.InSuspendBlock = true;
261
262 assert(CGF.CurCoro.Data && CGF.CurCoro.Data->CoroBegin &&
263 "expected to be called in coroutine context");
264
265 SmallVector<llvm::Value *, 3> SuspendIntrinsicCallArgs;
266 SuspendIntrinsicCallArgs.push_back(
268
269 SuspendIntrinsicCallArgs.push_back(CGF.CurCoro.Data->CoroBegin);
270 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
271
272 const auto SuspendReturnType = S.getSuspendReturnType();
273 llvm::Intrinsic::ID AwaitSuspendIID;
274
275 switch (SuspendReturnType) {
277 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
278 break;
280 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
281 break;
283 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
284 break;
285 }
286
287 llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID);
288
289 // SuspendHandle might throw since it also resumes the returned handle.
290 const bool AwaitSuspendCanThrow =
291 SuspendReturnType ==
294
295 llvm::CallBase *SuspendRet = nullptr;
296 // FIXME: add call attributes?
297 if (AwaitSuspendCanThrow)
298 SuspendRet =
299 CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendIntrinsicCallArgs);
300 else
301 SuspendRet = CGF.EmitNounwindRuntimeCall(AwaitSuspendIntrinsic,
302 SuspendIntrinsicCallArgs);
303
304 assert(SuspendRet);
305 CGF.CurCoro.InSuspendBlock = false;
306
307 switch (SuspendReturnType) {
309 assert(SuspendRet->getType()->isVoidTy());
310 break;
312 assert(SuspendRet->getType()->isIntegerTy());
313
314 // Veto suspension if requested by bool returning await_suspend.
315 BasicBlock *RealSuspendBlock =
316 CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
317 CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
318 CGF.EmitBlock(RealSuspendBlock);
319 break;
320 }
322 assert(SuspendRet->getType()->isVoidTy());
323 break;
324 }
325 }
326
327 // Emit the suspend point.
328 const bool IsFinalSuspend = (Kind == AwaitKind::Final);
329 llvm::Function *CoroSuspend =
330 CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_suspend);
331 auto *SuspendResult = Builder.CreateCall(
332 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});
333
334 // Create a switch capturing three possible continuations.
335 auto *Switch = Builder.CreateSwitch(SuspendResult, Coro.SuspendBB, 2);
336 Switch->addCase(Builder.getInt8(0), ReadyBlock);
337 Switch->addCase(Builder.getInt8(1), CleanupBlock);
338
339 // Emit cleanup for this suspend point.
340 CGF.EmitBlock(CleanupBlock);
342 if (IsFinalSuspend)
343 Coro.FinalExit = CleanupBlock->getSingleSuccessor();
344
345 // Emit await_resume expression.
346 CGF.EmitBlock(ReadyBlock);
347 if (Kind == AwaitKind::Init && Coro.InitialReturnObjectActiveFlag.isValid()) {
348 Builder.CreateStore(Builder.getFalse(), Coro.InitialReturnObjectActiveFlag);
350 }
351
352 // Exception handling requires additional IR. If the 'await_resume' function
353 // is marked as 'noexcept', we avoid generating this additional IR.
354 CXXTryStmt *TryStmt = nullptr;
355 if (Coro.ExceptionHandler && Kind == AwaitKind::Init &&
357 Coro.ResumeEHVar =
358 CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh"));
359 Builder.CreateFlagStore(true, Coro.ResumeEHVar);
360
361 auto Loc = S.getResumeExpr()->getExprLoc();
362 auto *Catch = new (CGF.getContext())
363 CXXCatchStmt(Loc, /*exDecl=*/nullptr, Coro.ExceptionHandler);
364 auto *TryBody = CompoundStmt::Create(CGF.getContext(), S.getResumeExpr(),
365 FPOptionsOverride(), Loc, Loc);
366 TryStmt = CXXTryStmt::Create(CGF.getContext(), Loc, TryBody, Catch);
367 CGF.EnterCXXTryStmt(*TryStmt);
368 CGF.EmitStmt(TryBody);
369 // We don't use EmitCXXTryStmt here. We need to store to ResumeEHVar that
370 // doesn't exist in the body.
371 Builder.CreateFlagStore(false, Coro.ResumeEHVar);
372 CGF.ExitCXXTryStmt(*TryStmt);
373 LValueOrRValue Res;
374 // We are not supposed to obtain the value from init suspend await_resume().
375 Res.RV = RValue::getIgnored();
376 return Res;
377 }
378
379 LValueOrRValue Res;
380 if (forLValue)
381 Res.LV = CGF.EmitLValue(S.getResumeExpr());
382 else
383 Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
384
385 return Res;
386}
387
389 AggValueSlot aggSlot,
390 bool ignoreResult) {
391 return emitSuspendExpression(*this, *CurCoro.Data, E,
392 CurCoro.Data->CurrentAwaitKind, aggSlot,
393 ignoreResult, /*forLValue*/false).RV;
394}
396 AggValueSlot aggSlot,
397 bool ignoreResult) {
398 return emitSuspendExpression(*this, *CurCoro.Data, E, AwaitKind::Yield,
399 aggSlot, ignoreResult, /*forLValue*/false).RV;
400}
401
403 ++CurCoro.Data->CoreturnCount;
404 const Expr *RV = S.getOperand();
405 if (RV && RV->getType()->isVoidType() && !isa<InitListExpr>(RV)) {
406 // Make sure to evaluate the non initlist expression of a co_return
407 // with a void expression for side effects.
408 RunCleanupsScope cleanupScope(*this);
409 EmitIgnoredExpr(RV);
410 }
412 EmitBranchThroughCleanup(CurCoro.Data->FinalJD);
413}
414
415
416#ifndef NDEBUG
418 const CoroutineSuspendExpr *E) {
419 const auto *RE = E->getResumeExpr();
420 // Is it possible for RE to be a CXXBindTemporaryExpr wrapping
421 // a MemberCallExpr?
422 assert(isa<CallExpr>(RE) && "unexpected suspend expression type");
423 return cast<CallExpr>(RE)->getCallReturnType(Ctx);
424}
425#endif
426
427llvm::Function *
429 Twine const &SuspendPointName,
430 CoroutineSuspendExpr const &S) {
431 std::string FuncName =
432 (CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str();
433
435
436 auto *AwaiterDecl =
438 auto *FrameDecl =
440 QualType ReturnTy = S.getSuspendExpr()->getType();
441
442 FunctionArgList args{AwaiterDecl, FrameDecl};
443 const CGFunctionInfo &FI =
444 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
445
446 llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
447
448 llvm::Function *Fn = llvm::Function::Create(
449 LTy, llvm::GlobalValue::InternalLinkage, FuncName, &CGM.getModule());
450
451 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
452 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
453
454 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
455
456 Fn->setMustProgress();
457 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
458 Fn->addFnAttr("sample-profile-suffix-elision-policy", "selected");
459
460 StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
461
462 // FIXME: add TBAA metadata to the loads
463 llvm::Value *AwaiterPtr = Builder.CreateLoad(GetAddrOfLocalVar(AwaiterDecl));
464 auto AwaiterLValue =
465 MakeNaturalAlignAddrLValue(AwaiterPtr, AwaiterDecl->getType());
466
467 CurAwaitSuspendWrapper.FramePtr =
468 Builder.CreateLoad(GetAddrOfLocalVar(FrameDecl));
469
471 *this, S.getOpaqueValue(), AwaiterLValue);
472
473 auto *SuspendRet = EmitScalarExpr(S.getSuspendExpr());
474
475 llvm::scope_exit UnbindCommonOnExit([&] { AwaiterBinder.unbind(*this); });
476 if (SuspendRet != nullptr) {
477 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
478 Builder.CreateStore(SuspendRet, ReturnValue);
479 }
480
481 CurAwaitSuspendWrapper.FramePtr = nullptr;
483 return Fn;
484}
485
486LValue
488 assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&
489 "Can't have a scalar return unless the return type is a "
490 "reference type!");
491 return emitSuspendExpression(*this, *CurCoro.Data, *E,
492 CurCoro.Data->CurrentAwaitKind, AggValueSlot::ignored(),
493 /*ignoreResult*/false, /*forLValue*/true).LV;
494}
495
496LValue
498 assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&
499 "Can't have a scalar return unless the return type is a "
500 "reference type!");
501 return emitSuspendExpression(*this, *CurCoro.Data, *E,
502 AwaitKind::Yield, AggValueSlot::ignored(),
503 /*ignoreResult*/false, /*forLValue*/true).LV;
504}
505
506// Hunts for the parameter reference in the parameter copy/move declaration.
507namespace {
508struct GetParamRef : public StmtVisitor<GetParamRef> {
509public:
510 DeclRefExpr *Expr = nullptr;
511 GetParamRef() {}
512 void VisitDeclRefExpr(DeclRefExpr *E) {
513 assert(Expr == nullptr && "multilple declref in param move");
514 Expr = E;
515 }
516 void VisitStmt(Stmt *S) {
517 for (auto *C : S->children()) {
518 if (C)
519 Visit(C);
520 }
521 }
522};
523}
524
525// This class replaces references to parameters to their copies by changing
526// the addresses in CGF.LocalDeclMap and restoring back the original values in
527// its destructor.
528
529namespace {
530 struct ParamReferenceReplacerRAII {
531 CodeGenFunction::DeclMapTy SavedLocals;
532 CodeGenFunction::DeclMapTy& LocalDeclMap;
533
534 ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap)
535 : LocalDeclMap(LocalDeclMap) {}
536
537 void addCopy(DeclStmt const *PM) {
538 // Figure out what param it refers to.
539
540 assert(PM->isSingleDecl());
541 VarDecl const*VD = static_cast<VarDecl const*>(PM->getSingleDecl());
542 Expr const *InitExpr = VD->getInit();
543 GetParamRef Visitor;
544 Visitor.Visit(const_cast<Expr*>(InitExpr));
545 assert(Visitor.Expr);
546 DeclRefExpr *DREOrig = Visitor.Expr;
547 auto *PD = DREOrig->getDecl();
548
549 auto it = LocalDeclMap.find(PD);
550 assert(it != LocalDeclMap.end() && "parameter is not found");
551 SavedLocals.insert({ PD, it->second });
552
553 auto copyIt = LocalDeclMap.find(VD);
554 assert(copyIt != LocalDeclMap.end() && "parameter copy is not found");
555 it->second = copyIt->getSecond();
556 }
557
558 ~ParamReferenceReplacerRAII() {
559 for (auto&& SavedLocal : SavedLocals) {
560 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
561 }
562 }
563 };
564}
565
566// For WinEH exception representation backend needs to know what funclet coro.end
567// belongs to. That information is passed in a funclet bundle.
568static SmallVector<llvm::OperandBundleDef, 1>
571
572 if (llvm::Instruction *EHPad = CGF.CurrentFuncletPad)
573 BundleList.emplace_back("funclet", EHPad);
574
575 return BundleList;
576}
577
578namespace {
579// We will insert coro.end to cut any of the destructors for objects that
580// do not need to be destroyed once the coroutine is resumed.
581// See llvm/docs/Coroutines.md for more details about coro.end.
582struct CallCoroEnd final : public EHScopeStack::Cleanup {
583 void Emit(CodeGenFunction &CGF, Flags flags) override {
584 auto &CGM = CGF.CGM;
585 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
586 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
587 // See if we have a funclet bundle to associate coro.end with. (WinEH)
588 auto Bundles = getBundlesForCoroEnd(CGF);
589 CGF.Builder.CreateCall(
590 CoroEndFn,
591 {NullPtr, CGF.Builder.getTrue(),
592 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
593 Bundles);
594 if (Bundles.empty()) {
595 // Otherwise, (landingpad model), create a conditional branch that leads
596 // either to a cleanup block or a block with EH resume instruction.
597 auto *ResumeBB = CGF.getEHResumeBlock(/*isCleanup=*/true);
598 auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont");
599 auto *CoroIsInRampFn = CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
600 auto *CoroIsInRamp = CGF.Builder.CreateCall(CoroIsInRampFn);
601 CGF.Builder.CreateCondBr(CoroIsInRamp, CleanupContBB, ResumeBB);
602 CGF.EmitBlock(CleanupContBB);
603 }
604 }
605};
606}
607
608namespace {
609// Make sure to call coro.delete on scope exit.
610struct CallCoroDelete final : public EHScopeStack::Cleanup {
611 Stmt *Deallocate;
612
613 // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
614
615 // Note: That deallocation will be emitted twice: once for a normal exit and
616 // once for exceptional exit. This usage is safe because Deallocate does not
617 // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
618 // builds a single call to a deallocation function which is safe to emit
619 // multiple times.
620 void Emit(CodeGenFunction &CGF, Flags) override {
621 // Remember the current point, as we are going to emit deallocation code
622 // first to get to coro.free instruction that is an argument to a delete
623 // call.
624 BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock();
625
626 auto *FreeBB = CGF.createBasicBlock("coro.free");
627 CGF.EmitBlock(FreeBB);
628 CGF.EmitStmt(Deallocate);
629
630 auto *AfterFreeBB = CGF.createBasicBlock("after.coro.free");
631 CGF.EmitBlock(AfterFreeBB);
632
633 // We should have captured coro.free from the emission of deallocate.
634 auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;
635 if (!CoroFree) {
636 CGF.CGM.Error(Deallocate->getBeginLoc(),
637 "Deallocation expressoin does not refer to coro.free");
638 return;
639 }
640
641 // Get back to the block we were originally and move coro.free there.
642 auto *InsertPt = SaveInsertBlock->getTerminator();
643 CoroFree->moveBefore(InsertPt->getIterator());
644 CGF.Builder.SetInsertPoint(InsertPt);
645
646 // Add if (auto *mem = coro.free) Deallocate;
647 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
648 auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr);
649 CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB);
650
651 // No longer need old terminator.
652 InsertPt->eraseFromParent();
653 CGF.Builder.SetInsertPoint(AfterFreeBB);
654
655 auto *CoroDeadFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_dead);
656 CGF.Builder.CreateCall(CoroDeadFn, {CGF.CurCoro.Data->CoroBegin});
657 }
658 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
659};
660}
661
662namespace {
663struct GetReturnObjectManager {
664 CodeGenFunction &CGF;
665 CGBuilderTy &Builder;
666 const CoroutineBodyStmt &S;
667 // When true, performs RVO for the return object.
668 bool DirectEmit = false;
669
670 Address GroActiveFlag;
671 CodeGenFunction::AutoVarEmission GroEmission;
672 std::unique_ptr<CodeGenFunction::RunCleanupsScope> GroScope;
673
674 GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S)
675 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()),
676 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {
677 // The call to get_­return_­object is sequenced before the call to
678 // initial_­suspend and is invoked at most once, but there are caveats
679 // regarding on whether the prvalue result object may be initialized
680 // directly/eager or delayed, depending on the types involved.
681 //
682 // More info at https://github.com/cplusplus/papers/issues/1414
683 //
684 // The general cases:
685 // 1. Same type of get_return_object and coroutine return type (direct
686 // emission):
687 // - Constructed in the return slot.
688 // 2. Different types (delayed emission):
689 // - Constructed temporary object prior to initial suspend initialized with
690 // a call to get_return_object()
691 // - When coroutine needs to to return to the caller and needs to construct
692 // return value for the coroutine it is initialized with expiring value of
693 // the temporary obtained above.
694 //
695 // Direct emission for void returning coroutines or GROs.
696 DirectEmit = [&]() {
697 auto *RVI = S.getReturnValueInit();
698 assert(RVI && "expected RVI");
699 auto GroType = RVI->getType();
700 return CGF.getContext().hasSameType(GroType, CGF.FnRetTy);
701 }();
702 }
703
704 // The gro variable has to outlive coroutine frame and coroutine promise, but,
705 // it can only be initialized after coroutine promise was created. Thus,
706 // EmitGroActive emits a flag and sets it to false. Later when coroutine
707 // promise is available we initialize the gro and set the flag indicating that
708 // the cleanup is now active.
709 void EmitGroActive() {
710 if (DirectEmit)
711 return;
712
713 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.getResultDecl());
714 if (!GroDeclStmt) {
715 // If get_return_object returns void, no need to do an alloca.
716 return;
717 }
718
719 // Set GRO flag that it is not initialized yet
720 GroActiveFlag = CGF.CreateTempAlloca(Builder.getInt1Ty(), CharUnits::One(),
721 "gro.active");
722 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
723 }
724
725 void EmitGroAlloca() {
726 if (DirectEmit)
727 return;
728
729 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.getResultDecl());
730 if (!GroDeclStmt) {
731 // If get_return_object returns void, no need to do an alloca.
732 return;
733 }
734
735 auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl());
736
737 GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
738
739 if (!GroVarDecl->isNRVOVariable()) {
740 // NRVO variables don't have allocas and won't have the same issue.
741 auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
743 assert(GroAlloca && "expected alloca to be emitted");
744 GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
745 llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
746 }
747
748 GroScope = std::make_unique<CodeGenFunction::RunCleanupsScope>(CGF);
749 // Remember the top of EHStack before emitting the cleanup.
750 auto old_top = CGF.EHStack.stable_begin();
751 CGF.EmitAutoVarCleanups(GroEmission);
752 auto top = CGF.EHStack.stable_begin();
753
754 // Make the cleanup conditional on gro.active
755 for (auto b = CGF.EHStack.find(top), e = CGF.EHStack.find(old_top); b != e;
756 b++) {
757 if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*b)) {
758 assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?");
759 Cleanup->setActiveFlag(GroActiveFlag);
760 Cleanup->setTestFlagInEHCleanup();
761 Cleanup->setTestFlagInNormalCleanup();
762 }
763 }
764 }
765
766 void EmitDirectReturnObjectCleanup() {
767 if (!DirectEmit || !CGF.ReturnValue.isValid())
768 return;
769
770 QualType RetTy = CGF.FnRetTy;
772 if (DtorKind == QualType::DK_none)
773 return;
774 if (!CGF.needsEHCleanup(DtorKind))
775 return;
776
777 Address ActiveFlag = CGF.CreateTempAlloca(
778 Builder.getInt1Ty(), CharUnits::One(), "coro.result.active");
779 Builder.CreateStore(Builder.getFalse(), ActiveFlag);
780 CGF.CurCoro.Data->InitialReturnObjectActiveFlag = ActiveFlag;
781
782 auto OldTop = CGF.EHStack.stable_begin();
783 CGF.pushDestroy(EHCleanup, CGF.ReturnValue, RetTy,
784 CGF.getDestroyer(DtorKind),
785 /*useEHCleanupForArray*/ true);
786 auto Top = CGF.EHStack.stable_begin();
787
788 for (auto B = CGF.EHStack.find(Top), E = CGF.EHStack.find(OldTop); B != E;
789 ++B) {
790 if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*B)) {
791 assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?");
792 Cleanup->setActiveFlag(ActiveFlag);
793 Cleanup->setTestFlagInEHCleanup();
794 }
795 }
796 }
797
798 void EmitGroInit() {
799 if (DirectEmit) {
800 // ReturnValue should be valid as long as the coroutine's return type
801 // is not void. The assertion could help us to reduce the check later.
802 assert(CGF.ReturnValue.isValid() == (bool)S.getReturnStmt());
803 // Now we have the promise, initialize the GRO.
804 // We need to emit `get_return_object` first. According to:
805 // [dcl.fct.def.coroutine]p7
806 // The call to get_return_­object is sequenced before the call to
807 // initial_suspend and is invoked at most once.
808 //
809 // So we couldn't emit return value when we emit return statment,
810 // otherwise the call to get_return_object wouldn't be in front
811 // of initial_suspend.
812 if (CGF.ReturnValue.isValid()) {
813 EmitDirectReturnObjectCleanup();
816 /*IsInit*/ true);
817 if (CGF.CurCoro.Data->InitialReturnObjectActiveFlag.isValid())
818 Builder.CreateStore(Builder.getTrue(),
819 CGF.CurCoro.Data->InitialReturnObjectActiveFlag);
820 }
821 return;
822 }
823
824 if (!GroActiveFlag.isValid()) {
825 // No Gro variable was allocated. Simply emit the call to
826 // get_return_object.
827 CGF.EmitStmt(S.getResultDecl());
828 return;
829 }
830
831 CGF.EmitAutoVarInit(GroEmission);
832 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
833 }
834 // The GRO returns either when it is first suspended or when it completes
835 // without ever being suspended. The EmitGroConv function evaluates these
836 // conditions and perform the conversion if needed.
837 //
838 // Before EmitGroConv():
839 // final.exit:
840 // switch i32 %cleanup.dest, label %destroy [
841 // i32 0, label %after.ready
842 // ]
843 //
844 // after.ready:
845 // ; (empty)
846 //
847 // After EmitGroConv():
848 // final.exit:
849 // switch i32 %cleanup.dest, label %destroy [
850 // i32 0, label %pre.gro.conv
851 // ]
852 //
853 // pre.gro.conv:
854 // %IsFinalExit = phi i1 [ false, %any.suspend ], [ true, %final.exit ]
855 // %InRamp = call i1 @llvm.coro.is_in_ramp()
856 // br i1 %InRamp, label %gro.conv, label %after.gro.conv
857 //
858 // gro.conv:
859 // ; GRO conversion
860 // br label %after.gro.conv
861 //
862 // after.gro.conv:
863 // br i1 %IsFinalExit, label %after.ready, label %coro.ret
864 void EmitGroConv(BasicBlock *RetBB) {
865 auto *AfterReadyBB = Builder.GetInsertBlock();
866 Builder.ClearInsertionPoint();
867
868 auto *PreConvBB = CGF.CurCoro.Data->SuspendBB;
869 CGF.EmitBlock(PreConvBB);
870 // If final.exit exists, redirect it to PreConvBB
871 llvm::PHINode *IsFinalExit = nullptr;
872 if (BasicBlock *FinalExit = CGF.CurCoro.Data->FinalExit) {
873 assert(AfterReadyBB &&
874 AfterReadyBB->getSinglePredecessor() == FinalExit &&
875 "Expect fallthrough from final.exit block");
876 AfterReadyBB->replaceAllUsesWith(PreConvBB);
877 PreConvBB->moveBefore(AfterReadyBB);
878
879 // If true, coroutine completes and should be destroyed after conversion
880 IsFinalExit =
881 Builder.CreatePHI(Builder.getInt1Ty(), llvm::pred_size(PreConvBB));
882 for (auto *Pred : llvm::predecessors(PreConvBB)) {
883 auto *V = (Pred == FinalExit) ? Builder.getTrue() : Builder.getFalse();
884 IsFinalExit->addIncoming(V, Pred);
885 }
886 }
887 auto *InRampFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
888 auto *InRamp = Builder.CreateCall(InRampFn, {}, "InRamp");
889 auto *ConvBB = CGF.createBasicBlock("gro.conv");
890 auto *AfterConvBB = CGF.createBasicBlock("after.gro.conv");
891 Builder.CreateCondBr(InRamp, ConvBB, AfterConvBB);
892
893 CGF.EmitBlock(ConvBB);
896 /*IsInit*/ true);
897 GroScope->ForceCleanup();
898 Builder.CreateBr(AfterConvBB);
899
900 CGF.EmitBlock(AfterConvBB);
901 if (IsFinalExit)
902 Builder.CreateCondBr(IsFinalExit, AfterReadyBB, RetBB);
903 else
904 Builder.CreateBr(RetBB);
905 Builder.SetInsertPoint(AfterReadyBB);
906 }
907};
908} // namespace
909
911 const CoroutineBodyStmt &S, Stmt *Body) {
912 CGF.EmitStmt(Body);
913 const bool CanFallthrough = CGF.Builder.GetInsertBlock();
914 if (CanFallthrough)
915 if (Stmt *OnFallthrough = S.getFallthroughHandler())
916 CGF.EmitStmt(OnFallthrough);
917}
918
920 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());
921 auto &TI = CGM.getContext().getTargetInfo();
922 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
923
924 auto *EntryBB = Builder.GetInsertBlock();
925 auto *AllocBB = createBasicBlock("coro.alloc");
926 auto *InitBB = createBasicBlock("coro.init");
927 auto *FinalBB = createBasicBlock("coro.final");
928 auto *CleanupBB = createBasicBlock("coro.cleanup");
929 auto *RetBB = createBasicBlock("coro.ret");
930
931 auto *CoroId = Builder.CreateCall(
932 CGM.getIntrinsic(llvm::Intrinsic::coro_id),
933 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
934 createCoroData(*this, CurCoro, CoroId);
935
936 GetReturnObjectManager GroManager(*this, S);
937 CurCoro.Data->SuspendBB =
938 GroManager.DirectEmit ? RetBB : createBasicBlock("pre.gvo.conv");
939 assert(ShouldEmitLifetimeMarkers &&
940 "Must emit lifetime intrinsics for coroutines");
941
942 // Backend is allowed to elide memory allocations, to help it, emit
943 // auto mem = coro.alloc() ? 0 : ... allocation code ...;
944 auto *CoroAlloc = Builder.CreateCall(
945 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
946
947 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
948
949 EmitBlock(AllocBB);
950 auto *AllocateCall = EmitScalarExpr(S.getAllocate());
951 auto *AllocOrInvokeContBB = Builder.GetInsertBlock();
952
953 // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
954 if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {
955 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
956
957 // See if allocation was successful.
958 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
959 auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr);
960 // Expect the allocation to be successful.
961 emitCondLikelihoodViaExpectIntrinsic(Cond, Stmt::LH_Likely);
962 Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB);
963
964 // If not, return OnAllocFailure object.
965 EmitBlock(RetOnFailureBB);
966 EmitStmt(RetOnAllocFailure);
967 }
968 else {
969 Builder.CreateBr(InitBB);
970 }
971
972 EmitBlock(InitBB);
973
974 // Pass the result of the allocation to coro.begin.
975 auto *Phi = Builder.CreatePHI(VoidPtrTy, 2);
976 Phi->addIncoming(NullPtr, EntryBB);
977 Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
978 auto *CoroBegin = Builder.CreateCall(
979 CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
980 CurCoro.Data->CoroBegin = CoroBegin;
981 {
983 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
984 CodeGenFunction::RunCleanupsScope ResumeScope(*this);
985 EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate());
986
987 // Create mapping between parameters and copy-params for coroutine function.
989 assert(
990 (ParamMoves.size() == 0 || (ParamMoves.size() == FnArgs.size())) &&
991 "ParamMoves and FnArgs should be the same size for coroutine function");
992 if (ParamMoves.size() == FnArgs.size() && DI)
993 for (const auto Pair : llvm::zip(FnArgs, ParamMoves))
995 {std::get<0>(Pair), std::get<1>(Pair)});
996
997 // Create parameter copies. We do it before creating a promise, since an
998 // evolution of coroutine TS may allow promise constructor to observe
999 // parameter copies.
1000 for (const ParmVarDecl *Parm : FnArgs) {
1001 // If the original param is in an alloca, exclude it from the coroutine
1002 // frame. The parameter copy will be part of the frame, but the original
1003 // parameter memory should remain on the stack. This is necessary to
1004 // ensure that parameters destroyed in callees, as with `trivial_abi` or
1005 // in the MSVC C++ ABI, are appropriately destroyed after setting up the
1006 // coroutine.
1007 Address ParmAddr = GetAddrOfLocalVar(Parm);
1008 if (auto *ParmAlloca =
1009 dyn_cast<llvm::AllocaInst>(ParmAddr.getBasePointer())) {
1010 ParmAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
1011 llvm::MDNode::get(CGM.getLLVMContext(), {}));
1012 }
1013 }
1014 for (auto *PM : S.getParamMoves()) {
1015 EmitStmt(PM);
1016 ParamReplacer.addCopy(cast<DeclStmt>(PM));
1017 // TODO: if(CoroParam(...)) need to surround ctor and dtor
1018 // for the copy, so that llvm can elide it if the copy is
1019 // not needed.
1020 }
1021
1022 GroManager.EmitGroActive();
1024
1025 Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl());
1026 // Update CoroId to refer to the promise. We could not do it earlier because
1027 // promise local variable was not emitted yet.
1028 CoroId->setArgOperand(1, PromiseAddr.emitRawPointer(*this));
1029
1030 // Now we have the promise, initialize the GRO
1031 GroManager.EmitGroAlloca();
1032 GroManager.EmitGroInit();
1033
1034 EHStack.pushCleanup<CallCoroEnd>(EHCleanup);
1035
1036 CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(CleanupBB);
1037 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
1038 CurCoro.Data->ExceptionHandler = S.getExceptionHandler();
1040 CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
1041
1042 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
1043
1044 if (CurCoro.Data->ExceptionHandler) {
1045 // If we generated IR to record whether an exception was thrown from
1046 // 'await_resume', then use that IR to determine whether the coroutine
1047 // body should be skipped.
1048 // If we didn't generate the IR (perhaps because 'await_resume' was marked
1049 // as 'noexcept'), then we skip this check.
1050 BasicBlock *ContBB = nullptr;
1051 if (CurCoro.Data->ResumeEHVar) {
1052 BasicBlock *BodyBB = createBasicBlock("coro.resumed.body");
1053 ContBB = createBasicBlock("coro.resumed.cont");
1054 Value *SkipBody = Builder.CreateFlagLoad(CurCoro.Data->ResumeEHVar,
1055 "coro.resumed.eh");
1056 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
1057 EmitBlock(BodyBB);
1058 }
1059
1060 auto Loc = S.getBeginLoc();
1061 CXXCatchStmt Catch(Loc, /*exDecl=*/nullptr,
1062 CurCoro.Data->ExceptionHandler);
1063 auto *TryStmt =
1064 CXXTryStmt::Create(getContext(), Loc, S.getBody(), &Catch);
1065
1066 EnterCXXTryStmt(*TryStmt);
1067 emitBodyAndFallthrough(*this, S, TryStmt->getTryBlock());
1068 ExitCXXTryStmt(*TryStmt);
1069
1070 if (ContBB)
1071 EmitBlock(ContBB);
1072 }
1073 else {
1074 emitBodyAndFallthrough(*this, S, S.getBody());
1075 }
1076
1077 // See if we need to generate final suspend.
1078 const bool CanFallthrough = Builder.GetInsertBlock();
1079 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
1080 if (CanFallthrough || HasCoreturns) {
1081 EmitBlock(FinalBB);
1082 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
1084 } else {
1085 // We don't need FinalBB. Emit it to make sure the block is deleted.
1086 EmitBlock(FinalBB, /*IsFinished=*/true);
1087 }
1088
1089 // We need conversion if get_return_object's type doesn't matches the
1090 // coroutine return type.
1091 if (!GroManager.DirectEmit)
1092 GroManager.EmitGroConv(RetBB);
1093 EmitBlock(CleanupBB);
1094 }
1095
1096 EmitBlock(RetBB);
1097 // Emit coro.end before ret instruction, since resume and destroy parts of the
1098 // coroutine should return void.
1099 llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
1100 Builder.CreateCall(CoroEnd,
1101 {NullPtr, Builder.getFalse(),
1102 llvm::ConstantTokenNone::get(CoroEnd->getContext())});
1103
1104 if (auto *Ret = cast_or_null<ReturnStmt>(S.getReturnStmt())) {
1105 // Since we already emitted the return value above, so we shouldn't
1106 // emit it again here.
1107 Expr *PreviousRetValue = Ret->getRetValue();
1108 Ret->setRetValue(nullptr);
1109 EmitStmt(Ret);
1110 // Set the return value back. The code generator, as the AST **Consumer**,
1111 // shouldn't change the AST.
1112 Ret->setRetValue(PreviousRetValue);
1113 }
1114 // LLVM require the frontend to mark the coroutine.
1115 CurFn->setPresplitCoroutine();
1116
1117 if (CXXRecordDecl *RD = FnRetTy->getAsCXXRecordDecl();
1118 RD && RD->hasAttr<CoroOnlyDestroyWhenCompleteAttr>())
1119 CurFn->setCoroDestroyOnlyWhenComplete();
1120}
1121
1122// Emit coroutine intrinsic and patch up arguments of the token type.
1124 unsigned int IID) {
1126 switch (IID) {
1127 default:
1128 break;
1129 // The coro.frame builtin is replaced with an SSA value of the coro.begin
1130 // intrinsic.
1131 case llvm::Intrinsic::coro_frame: {
1132 if (CurCoro.Data && CurCoro.Data->CoroBegin) {
1133 return RValue::get(CurCoro.Data->CoroBegin);
1134 }
1135
1136 if (CurAwaitSuspendWrapper.FramePtr) {
1137 return RValue::get(CurAwaitSuspendWrapper.FramePtr);
1138 }
1139
1140 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin "
1141 "has been used earlier in this function");
1142 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());
1143 return RValue::get(NullPtr);
1144 }
1145 case llvm::Intrinsic::coro_size: {
1146 auto &Context = getContext();
1147 llvm::IntegerType *T =
1148 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1149 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
1150 return RValue::get(Builder.CreateCall(F));
1151 }
1152 case llvm::Intrinsic::coro_align: {
1153 auto &Context = getContext();
1154 llvm::IntegerType *T =
1155 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1156 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
1157 return RValue::get(Builder.CreateCall(F));
1158 }
1159 // The following three intrinsics take a token parameter referring to a token
1160 // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
1161 // builtins, we patch it up here.
1162 case llvm::Intrinsic::coro_alloc:
1163 case llvm::Intrinsic::coro_begin:
1164 case llvm::Intrinsic::coro_free: {
1165 if (CurCoro.Data && CurCoro.Data->CoroId) {
1166 Args.push_back(CurCoro.Data->CoroId);
1167 break;
1168 }
1169 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
1170 " been used earlier in this function");
1171 // Fallthrough to the next case to add TokenNone as the first argument.
1172 [[fallthrough]];
1173 }
1174 // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first
1175 // argument.
1176 case llvm::Intrinsic::coro_suspend:
1177 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
1178 break;
1179 }
1180 for (const Expr *Arg : E->arguments())
1181 Args.push_back(EmitScalarExpr(Arg));
1182 // @llvm.coro.end takes a token parameter. Add token 'none' as the last
1183 // argument.
1184 if (IID == llvm::Intrinsic::coro_end)
1185 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
1186
1187 llvm::Function *F = CGM.getIntrinsic(IID);
1188 llvm::CallInst *Call = Builder.CreateCall(F, Args);
1189
1190 // Note: The following code is to enable to emit coro.id and coro.begin by
1191 // hand to experiment with coroutines in C.
1192 // If we see @llvm.coro.id remember it in the CoroData. We will update
1193 // coro.alloc, coro.begin and coro.free intrinsics to refer to it.
1194 if (IID == llvm::Intrinsic::coro_id) {
1195 createCoroData(*this, CurCoro, Call, E);
1196 }
1197 else if (IID == llvm::Intrinsic::coro_begin) {
1198 if (CurCoro.Data)
1199 CurCoro.Data->CoroBegin = Call;
1200 }
1201 else if (IID == llvm::Intrinsic::coro_free) {
1202 // Remember the last coro_free as we need it to build the conditional
1203 // deletion of the coroutine frame.
1204 if (CurCoro.Data)
1205 CurCoro.Data->LastCoroFree = Call;
1206 }
1207 return RValue::get(Call);
1208}
#define V(N, I)
static SmallString< 32 > buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind)
static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, const CoroutineSuspendExpr *E)
static bool StmtCanThrow(const Stmt *S)
static bool FunctionCanThrow(const FunctionDecl *D)
static SmallVector< llvm::OperandBundleDef, 1 > getBundlesForCoroEnd(CodeGenFunction &CGF)
static LValueOrRValue emitSuspendExpression(CIRGenFunction &cgf, CGCoroData &coro, CoroutineSuspendExpr const &s, cir::AwaitKind kind, AggValueSlot aggSlot, bool ignoreResult, mlir::Block *scopeParentBlock, mlir::Value &tmpResumeRValAddr, bool forLValue)
static mlir::LogicalResult emitBodyAndFallthrough(CIRGenFunction &cgf, const CoroutineBodyStmt &s, Stmt *body, const CIRGenFunction::LexicalScope *currLexScope)
static void createCoroData(CIRGenFunction &cgf, CIRGenFunction::CGCoroInfo &curCoro, cir::CallOp coroId)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:28
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:69
static CXXTryStmt * Create(const ASTContext &C, SourceLocation tryLoc, CompoundStmt *tryBlock, ArrayRef< Stmt * > handlers)
Definition StmtCXX.cpp:25
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
SourceLocation getBeginLoc() const
Definition Expr.h:3280
arg_range arguments()
Definition Expr.h:3198
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
Represents a 'co_await' expression.
Definition ExprCXX.h:5365
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition Address.h:128
llvm::Value * getBasePointer() const
Definition Address.h:198
static Address invalid()
Definition Address.h:176
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:253
bool isValid() const
Definition Address.h:177
An aggregate value slot.
Definition CGValue.h:551
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
Definition CGValue.h:619
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
Definition CGDebugInfo.h:59
ParamDecl2StmtTy & getCoroutineParameterMappings()
CGFunctionInfo - Class to encapsulate the information about a function definition.
RawAddress getOriginalAllocatedAddress() const
Returns the address for the original alloca instruction.
static OpaqueValueMappingData bind(CodeGenFunction &CGF, const OpaqueValueExpr *ov, const Expr *e)
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitCoawaitLValue(const CoawaitExpr *E)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
AwaitSuspendWrapperInfo CurAwaitSuspendWrapper
llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")
Emits a call or invoke instruction to the given function, depending on the current state of the EH st...
Definition CGCall.cpp:5303
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitAutoVarInit(const AutoVarEmission &emission)
Definition CGDecl.cpp:1945
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
Definition CGDecl.cpp:1483
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Definition CGDecl.cpp:2299
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
Definition CGDecl.cpp:2272
llvm::BasicBlock * getEHResumeBlock(bool isCleanup)
llvm::DenseMap< const Decl *, Address > DeclMapTy
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
Definition CGExpr.cpp:258
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
RValue EmitCoyieldExpr(const CoyieldExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
Definition CGExpr.cpp:159
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
Definition CGExpr.cpp:6388
llvm::Function * generateAwaitSuspendWrapper(Twine const &CoroName, Twine const &SuspendPointName, CoroutineSuspendExpr const &S)
void EmitCoroutineBody(const CoroutineBodyStmt &S)
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
void EmitAutoVarCleanups(const AutoVarEmission &emission)
Definition CGDecl.cpp:2218
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
Definition CGExpr.cpp:309
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
Definition CGExpr.cpp:280
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
Definition CGStmt.cpp:58
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
LValue EmitCoyieldLValue(const CoyieldExpr *E)
RValue EmitCoawaitExpr(const CoawaitExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
llvm::SmallVector< const ParmVarDecl *, 4 > FnArgs
Save Parameter Decl for coroutine.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
Definition CGExpr.cpp:1714
llvm::Instruction * CurrentFuncletPad
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
Definition CGStmt.cpp:643
void Error(SourceLocation loc, StringRef error)
Emit a general error that something can't be done.
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
iterator find(stable_iterator save) const
Turn a stable reference to a scope depth into a unstable pointer to the EH stack.
Definition CGCleanup.h:654
FunctionArgList - Type for representing both the decl and type of parameters to a function.
Definition CGCall.h:376
LValue - This represents an lvalue references.
Definition CGValue.h:183
llvm::Value * getPointer(CodeGenFunction &CGF) const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition CGValue.h:42
static RValue getIgnored()
Definition CGValue.h:94
static RValue get(llvm::Value *V)
Definition CGValue.h:99
llvm::Value * getPointer() const
Definition Address.h:66
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
Represents a 'co_return' statement in the C++ Coroutines TS.
Definition StmtCXX.h:473
Expr * getOperand() const
Retrieve the operand of the 'co_return' statement.
Definition StmtCXX.h:497
Expr * getPromiseCall() const
Retrieve the promise call that results from this 'co_return' statement.
Definition StmtCXX.h:502
Represents the body of a coroutine.
Definition StmtCXX.h:320
CompoundStmt * getBody() const
Retrieve the body of the coroutine as written.
Definition StmtCXX.h:380
Stmt * getReturnStmtOnAllocFailure() const
Definition StmtCXX.h:420
Expr * getReturnValueInit() const
Definition StmtCXX.h:412
Stmt * getReturnStmt() const
Definition StmtCXX.h:419
Stmt * getResultDecl() const
Definition StmtCXX.h:411
Stmt * getInitSuspendStmt() const
Definition StmtCXX.h:391
Expr * getAllocate() const
Definition StmtCXX.h:405
Stmt * getPromiseDeclStmt() const
Definition StmtCXX.h:384
VarDecl * getPromiseDecl() const
Definition StmtCXX.h:387
Expr * getDeallocate() const
Definition StmtCXX.h:408
Stmt * getFallthroughHandler() const
Definition StmtCXX.h:401
Stmt * getExceptionHandler() const
Definition StmtCXX.h:398
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtCXX.h:427
Expr * getReturnValue() const
Definition StmtCXX.h:415
Stmt * getFinalSuspendStmt() const
Definition StmtCXX.h:394
ArrayRef< Stmt const * > getParamMoves() const
Definition StmtCXX.h:423
Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...
Definition ExprCXX.h:5251
SuspendReturnType getSuspendReturnType() const
Definition ExprCXX.h:5324
Expr * getReadyExpr() const
Definition ExprCXX.h:5307
Expr * getResumeExpr() const
Definition ExprCXX.h:5315
Expr * getSuspendExpr() const
Definition ExprCXX.h:5311
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Definition ExprCXX.h:5305
Expr * getCommonExpr() const
Definition ExprCXX.h:5300
Represents a 'co_yield' expression.
Definition ExprCXX.h:5446
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1273
ValueDecl * getDecl()
Definition Expr.h:1341
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1654
const Decl * getSingleDecl() const
Definition Stmt.h:1656
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2018
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5596
Represents a parameter to a function.
Definition Decl.h:1808
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8485
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1560
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:304
@ LH_Likely
Branch has the [[likely]] attribute.
Definition Stmt.h:1450
bool isVoidType() const
Definition TypeBase.h:9048
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9275
QualType getType() const
Definition Decl.h:723
const Expr * getInit() const
Definition Decl.h:1381
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
Expr * Cond
};
bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType)
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1763
CodeGenFunction::JumpDest FinalJD
CallExpr const * CoroIdExpr
llvm::BasicBlock * FinalExit
CodeGenFunction::JumpDest CleanupJD
llvm::BasicBlock * SuspendBB
llvm::CallInst * CoroBegin
llvm::CallInst * LastCoroFree
A jump destination is an abstract label, branching to which may require a jump out through normal cle...