18#include "llvm/ADT/ScopeExit.h"
24using llvm::BasicBlock;
27enum class AwaitKind {
Init,
Normal, Yield, Final };
28static constexpr llvm::StringLiteral AwaitKindStr[] = {
"init",
"await",
"yield",
100 llvm::CallInst *CoroId,
101 CallExpr const *CoroIdExpr =
nullptr) {
104 CGF.
CGM.
Error(CoroIdExpr->getBeginLoc(),
105 "only one __builtin_coro_id can be used in a function");
107 CGF.
CGM.
Error(CoroIdExpr->getBeginLoc(),
108 "__builtin_coro_id shall not be used in a C++ coroutine");
110 llvm_unreachable(
"EmitCoroutineBodyStatement called twice?");
124 case AwaitKind::Init:
125 case AwaitKind::Final:
127 case AwaitKind::Normal:
130 case AwaitKind::Yield:
136 Twine(
No).toVector(Prefix);
154 if (
const auto *CE = dyn_cast<CallExpr>(S)) {
155 const auto *Callee = CE->getDirectCallee();
166 if (
const auto *TE = dyn_cast<CXXBindTemporaryExpr>(S)) {
171 const auto *Dtor = TE->getTemporary()->getDestructor();
178 for (
const auto *child : S->
children())
226 struct LValueOrRValue {
234 bool ignoreResult,
bool forLValue) {
239 llvm::scope_exit UnbindCommonOnExit([&] { CommonBinder.unbind(CGF); });
243 BasicBlock *SuspendBlock = CGF.
createBasicBlock(Prefix + Twine(
".suspend"));
244 BasicBlock *CleanupBlock = CGF.
createBasicBlock(Prefix + Twine(
".cleanup"));
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});
258 CGF.
CurFn->getName(), Prefix, S);
263 "expected to be called in coroutine context");
266 SuspendIntrinsicCallArgs.push_back(
269 SuspendIntrinsicCallArgs.push_back(CGF.
CurCoro.
Data->CoroBegin);
270 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
273 llvm::Intrinsic::ID AwaitSuspendIID;
275 switch (SuspendReturnType) {
277 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
280 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
283 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
287 llvm::Function *AwaitSuspendIntrinsic = CGF.
CGM.
getIntrinsic(AwaitSuspendIID);
290 const bool AwaitSuspendCanThrow =
295 llvm::CallBase *SuspendRet =
nullptr;
297 if (AwaitSuspendCanThrow)
302 SuspendIntrinsicCallArgs);
307 switch (SuspendReturnType) {
309 assert(SuspendRet->getType()->isVoidTy());
312 assert(SuspendRet->getType()->isIntegerTy());
315 BasicBlock *RealSuspendBlock =
317 CGF.
Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
322 assert(SuspendRet->getType()->isVoidTy());
328 const bool IsFinalSuspend = (Kind == AwaitKind::Final);
329 llvm::Function *CoroSuspend =
331 auto *SuspendResult = Builder.CreateCall(
332 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});
336 Switch->addCase(Builder.getInt8(0), ReadyBlock);
337 Switch->addCase(Builder.getInt8(1), CleanupBlock);
343 Coro.
FinalExit = CleanupBlock->getSingleSuccessor();
392 CurCoro.Data->CurrentAwaitKind, aggSlot,
393 ignoreResult,
false).RV;
399 aggSlot, ignoreResult,
false).RV;
422 assert(
isa<CallExpr>(RE) &&
"unexpected suspend expression type");
429 Twine
const &SuspendPointName,
431 std::string FuncName =
432 (CoroName +
".__await_suspend_wrapper__" + SuspendPointName).str();
444 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
446 llvm::FunctionType *LTy =
CGM.getTypes().GetFunctionType(FI);
448 llvm::Function *Fn = llvm::Function::Create(
449 LTy, llvm::GlobalValue::InternalLinkage, FuncName, &
CGM.getModule());
451 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
452 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
454 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
456 Fn->setMustProgress();
457 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
458 Fn->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
475 llvm::scope_exit UnbindCommonOnExit([&] { AwaiterBinder.unbind(*
this); });
476 if (SuspendRet !=
nullptr) {
477 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
489 "Can't have a scalar return unless the return type is a "
499 "Can't have a scalar return unless the return type is a "
508struct GetParamRef :
public StmtVisitor<GetParamRef> {
513 assert(
Expr ==
nullptr &&
"multilple declref in param move");
516 void VisitStmt(
Stmt *S) {
530 struct ParamReferenceReplacerRAII {
535 : LocalDeclMap(LocalDeclMap) {}
537 void addCopy(DeclStmt
const *PM) {
541 VarDecl
const*VD =
static_cast<VarDecl const*
>(PM->
getSingleDecl());
542 Expr
const *InitExpr = VD->
getInit();
544 Visitor.Visit(
const_cast<Expr*
>(InitExpr));
545 assert(Visitor.Expr);
546 DeclRefExpr *DREOrig = Visitor.Expr;
549 auto it = LocalDeclMap.find(PD);
550 assert(it != LocalDeclMap.end() &&
"parameter is not found");
551 SavedLocals.insert({ PD, it->second });
553 auto copyIt = LocalDeclMap.find(VD);
554 assert(copyIt != LocalDeclMap.end() &&
"parameter copy is not found");
555 it->second = copyIt->getSecond();
558 ~ParamReferenceReplacerRAII() {
559 for (
auto&& SavedLocal : SavedLocals) {
560 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
568static SmallVector<llvm::OperandBundleDef, 1>
573 BundleList.emplace_back(
"funclet", EHPad);
582struct CallCoroEnd final :
public EHScopeStack::Cleanup {
583 void Emit(CodeGenFunction &CGF, Flags flags)
override {
585 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
586 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
591 {NullPtr, CGF.
Builder.getTrue(),
592 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
594 if (Bundles.empty()) {
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);
610struct CallCoroDelete final :
public EHScopeStack::Cleanup {
620 void Emit(CodeGenFunction &CGF, Flags)
override {
624 BasicBlock *SaveInsertBlock = CGF.
Builder.GetInsertBlock();
636 CGF.
CGM.
Error(Deallocate->getBeginLoc(),
637 "Deallocation expressoin does not refer to coro.free");
642 auto *InsertPt = SaveInsertBlock->getTerminator();
643 CoroFree->moveBefore(InsertPt->getIterator());
644 CGF.
Builder.SetInsertPoint(InsertPt);
647 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
648 auto *
Cond = CGF.
Builder.CreateICmpNE(CoroFree, NullPtr);
649 CGF.
Builder.CreateCondBr(
Cond, FreeBB, AfterFreeBB);
652 InsertPt->eraseFromParent();
653 CGF.
Builder.SetInsertPoint(AfterFreeBB);
658 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
663struct GetReturnObjectManager {
664 CodeGenFunction &CGF;
665 CGBuilderTy &Builder;
666 const CoroutineBodyStmt &S;
668 bool DirectEmit =
false;
671 CodeGenFunction::AutoVarEmission GroEmission;
672 std::unique_ptr<CodeGenFunction::RunCleanupsScope> GroScope;
674 GetReturnObjectManager(CodeGenFunction &CGF,
const CoroutineBodyStmt &S)
675 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(
Address::invalid()),
676 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {
698 assert(RVI &&
"expected RVI");
699 auto GroType = RVI->getType();
709 void EmitGroActive() {
713 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
722 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
725 void EmitGroAlloca() {
729 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
735 auto *GroVarDecl =
cast<VarDecl>(GroDeclStmt->getSingleDecl());
739 if (!GroVarDecl->isNRVOVariable()) {
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,
748 GroScope = std::make_unique<CodeGenFunction::RunCleanupsScope>(CGF);
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();
766 void EmitDirectReturnObjectCleanup() {
779 Builder.CreateStore(Builder.getFalse(), ActiveFlag);
780 CGF.
CurCoro.
Data->InitialReturnObjectActiveFlag = ActiveFlag;
790 if (
auto *Cleanup = dyn_cast<EHCleanupScope>(&*B)) {
791 assert(!Cleanup->hasActiveFlag() &&
"cleanup already has active flag?");
792 Cleanup->setActiveFlag(ActiveFlag);
793 Cleanup->setTestFlagInEHCleanup();
813 EmitDirectReturnObjectCleanup();
817 if (CGF.
CurCoro.
Data->InitialReturnObjectActiveFlag.isValid())
818 Builder.CreateStore(Builder.getTrue(),
824 if (!GroActiveFlag.
isValid()) {
832 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
864 void EmitGroConv(BasicBlock *RetBB) {
865 auto *AfterReadyBB = Builder.GetInsertBlock();
866 Builder.ClearInsertionPoint();
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);
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);
887 auto *InRampFn = CGF.
CGM.
getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
888 auto *InRamp = Builder.CreateCall(InRampFn, {},
"InRamp");
891 Builder.CreateCondBr(InRamp, ConvBB, AfterConvBB);
897 GroScope->ForceCleanup();
898 Builder.CreateBr(AfterConvBB);
902 Builder.CreateCondBr(IsFinalExit, AfterReadyBB, RetBB);
904 Builder.CreateBr(RetBB);
905 Builder.SetInsertPoint(AfterReadyBB);
913 const bool CanFallthrough = CGF.
Builder.GetInsertBlock();
920 auto *NullPtr = llvm::ConstantPointerNull::get(
Builder.getPtrTy());
921 auto &TI =
CGM.getContext().getTargetInfo();
922 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
924 auto *EntryBB =
Builder.GetInsertBlock();
931 auto *CoroId =
Builder.CreateCall(
932 CGM.getIntrinsic(llvm::Intrinsic::coro_id),
933 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
936 GetReturnObjectManager GroManager(*
this, S);
939 assert(ShouldEmitLifetimeMarkers &&
940 "Must emit lifetime intrinsics for coroutines");
944 auto *CoroAlloc =
Builder.CreateCall(
945 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
947 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
951 auto *AllocOrInvokeContBB =
Builder.GetInsertBlock();
958 auto *NullPtr = llvm::ConstantPointerNull::get(
Int8PtrTy);
959 auto *
Cond =
Builder.CreateICmpNE(AllocateCall, NullPtr);
962 Builder.CreateCondBr(
Cond, InitBB, RetOnFailureBB);
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;
983 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
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)});
1008 if (
auto *ParmAlloca =
1010 ParmAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
1011 llvm::MDNode::get(
CGM.getLLVMContext(), {}));
1022 GroManager.EmitGroActive();
1031 GroManager.EmitGroAlloca();
1032 GroManager.EmitGroInit();
1037 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
1042 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
1044 if (
CurCoro.Data->ExceptionHandler) {
1050 BasicBlock *ContBB =
nullptr;
1051 if (
CurCoro.Data->ResumeEHVar) {
1056 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
1062 CurCoro.Data->ExceptionHandler);
1078 const bool CanFallthrough =
Builder.GetInsertBlock();
1079 const bool HasCoreturns =
CurCoro.Data->CoreturnCount > 0;
1080 if (CanFallthrough || HasCoreturns) {
1082 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
1091 if (!GroManager.DirectEmit)
1092 GroManager.EmitGroConv(RetBB);
1099 llvm::Function *CoroEnd =
CGM.getIntrinsic(llvm::Intrinsic::coro_end);
1102 llvm::ConstantTokenNone::get(CoroEnd->getContext())});
1104 if (
auto *Ret = cast_or_null<ReturnStmt>(S.
getReturnStmt())) {
1107 Expr *PreviousRetValue = Ret->getRetValue();
1108 Ret->setRetValue(
nullptr);
1112 Ret->setRetValue(PreviousRetValue);
1115 CurFn->setPresplitCoroutine();
1118 RD && RD->hasAttr<CoroOnlyDestroyWhenCompleteAttr>())
1119 CurFn->setCoroDestroyOnlyWhenComplete();
1131 case llvm::Intrinsic::coro_frame: {
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());
1145 case llvm::Intrinsic::coro_size: {
1147 llvm::IntegerType *T =
1148 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1149 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
1152 case llvm::Intrinsic::coro_align: {
1154 llvm::IntegerType *T =
1155 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1156 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
1162 case llvm::Intrinsic::coro_alloc:
1163 case llvm::Intrinsic::coro_begin:
1164 case llvm::Intrinsic::coro_free: {
1166 Args.push_back(
CurCoro.Data->CoroId);
1169 CGM.Error(E->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
1170 " been used earlier in this function");
1176 case llvm::Intrinsic::coro_suspend:
1184 if (IID == llvm::Intrinsic::coro_end)
1187 llvm::Function *F =
CGM.getIntrinsic(IID);
1188 llvm::CallInst *
Call =
Builder.CreateCall(F, Args);
1194 if (IID == llvm::Intrinsic::coro_id) {
1197 else if (IID == llvm::Intrinsic::coro_begin) {
1201 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.
Address InitialReturnObjectActiveFlag
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