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 auto UnbindCommonOnExit =
234 llvm::make_scope_exit([&] { CommonBinder.unbind(CGF); });
238 BasicBlock *SuspendBlock = CGF.
createBasicBlock(Prefix + Twine(
".suspend"));
239 BasicBlock *CleanupBlock = CGF.
createBasicBlock(Prefix + Twine(
".cleanup"));
248 llvm::Function *CoroSave = CGF.
CGM.
getIntrinsic(llvm::Intrinsic::coro_save);
249 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
CGM.
Int8PtrTy);
250 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
253 CGF.
CurFn->getName(), Prefix, S);
258 "expected to be called in coroutine context");
261 SuspendIntrinsicCallArgs.push_back(
264 SuspendIntrinsicCallArgs.push_back(CGF.
CurCoro.
Data->CoroBegin);
265 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
268 llvm::Intrinsic::ID AwaitSuspendIID;
270 switch (SuspendReturnType) {
272 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
275 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
278 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
282 llvm::Function *AwaitSuspendIntrinsic = CGF.
CGM.
getIntrinsic(AwaitSuspendIID);
285 const bool AwaitSuspendCanThrow =
290 llvm::CallBase *SuspendRet =
nullptr;
292 if (AwaitSuspendCanThrow)
297 SuspendIntrinsicCallArgs);
302 switch (SuspendReturnType) {
304 assert(SuspendRet->getType()->isVoidTy());
307 assert(SuspendRet->getType()->isIntegerTy());
310 BasicBlock *RealSuspendBlock =
312 CGF.
Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
317 assert(SuspendRet->getType()->isVoidTy());
323 const bool IsFinalSuspend = (Kind == AwaitKind::Final);
324 llvm::Function *CoroSuspend =
326 auto *SuspendResult = Builder.CreateCall(
327 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});
331 Switch->addCase(Builder.getInt8(0), ReadyBlock);
332 Switch->addCase(Builder.getInt8(1), CleanupBlock);
338 Coro.
FinalExit = CleanupBlock->getSingleSuccessor();
383 CurCoro.Data->CurrentAwaitKind, aggSlot,
384 ignoreResult,
false).RV;
390 aggSlot, ignoreResult,
false).RV;
413 assert(
isa<CallExpr>(RE) &&
"unexpected suspend expression type");
420 Twine
const &SuspendPointName,
422 std::string FuncName =
423 (CoroName +
".__await_suspend_wrapper__" + SuspendPointName).str();
433 args.push_back(&AwaiterDecl);
434 args.push_back(&FrameDecl);
437 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
439 llvm::FunctionType *LTy =
CGM.getTypes().GetFunctionType(FI);
441 llvm::Function *Fn = llvm::Function::Create(
442 LTy, llvm::GlobalValue::InternalLinkage, FuncName, &
CGM.getModule());
444 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
445 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
447 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
449 Fn->setMustProgress();
450 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
467 auto UnbindCommonOnExit =
468 llvm::make_scope_exit([&] { AwaiterBinder.unbind(*
this); });
469 if (SuspendRet !=
nullptr) {
470 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
482 "Can't have a scalar return unless the return type is a "
492 "Can't have a scalar return unless the return type is a "
501struct GetParamRef :
public StmtVisitor<GetParamRef> {
506 assert(
Expr ==
nullptr &&
"multilple declref in param move");
509 void VisitStmt(
Stmt *S) {
523 struct ParamReferenceReplacerRAII {
528 : LocalDeclMap(LocalDeclMap) {}
530 void addCopy(DeclStmt
const *PM) {
534 VarDecl
const*VD =
static_cast<VarDecl const*
>(PM->
getSingleDecl());
535 Expr
const *InitExpr = VD->
getInit();
537 Visitor.Visit(
const_cast<Expr*
>(InitExpr));
538 assert(Visitor.Expr);
539 DeclRefExpr *DREOrig = Visitor.Expr;
542 auto it = LocalDeclMap.find(PD);
543 assert(it != LocalDeclMap.end() &&
"parameter is not found");
544 SavedLocals.insert({ PD, it->second });
546 auto copyIt = LocalDeclMap.find(VD);
547 assert(copyIt != LocalDeclMap.end() &&
"parameter copy is not found");
548 it->second = copyIt->getSecond();
551 ~ParamReferenceReplacerRAII() {
552 for (
auto&& SavedLocal : SavedLocals) {
553 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
561static SmallVector<llvm::OperandBundleDef, 1>
566 BundleList.emplace_back(
"funclet", EHPad);
575struct CallCoroEnd final :
public EHScopeStack::Cleanup {
576 void Emit(CodeGenFunction &CGF, Flags flags)
override {
578 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
579 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
584 {NullPtr, CGF.
Builder.getTrue(),
585 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
587 if (Bundles.empty()) {
592 auto *CoroIsInRampFn = CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
593 auto *CoroIsInRamp = CGF.
Builder.CreateCall(CoroIsInRampFn);
594 CGF.
Builder.CreateCondBr(CoroIsInRamp, CleanupContBB, ResumeBB);
603struct CallCoroDelete final :
public EHScopeStack::Cleanup {
613 void Emit(CodeGenFunction &CGF, Flags)
override {
617 BasicBlock *SaveInsertBlock = CGF.
Builder.GetInsertBlock();
629 CGF.
CGM.
Error(Deallocate->getBeginLoc(),
630 "Deallocation expressoin does not refer to coro.free");
635 auto *InsertPt = SaveInsertBlock->getTerminator();
636 CoroFree->moveBefore(InsertPt->getIterator());
637 CGF.
Builder.SetInsertPoint(InsertPt);
640 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.
Int8PtrTy);
641 auto *
Cond = CGF.
Builder.CreateICmpNE(CoroFree, NullPtr);
642 CGF.
Builder.CreateCondBr(
Cond, FreeBB, AfterFreeBB);
645 InsertPt->eraseFromParent();
646 CGF.
Builder.SetInsertPoint(AfterFreeBB);
648 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
653struct GetReturnObjectManager {
654 CodeGenFunction &CGF;
655 CGBuilderTy &Builder;
656 const CoroutineBodyStmt &S;
658 bool DirectEmit =
false;
660 Address GroActiveFlag;
661 CodeGenFunction::AutoVarEmission GroEmission;
663 GetReturnObjectManager(CodeGenFunction &CGF,
const CoroutineBodyStmt &S)
664 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()),
665 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {
687 assert(RVI &&
"expected RVI");
688 auto GroType = RVI->getType();
698 void EmitGroActive() {
702 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
711 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
714 void EmitGroAlloca() {
718 auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.
getResultDecl());
724 auto *GroVarDecl =
cast<VarDecl>(GroDeclStmt->getSingleDecl());
728 if (!GroVarDecl->isNRVOVariable()) {
730 auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
732 assert(GroAlloca &&
"expected alloca to be emitted");
733 GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
745 if (
auto *Cleanup = dyn_cast<EHCleanupScope>(&*
b)) {
746 assert(!Cleanup->hasActiveFlag() &&
"cleanup already has active flag?");
747 Cleanup->setActiveFlag(GroActiveFlag);
748 Cleanup->setTestFlagInEHCleanup();
749 Cleanup->setTestFlagInNormalCleanup();
776 if (!GroActiveFlag.
isValid()) {
784 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
816 void EmitGroConv(BasicBlock *RetBB) {
817 auto *AfterReadyBB = Builder.GetInsertBlock();
818 Builder.ClearInsertionPoint();
823 llvm::PHINode *IsFinalExit =
nullptr;
824 if (BasicBlock *FinalExit = CGF.
CurCoro.
Data->FinalExit) {
825 assert(AfterReadyBB &&
826 AfterReadyBB->getSinglePredecessor() == FinalExit &&
827 "Expect fallthrough from final.exit block");
828 AfterReadyBB->replaceAllUsesWith(PreConvBB);
829 PreConvBB->moveBefore(AfterReadyBB);
833 Builder.CreatePHI(Builder.getInt1Ty(), llvm::pred_size(PreConvBB));
834 for (
auto *Pred : llvm::predecessors(PreConvBB)) {
835 auto *
V = (Pred == FinalExit) ? Builder.getTrue() : Builder.getFalse();
836 IsFinalExit->addIncoming(
V, Pred);
839 auto *InRampFn = CGF.
CGM.
getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
840 auto *InRamp = Builder.CreateCall(InRampFn, {},
"InRamp");
843 Builder.CreateCondBr(InRamp, ConvBB, AfterConvBB);
849 Builder.CreateBr(AfterConvBB);
853 Builder.CreateCondBr(IsFinalExit, AfterReadyBB, RetBB);
855 Builder.CreateBr(RetBB);
856 Builder.SetInsertPoint(AfterReadyBB);
864 const bool CanFallthrough = CGF.
Builder.GetInsertBlock();
871 auto *NullPtr = llvm::ConstantPointerNull::get(
Builder.getPtrTy());
872 auto &TI =
CGM.getContext().getTargetInfo();
873 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
875 auto *EntryBB =
Builder.GetInsertBlock();
881 auto *CoroId =
Builder.CreateCall(
882 CGM.getIntrinsic(llvm::Intrinsic::coro_id),
883 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
886 GetReturnObjectManager GroManager(*
this, S);
889 assert(ShouldEmitLifetimeMarkers &&
890 "Must emit lifetime intrinsics for coroutines");
894 auto *CoroAlloc =
Builder.CreateCall(
895 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
897 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
901 auto *AllocOrInvokeContBB =
Builder.GetInsertBlock();
908 auto *NullPtr = llvm::ConstantPointerNull::get(
Int8PtrTy);
909 auto *
Cond =
Builder.CreateICmpNE(AllocateCall, NullPtr);
912 Builder.CreateCondBr(
Cond, InitBB, RetOnFailureBB);
926 Phi->addIncoming(NullPtr, EntryBB);
927 Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
928 auto *CoroBegin =
Builder.CreateCall(
929 CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
930 CurCoro.Data->CoroBegin = CoroBegin;
935 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
942 (ParamMoves.size() == 0 || (ParamMoves.size() ==
FnArgs.size())) &&
943 "ParamMoves and FnArgs should be the same size for coroutine function");
944 if (ParamMoves.size() ==
FnArgs.size() && DI)
945 for (
const auto Pair : llvm::zip(
FnArgs, ParamMoves))
947 {std::get<0>(Pair), std::get<1>(Pair)});
960 if (
auto *ParmAlloca =
962 ParmAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
963 llvm::MDNode::get(
CGM.getLLVMContext(), {}));
974 GroManager.EmitGroActive();
983 GroManager.EmitGroAlloca();
984 GroManager.EmitGroInit();
988 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
993 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
995 if (
CurCoro.Data->ExceptionHandler) {
1001 BasicBlock *ContBB =
nullptr;
1002 if (
CurCoro.Data->ResumeEHVar) {
1007 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
1013 CurCoro.Data->ExceptionHandler);
1029 const bool CanFallthrough =
Builder.GetInsertBlock();
1030 const bool HasCoreturns =
CurCoro.Data->CoreturnCount > 0;
1031 if (CanFallthrough || HasCoreturns) {
1033 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
1042 if (!GroManager.DirectEmit)
1043 GroManager.EmitGroConv(RetBB);
1049 llvm::Function *CoroEnd =
CGM.getIntrinsic(llvm::Intrinsic::coro_end);
1052 llvm::ConstantTokenNone::get(CoroEnd->getContext())});
1054 if (
auto *Ret = cast_or_null<ReturnStmt>(S.
getReturnStmt())) {
1057 Expr *PreviousRetValue = Ret->getRetValue();
1058 Ret->setRetValue(
nullptr);
1062 Ret->setRetValue(PreviousRetValue);
1065 CurFn->setPresplitCoroutine();
1068 RD && RD->hasAttr<CoroOnlyDestroyWhenCompleteAttr>())
1069 CurFn->setCoroDestroyOnlyWhenComplete();
1081 case llvm::Intrinsic::coro_frame: {
1090 CGM.Error(E->
getBeginLoc(),
"this builtin expect that __builtin_coro_begin "
1091 "has been used earlier in this function");
1092 auto *NullPtr = llvm::ConstantPointerNull::get(
Builder.getPtrTy());
1095 case llvm::Intrinsic::coro_size: {
1097 llvm::IntegerType *
T =
1098 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1099 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_size,
T);
1102 case llvm::Intrinsic::coro_align: {
1104 llvm::IntegerType *
T =
1105 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1106 llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::coro_align,
T);
1112 case llvm::Intrinsic::coro_alloc:
1113 case llvm::Intrinsic::coro_begin:
1114 case llvm::Intrinsic::coro_free: {
1116 Args.push_back(
CurCoro.Data->CoroId);
1119 CGM.Error(E->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
1120 " been used earlier in this function");
1126 case llvm::Intrinsic::coro_suspend:
1134 if (IID == llvm::Intrinsic::coro_end)
1137 llvm::Function *F =
CGM.getIntrinsic(IID);
1138 llvm::CallInst *
Call =
Builder.CreateCall(F, Args);
1144 if (IID == llvm::Intrinsic::coro_id) {
1147 else if (IID == llvm::Intrinsic::coro_begin) {
1151 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 EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
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.
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.
Represents a parameter to a function.
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
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...
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
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