18#include "llvm/ADT/ScopeExit.h"
24using llvm::BasicBlock;
27enum class AwaitKind {
Init,
Normal, Yield, Final };
28static constexpr llvm::StringLiteral AwaitKindStr[] = {
"init",
"await",
"yield",
94 llvm::CallInst *CoroId,
95 CallExpr const *CoroIdExpr =
nullptr) {
98 CGF.
CGM.
Error(CoroIdExpr->getBeginLoc(),
99 "only one __builtin_coro_id can be used in a function");
101 CGF.
CGM.
Error(CoroIdExpr->getBeginLoc(),
102 "__builtin_coro_id shall not be used in a C++ coroutine");
104 llvm_unreachable(
"EmitCoroutineBodyStatement called twice?");
118 case AwaitKind::Init:
119 case AwaitKind::Final:
121 case AwaitKind::Normal:
124 case AwaitKind::Yield:
130 Twine(
No).toVector(Prefix);
148 if (
const auto *CE = dyn_cast<CallExpr>(S)) {
149 const auto *Callee = CE->getDirectCallee();
160 if (
const auto *TE = dyn_cast<CXXBindTemporaryExpr>(S)) {
165 const auto *Dtor = TE->getTemporary()->getDestructor();
172 for (
const auto *child : S->
children())
220 struct LValueOrRValue {
228 bool ignoreResult,
bool forLValue) {
233 llvm::scope_exit UnbindCommonOnExit([&] { CommonBinder.unbind(CGF); });
237 BasicBlock *SuspendBlock = CGF.
createBasicBlock(Prefix + Twine(
".suspend"));
238 BasicBlock *CleanupBlock = CGF.
createBasicBlock(Prefix + Twine(
".cleanup"));
247 llvm::Function *CoroSave = CGF.
CGM.
getIntrinsic(llvm::Intrinsic::coro_save);
248 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
CGM.
Int8PtrTy);
249 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
252 CGF.
CurFn->getName(), Prefix, S);
257 "expected to be called in coroutine context");
260 SuspendIntrinsicCallArgs.push_back(
263 SuspendIntrinsicCallArgs.push_back(CGF.
CurCoro.
Data->CoroBegin);
264 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
267 llvm::Intrinsic::ID AwaitSuspendIID;
269 switch (SuspendReturnType) {
271 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
274 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
277 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
281 llvm::Function *AwaitSuspendIntrinsic = CGF.
CGM.
getIntrinsic(AwaitSuspendIID);
284 const bool AwaitSuspendCanThrow =
289 llvm::CallBase *SuspendRet =
nullptr;
291 if (AwaitSuspendCanThrow)
296 SuspendIntrinsicCallArgs);
301 switch (SuspendReturnType) {
303 assert(SuspendRet->getType()->isVoidTy());
306 assert(SuspendRet->getType()->isIntegerTy());
309 BasicBlock *RealSuspendBlock =
311 CGF.
Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
316 assert(SuspendRet->getType()->isVoidTy());
322 const bool IsFinalSuspend = (Kind == AwaitKind::Final);
323 llvm::Function *CoroSuspend =
325 auto *SuspendResult = Builder.CreateCall(
326 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});
330 Switch->addCase(Builder.getInt8(0), ReadyBlock);
331 Switch->addCase(Builder.getInt8(1), CleanupBlock);
337 Coro.
FinalExit = CleanupBlock->getSingleSuccessor();
382 CurCoro.Data->CurrentAwaitKind, aggSlot,
383 ignoreResult,
false).RV;
389 aggSlot, ignoreResult,
false).RV;
412 assert(
isa<CallExpr>(RE) &&
"unexpected suspend expression type");
419 Twine
const &SuspendPointName,
421 std::string FuncName =
422 (CoroName +
".__await_suspend_wrapper__" + SuspendPointName).str();
434 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
436 llvm::FunctionType *LTy =
CGM.getTypes().GetFunctionType(FI);
438 llvm::Function *Fn = llvm::Function::Create(
439 LTy, llvm::GlobalValue::InternalLinkage, FuncName, &
CGM.getModule());
442 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
443 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
445 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
447 Fn->setMustProgress();
448 Fn->removeFnAttr(llvm::Attribute::AttrKind::NoInline);
449 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
450 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
467 llvm::scope_exit UnbindCommonOnExit([&] { AwaiterBinder.unbind(*
this); });
468 if (SuspendRet !=
nullptr) {
469 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
481 "Can't have a scalar return unless the return type is a "
491 "Can't have a scalar return unless the return type is a "
500struct GetParamRef :
public StmtVisitor<GetParamRef> {
505 assert(
Expr ==
nullptr &&
"multilple declref in param move");
508 void VisitStmt(
Stmt *S) {
522 struct ParamReferenceReplacerRAII {
527 : LocalDeclMap(LocalDeclMap) {}
529 void addCopy(DeclStmt
const *PM) {
533 VarDecl
const*VD =
static_cast<VarDecl const*
>(PM->
getSingleDecl());
534 Expr
const *InitExpr = VD->
getInit();
536 Visitor.Visit(
const_cast<Expr*
>(InitExpr));
537 assert(Visitor.Expr);
538 DeclRefExpr *DREOrig = Visitor.Expr;
541 auto it = LocalDeclMap.find(PD);
542 assert(it != LocalDeclMap.end() &&
"parameter is not found");
543 SavedLocals.insert({ PD, it->second });
545 auto copyIt = LocalDeclMap.find(VD);
546 assert(copyIt != LocalDeclMap.end() &&
"parameter copy is not found");
547 it->second = copyIt->getSecond();
550 ~ParamReferenceReplacerRAII() {
551 for (
auto&& SavedLocal : SavedLocals) {
552 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
560static SmallVector<llvm::OperandBundleDef, 1>
565 BundleList.emplace_back(
"funclet", EHPad);
574struct CallCoroEnd final :
public EHScopeStack::Cleanup {
575 void Emit(CodeGenFunction &CGF, Flags flags)
override {
577 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
578 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
583 {NullPtr, CGF.
Builder.getTrue(),
584 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
586 if (Bundles.empty()) {
591 auto *CoroIsInRampFn = CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
592 auto *CoroIsInRamp = CGF.
Builder.CreateCall(CoroIsInRampFn);
593 CGF.
Builder.CreateCondBr(CoroIsInRamp, CleanupContBB, ResumeBB);
602struct CallCoroDelete final :
public EHScopeStack::Cleanup {
612 void Emit(CodeGenFunction &CGF, Flags)
override {
616 BasicBlock *SaveInsertBlock = CGF.
Builder.GetInsertBlock();
628 CGF.
CGM.
Error(Deallocate->getBeginLoc(),
629 "Deallocation expressoin does not refer to coro.free");
634 auto *InsertPt = SaveInsertBlock->getTerminator();
635 CoroFree->moveBefore(InsertPt->getIterator());
636 CGF.
Builder.SetInsertPoint(InsertPt);
639 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
640 auto *
Cond = CGF.
Builder.CreateICmpNE(CoroFree, NullPtr);
641 CGF.
Builder.CreateCondBr(
Cond, FreeBB, AfterFreeBB);
644 InsertPt->eraseFromParent();
645 CGF.
Builder.SetInsertPoint(AfterFreeBB);
650 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
655struct GetReturnObjectManager {
656 CodeGenFunction &CGF;
657 CGBuilderTy &Builder;
658 const CoroutineBodyStmt &S;
660 bool DirectEmit =
false;
663 CodeGenFunction::AutoVarEmission GroEmission;
664 std::unique_ptr<CodeGenFunction::RunCleanupsScope> GroScope;
666 GetReturnObjectManager(CodeGenFunction &CGF,
const CoroutineBodyStmt &S)
667 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(
Address::invalid()),
668 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {
690 assert(RVI &&
"expected RVI");
691 auto GroType = RVI->getType();
701 void EmitGroActive() {
705 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
714 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
717 void EmitGroAlloca() {
721 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
727 auto *GroVarDecl =
cast<VarDecl>(GroDeclStmt->getSingleDecl());
731 if (!GroVarDecl->isNRVOVariable()) {
733 auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
735 assert(GroAlloca &&
"expected alloca to be emitted");
736 GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
740 GroScope = std::make_unique<CodeGenFunction::RunCleanupsScope>(CGF);
749 if (
auto *Cleanup = dyn_cast<EHCleanupScope>(&*b)) {
750 assert(!Cleanup->hasActiveFlag() &&
"cleanup already has active flag?");
751 Cleanup->setActiveFlag(GroActiveFlag);
752 Cleanup->setTestFlagInEHCleanup();
753 Cleanup->setTestFlagInNormalCleanup();
758 Address EmitDirectReturnObjectCleanup() {
769 Builder.CreateStore(Builder.getFalse(), ActiveFlag);
779 if (
auto *Cleanup = dyn_cast<EHCleanupScope>(&*B)) {
780 assert(!Cleanup->hasActiveFlag() &&
"cleanup already has active flag?");
781 Cleanup->setActiveFlag(ActiveFlag);
782 Cleanup->setTestFlagInEHCleanup();
803 auto ActiveFlag = EmitDirectReturnObjectCleanup();
808 Builder.CreateStore(Builder.getTrue(), ActiveFlag);
813 if (!GroActiveFlag.
isValid()) {
821 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
853 void EmitGroConv(BasicBlock *RetBB) {
854 auto *AfterReadyBB = Builder.GetInsertBlock();
855 Builder.ClearInsertionPoint();
860 llvm::PHINode *IsFinalExit =
nullptr;
861 if (BasicBlock *FinalExit = CGF.
CurCoro.
Data->FinalExit) {
862 assert(AfterReadyBB &&
863 AfterReadyBB->getSinglePredecessor() == FinalExit &&
864 "Expect fallthrough from final.exit block");
865 AfterReadyBB->replaceAllUsesWith(PreConvBB);
866 PreConvBB->moveBefore(AfterReadyBB);
870 Builder.CreatePHI(Builder.getInt1Ty(), llvm::pred_size(PreConvBB));
871 for (
auto *Pred : llvm::predecessors(PreConvBB)) {
872 auto *
V = (Pred == FinalExit) ? Builder.getTrue() : Builder.getFalse();
873 IsFinalExit->addIncoming(
V, Pred);
876 auto *InRampFn = CGF.
CGM.
getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
877 auto *InRamp = Builder.CreateCall(InRampFn, {},
"InRamp");
880 Builder.CreateCondBr(InRamp, ConvBB, AfterConvBB);
886 GroScope->ForceCleanup();
887 Builder.CreateBr(AfterConvBB);
891 Builder.CreateCondBr(IsFinalExit, AfterReadyBB, RetBB);
893 Builder.CreateBr(RetBB);
894 Builder.SetInsertPoint(AfterReadyBB);
902 const bool CanFallthrough = CGF.
Builder.GetInsertBlock();
909 auto *NullPtr = llvm::ConstantPointerNull::get(
Builder.getPtrTy());
910 auto &TI =
CGM.getContext().getTargetInfo();
911 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
913 auto *EntryBB =
Builder.GetInsertBlock();
920 auto *CoroId =
Builder.CreateCall(
921 CGM.getIntrinsic(llvm::Intrinsic::coro_id),
922 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
925 GetReturnObjectManager GroManager(*
this, S);
928 assert(ShouldEmitLifetimeMarkers &&
929 "Must emit lifetime intrinsics for coroutines");
933 auto *CoroAlloc =
Builder.CreateCall(
934 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
936 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
940 auto *AllocOrInvokeContBB =
Builder.GetInsertBlock();
947 auto *NullPtr = llvm::ConstantPointerNull::get(
Int8PtrTy);
948 auto *
Cond =
Builder.CreateICmpNE(AllocateCall, NullPtr);
951 Builder.CreateCondBr(
Cond, InitBB, RetOnFailureBB);
965 Phi->addIncoming(NullPtr, EntryBB);
966 Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
967 auto *CoroBegin =
Builder.CreateCall(
968 CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
969 CurCoro.Data->CoroBegin = CoroBegin;
972 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
979 (ParamMoves.size() == 0 || (ParamMoves.size() ==
FnArgs.size())) &&
980 "ParamMoves and FnArgs should be the same size for coroutine function");
981 if (ParamMoves.size() ==
FnArgs.size() && DI)
982 for (
const auto Pair : llvm::zip(
FnArgs, ParamMoves))
984 {std::get<0>(Pair), std::get<1>(Pair)});
997 if (
auto *ParmAlloca =
999 ParmAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
1000 llvm::MDNode::get(
CGM.getLLVMContext(), {}));
1011 GroManager.EmitGroActive();
1020 GroManager.EmitGroAlloca();
1021 GroManager.EmitGroInit();
1026 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
1031 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
1033 if (
CurCoro.Data->ExceptionHandler) {
1039 BasicBlock *ContBB =
nullptr;
1040 if (
CurCoro.Data->ResumeEHVar) {
1045 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
1051 CurCoro.Data->ExceptionHandler);
1067 const bool CanFallthrough =
Builder.GetInsertBlock();
1068 const bool HasCoreturns =
CurCoro.Data->CoreturnCount > 0;
1069 if (CanFallthrough || HasCoreturns) {
1071 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
1080 if (!GroManager.DirectEmit)
1081 GroManager.EmitGroConv(RetBB);
1088 llvm::Function *CoroEnd =
CGM.getIntrinsic(llvm::Intrinsic::coro_end);
1091 llvm::ConstantTokenNone::get(CoroEnd->getContext())});
1093 if (
auto *Ret = cast_or_null<ReturnStmt>(S.
getReturnStmt())) {
1096 Expr *PreviousRetValue = Ret->getRetValue();
1097 Ret->setRetValue(
nullptr);
1101 Ret->setRetValue(PreviousRetValue);
1104 CurFn->setPresplitCoroutine();
1107 RD && RD->hasAttr<CoroOnlyDestroyWhenCompleteAttr>())
1108 CurFn->setCoroDestroyOnlyWhenComplete();
1120 case llvm::Intrinsic::coro_frame: {
1129 CGM.Error(E->
getBeginLoc(),
"this builtin expect that __builtin_coro_begin "
1130 "has been used earlier in this function");
1131 auto *NullPtr = llvm::ConstantPointerNull::get(
Builder.getPtrTy());
1134 case llvm::Intrinsic::coro_size: {
1136 llvm::IntegerType *T =
1137 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1138 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
1141 case llvm::Intrinsic::coro_align: {
1143 llvm::IntegerType *T =
1144 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1145 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
1151 case llvm::Intrinsic::coro_alloc:
1152 case llvm::Intrinsic::coro_begin:
1153 case llvm::Intrinsic::coro_free: {
1155 Args.push_back(
CurCoro.Data->CoroId);
1158 CGM.Error(E->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
1159 " been used earlier in this function");
1165 case llvm::Intrinsic::coro_suspend:
1173 if (IID == llvm::Intrinsic::coro_end)
1176 llvm::Function *F =
CGM.getIntrinsic(IID);
1177 llvm::CallInst *
Call =
Builder.CreateCall(F, Args);
1183 if (IID == llvm::Intrinsic::coro_id) {
1186 else if (IID == llvm::Intrinsic::coro_begin) {
1190 else if (IID == llvm::Intrinsic::coro_free) {
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 ...
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
CXXCatchStmt - This represents a C++ catch block.
Represents a C++ struct/union/class.
CXXTryStmt - A C++ try block, including all handlers.
static CXXTryStmt * Create(const ASTContext &C, SourceLocation tryLoc, CompoundStmt *tryBlock, ArrayRef< Stmt * > handlers)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const
static CharUnits One()
One - Construct a CharUnits quantity of one.
Represents a 'co_await' expression.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * getBasePointer() const
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
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...
void EmitCoreturnStmt(const CoreturnStmt &S)
void EmitAutoVarInit(const AutoVarEmission &emission)
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.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
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.
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)
CGDebugInfo * getDebugInfo()
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...
LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)
Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.
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="")
ASTContext & getContext() const
void EmitAutoVarCleanups(const AutoVarEmission &emission)
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...
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.
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.
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.
llvm::Instruction * CurrentFuncletPad
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
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.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue getIgnored()
static RValue get(llvm::Value *V)
llvm::Value * getPointer() const
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Represents a 'co_return' statement in the C++ Coroutines TS.
Expr * getOperand() const
Retrieve the operand of the 'co_return' statement.
Expr * getPromiseCall() const
Retrieve the promise call that results from this 'co_return' statement.
Represents the body of a coroutine.
CompoundStmt * getBody() const
Retrieve the body of the coroutine as written.
Stmt * getReturnStmtOnAllocFailure() const
Expr * getReturnValueInit() const
Stmt * getReturnStmt() const
Stmt * getResultDecl() const
Stmt * getInitSuspendStmt() const
Expr * getAllocate() const
Stmt * getPromiseDeclStmt() const
VarDecl * getPromiseDecl() const
Expr * getDeallocate() const
Stmt * getFallthroughHandler() const
Stmt * getExceptionHandler() const
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getReturnValue() const
Stmt * getFinalSuspendStmt() const
ArrayRef< Stmt const * > getParamMoves() const
Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...
SuspendReturnType getSuspendReturnType() const
Expr * getReadyExpr() const
Expr * getResumeExpr() const
Expr * getSuspendExpr() const
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
Expr * getCommonExpr() const
Represents a 'co_yield' expression.
A reference to a declared variable, function, enum, etc.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
const Decl * getSingleDecl() const
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
GlobalDecl - represents a global declaration.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Represents a parameter to a function.
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
@ LH_Likely
Branch has the [[likely]] attribute.
const T * getAs() const
Member-template getAs<specific type>'.
const Expr * getInit() const
@ 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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType)
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
llvm::Value * ResumeEHVar
CodeGenFunction::JumpDest FinalJD
CallExpr const * CoroIdExpr
llvm::BasicBlock * FinalExit
CodeGenFunction::JumpDest CleanupJD
llvm::BasicBlock * SuspendBB
AwaitKind CurrentAwaitKind
llvm::CallInst * CoroBegin
llvm::CallInst * LastCoroFree
std::unique_ptr< CGCoroData > Data
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::PointerType * VoidPtrTy
llvm::PointerType * Int8PtrTy