clang: lib/CodeGen/CGCoroutine.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
18#include "llvm/ADT/ScopeExit.h"
19
20using namespace clang;
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
34
35
39
40
41
43
44
46
47
49
50
51
52
53
55
56
57
58
60
61
62
64
65
66
67
68
69 llvm::CallInst *CoroId = nullptr;
70
71
72
73
75
76
77
79
80
81
82
84};
85
86
89
92 llvm::CallInst *CoroId,
93 CallExpr const *CoroIdExpr = nullptr) {
96 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
97 "only one __builtin_coro_id can be used in a function");
98 else if (CoroIdExpr)
99 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),
100 "__builtin_coro_id shall not be used in a C++ coroutine");
101 else
102 llvm_unreachable("EmitCoroutineBodyStatement called twice?");
103
104 return;
105 }
106
107 CurCoro.Data = std::make_unique();
110}
111
112
114 unsigned No = 0;
115 switch (Kind) {
116 case AwaitKind::Init:
117 case AwaitKind::Final:
118 break;
119 case AwaitKind::Normal:
121 break;
122 case AwaitKind::Yield:
124 break;
125 }
126 SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]);
127 if (No > 1) {
128 Twine(No).toVector(Prefix);
129 }
130 return Prefix;
131}
132
133
134
137 if (!Proto) {
138
139 return true;
140 }
143}
144
146 if (const auto *CE = dyn_cast(S)) {
147 const auto *Callee = CE->getDirectCallee();
148 if (!Callee)
149
150 return true;
151
153 return true;
154
155
156 }
157
158 if (const auto *TE = dyn_cast(S)) {
159
160
161
162
163 const auto *Dtor = TE->getTemporary()->getDestructor();
165 return true;
166
167
168 }
169
170 for (const auto *child : S->children())
172 return true;
173
174 return false;
175}
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217namespace {
218 struct LValueOrRValue {
219 LValue LV;
220 RValue RV;
221 };
222}
226 bool ignoreResult, bool forLValue) {
228
229 auto CommonBinder =
231 auto UnbindCommonOnExit =
232 llvm::make_scope_exit([&] { CommonBinder.unbind(CGF); });
233
235 BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready"));
236 BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend"));
237 BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup"));
238
239
241
242
244
245 auto &Builder = CGF.Builder;
246 llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save);
247 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
248 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
249
251 CGF.CurFn->getName(), Prefix, S);
252
254
256 "expected to be called in coroutine context");
257
259 SuspendIntrinsicCallArgs.push_back(
261
262 SuspendIntrinsicCallArgs.push_back(CGF.CurCoro.Data->CoroBegin);
263 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
264
266 llvm::Intrinsic::ID AwaitSuspendIID;
267
268 switch (SuspendReturnType) {
270 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
271 break;
273 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
274 break;
276 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
277 break;
278 }
279
280 llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID);
281
282
283 const bool AwaitSuspendCanThrow =
284 SuspendReturnType ==
287
288 llvm::CallBase *SuspendRet = nullptr;
289
290 if (AwaitSuspendCanThrow)
291 SuspendRet =
292 CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendIntrinsicCallArgs);
293 else
295 SuspendIntrinsicCallArgs);
296
297 assert(SuspendRet);
299
300 switch (SuspendReturnType) {
302 assert(SuspendRet->getType()->isVoidTy());
303 break;
305 assert(SuspendRet->getType()->isIntegerTy());
306
307
308 BasicBlock *RealSuspendBlock =
310 CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
312 break;
313 }
315 assert(SuspendRet->getType()->isVoidTy());
316 break;
317 }
318 }
319
320
321 const bool IsFinalSuspend = (Kind == AwaitKind::Final);
322 llvm::Function *CoroSuspend =
324 auto *SuspendResult = Builder.CreateCall(
325 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});
326
327
328 auto *Switch = Builder.CreateSwitch(SuspendResult, Coro.SuspendBB, 2);
329 Switch->addCase(Builder.getInt8(0), ReadyBlock);
330 Switch->addCase(Builder.getInt8(1), CleanupBlock);
331
332
335
336
338
339
340
345 CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh"));
346 Builder.CreateFlagStore(true, Coro.ResumeEHVar);
347
356
357
358 Builder.CreateFlagStore(false, Coro.ResumeEHVar);
360 LValueOrRValue Res;
361
363 return Res;
364 }
365
366 LValueOrRValue Res;
367 if (forLValue)
369 else
371
372 return Res;
373}
374
377 bool ignoreResult) {
379 CurCoro.Data->CurrentAwaitKind, aggSlot,
380 ignoreResult, false).RV;
381}
384 bool ignoreResult) {
386 aggSlot, ignoreResult, false).RV;
387}
388
390 ++CurCoro.Data->CoreturnCount;
393
394
397 }
400}
401
402
403#ifndef NDEBUG
407
408
409 assert(isa(RE) && "unexpected suspend expression type");
411}
412#endif
413
414llvm::Function *
416 Twine const &SuspendPointName,
418 std::string FuncName =
419 (CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str();
420
422
424
428
429 args.push_back(&AwaiterDecl);
430 args.push_back(&FrameDecl);
431
433 CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
434
435 llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
436
437 llvm::Function *Fn = llvm::Function::Create(
438 LTy, llvm::GlobalValue::InternalLinkage, FuncName, &CGM.getModule());
439
440 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
441 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
442
443 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
444
445 Fn->setMustProgress();
446 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
447
449
450
452 auto AwaiterLValue =
454
457
460
462
463 auto UnbindCommonOnExit =
464 llvm::make_scope_exit([&] { AwaiterBinder.unbind(*this); });
465 if (SuspendRet != nullptr) {
466 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
468 }
469
472 return Fn;
473}
474
478 "Can't have a scalar return unless the return type is a "
479 "reference type!");
482 false, true).LV;
483}
484
488 "Can't have a scalar return unless the return type is a "
489 "reference type!");
492 false, true).LV;
493}
494
495
496namespace {
497struct GetParamRef : public StmtVisitor {
498public:
500 GetParamRef() {}
502 assert(Expr == nullptr && "multilple declref in param move");
504 }
505 void VisitStmt(Stmt *S) {
507 if (C)
508 Visit(C);
509 }
510 }
511};
512}
513
514
515
516
517
518namespace {
519 struct ParamReferenceReplacerRAII {
522
524 : LocalDeclMap(LocalDeclMap) {}
525
526 void addCopy(DeclStmt const *PM) {
527
528
530 VarDecl const*VD = static_cast<VarDecl const*>(PM->getSingleDecl());
531 Expr const *InitExpr = VD->getInit();
532 GetParamRef Visitor;
533 Visitor.Visit(const_cast<Expr*>(InitExpr));
534 assert(Visitor.Expr);
535 DeclRefExpr *DREOrig = Visitor.Expr;
536 auto *PD = DREOrig->getDecl();
537
538 auto it = LocalDeclMap.find(PD);
539 assert(it != LocalDeclMap.end() && "parameter is not found");
540 SavedLocals.insert({ PD, it->second });
541
542 auto copyIt = LocalDeclMap.find(VD);
543 assert(copyIt != LocalDeclMap.end() && "parameter copy is not found");
544 it->second = copyIt->getSecond();
545 }
546
547 ~ParamReferenceReplacerRAII() {
548 for (auto&& SavedLocal : SavedLocals) {
549 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});
550 }
551 }
552 };
553}
554
555
556
557static SmallVector<llvm::OperandBundleDef, 1>
560
562 BundleList.emplace_back("funclet", EHPad);
563
564 return BundleList;
565}
566
567namespace {
568
569
570
571struct CallCoroEnd final : public EHScopeStack::Cleanup {
572 void Emit(CodeGenFunction &CGF, Flags flags) override {
573 auto &CGM = CGF.CGM;
574 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
575 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
576
579 CoroEndFn,
580 {NullPtr, CGF.Builder.getTrue(),
581 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},
582 Bundles);
583 if (Bundles.empty()) {
584
585
588 auto *CoroIsInRampFn = CGM.getIntrinsic(llvm::Intrinsic::coro_is_in_ramp);
589 auto *CoroIsInRamp = CGF.Builder.CreateCall(CoroIsInRampFn);
590 CGF.Builder.CreateCondBr(CoroIsInRamp, CleanupContBB, ResumeBB);
592 }
593 }
594};
595}
596
597namespace {
598
599struct CallCoroDelete final : public EHScopeStack::Cleanup {
600 Stmt *Deallocate;
601
602
603
604
605
606
607
608
609 void Emit(CodeGenFunction &CGF, Flags) override {
610
611
612
613 BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock();
614
618
621
622
623 auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;
624 if (!CoroFree) {
625 CGF.CGM.Error(Deallocate->getBeginLoc(),
626 "Deallocation expressoin does not refer to coro.free");
627 return;
628 }
629
630
631 auto *InsertPt = SaveInsertBlock->getTerminator();
632 CoroFree->moveBefore(InsertPt->getIterator());
633 CGF.Builder.SetInsertPoint(InsertPt);
634
635
636 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
637 auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr);
638 CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB);
639
640
641 InsertPt->eraseFromParent();
642 CGF.Builder.SetInsertPoint(AfterFreeBB);
643 }
644 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
645};
646}
647
648namespace {
649struct GetReturnObjectManager {
650 CodeGenFunction &CGF;
651 CGBuilderTy &Builder;
652 const CoroutineBodyStmt &S;
653
654 bool DirectEmit = false;
655
656 Address GroActiveFlag;
657 CodeGenFunction::AutoVarEmission GroEmission;
658
659 GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S)
660 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()),
661 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681 DirectEmit = [&]() {
683 assert(RVI && "expected RVI");
684 auto GroType = RVI->getType();
686 }();
687 }
688
689
690
691
692
693
694 void EmitGroAlloca() {
695 if (DirectEmit)
696 return;
697
698 auto *GroDeclStmt = dyn_cast_or_null(S.getResultDecl());
699 if (!GroDeclStmt) {
700
701 return;
702 }
703
704 auto *GroVarDecl = cast(GroDeclStmt->getSingleDecl());
705
706
708 "gro.active");
709 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
710
712
713 if (!GroVarDecl->isNRVOVariable()) {
714
715 auto *GroAlloca = dyn_cast_or_nullllvm::AllocaInst(
717 assert(GroAlloca && "expected alloca to be emitted");
718 GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
720 }
721
722
726
727
729 b++) {
730 if (auto *Cleanup = dyn_cast(&*b)) {
731 assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?");
732 Cleanup->setActiveFlag(GroActiveFlag);
733 Cleanup->setTestFlagInEHCleanup();
734 Cleanup->setTestFlagInNormalCleanup();
735 }
736 }
737 }
738
739 void EmitGroInit() {
740 if (DirectEmit) {
741
742
744
745
746
747
748
749
750
751
752
756 true);
757 }
758 return;
759 }
760
761 if (!GroActiveFlag.isValid()) {
762
763
765 return;
766 }
767
769 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);
770 }
771};
772}
773
777 const bool CanFallthrough = CGF.Builder.GetInsertBlock();
778 if (CanFallthrough)
781}
782
784 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());
785 auto &TI = CGM.getContext().getTargetInfo();
786 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
787
788 auto *EntryBB = Builder.GetInsertBlock();
793
794 auto *CoroId = Builder.CreateCall(
795 CGM.getIntrinsic(llvm::Intrinsic::coro_id),
796 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
798 CurCoro.Data->SuspendBB = RetBB;
799 assert(ShouldEmitLifetimeMarkers &&
800 "Must emit lifetime intrinsics for coroutines");
801
802
803
804 auto *CoroAlloc = Builder.CreateCall(
805 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});
806
807 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);
808
811 auto *AllocOrInvokeContBB = Builder.GetInsertBlock();
812
813
815 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");
816
817
818 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);
819 auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr);
820
822 Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB);
823
824
827 }
828 else {
829 Builder.CreateBr(InitBB);
830 }
831
833
834
836 Phi->addIncoming(NullPtr, EntryBB);
837 Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
838 auto *CoroBegin = Builder.CreateCall(
839 CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
840 CurCoro.Data->CoroBegin = CoroBegin;
841
842 GetReturnObjectManager GroManager(*this, S);
843 GroManager.EmitGroAlloca();
844
846 {
848 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
851
852
854 assert(
855 (ParamMoves.size() == 0 || (ParamMoves.size() == FnArgs.size())) &&
856 "ParamMoves and FnArgs should be the same size for coroutine function");
857 if (ParamMoves.size() == FnArgs.size() && DI)
858 for (const auto Pair : llvm::zip(FnArgs, ParamMoves))
860 {std::get<0>(Pair), std::get<1>(Pair)});
861
862
863
864
866
867
868
869
870
871
873 if (auto *ParmAlloca =
874 dyn_castllvm::AllocaInst(ParmAddr.getBasePointer())) {
875 ParmAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
876 llvm::MDNode::get(CGM.getLLVMContext(), {}));
877 }
878 }
882
883
884
885 }
886
888
890 auto *PromiseAddrVoidPtr =
892 CoroId->getIterator());
893
894
895 CoroId->setArgOperand(1, PromiseAddrVoidPtr);
896
897
898 GroManager.EmitGroInit();
899
901
902 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
906
907 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
908
909 if (CurCoro.Data->ExceptionHandler) {
910
911
912
913
914
915 BasicBlock *ContBB = nullptr;
916 if (CurCoro.Data->ResumeEHVar) {
920 "coro.resumed.eh");
921 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);
923 }
924
927 CurCoro.Data->ExceptionHandler);
928 auto *TryStmt =
930
934
935 if (ContBB)
937 }
938 else {
940 }
941
942
943 const bool CanFallthrough = Builder.GetInsertBlock();
944 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
945 if (CanFallthrough || HasCoreturns) {
947 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
949 } else {
950
951 EmitBlock(FinalBB, true);
952 }
953 }
954
956
957
958 llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);
959 Builder.CreateCall(CoroEnd,
960 {NullPtr, Builder.getFalse(),
961 llvm::ConstantTokenNone::get(CoroEnd->getContext())});
962
964
965
966 Expr *PreviousRetValue = nullptr;
967 if (GroManager.DirectEmit) {
970 }
972
973
974 if (PreviousRetValue)
976 }
977
978
979 CurFn->setPresplitCoroutine();
980
982 RD && RD->hasAttr())
983 CurFn->setCoroDestroyOnlyWhenComplete();
984}
985
986
988 unsigned int IID) {
990 switch (IID) {
991 default:
992 break;
993
994
995 case llvm::Intrinsic::coro_frame: {
998 }
999
1002 }
1003
1004 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin "
1005 "has been used earlier in this function");
1006 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());
1008 }
1009 case llvm::Intrinsic::coro_size: {
1011 llvm::IntegerType *T =
1012 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1013 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
1015 }
1016 case llvm::Intrinsic::coro_align: {
1018 llvm::IntegerType *T =
1019 Builder.getIntNTy(Context.getTypeSize(Context.getSizeType()));
1020 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
1022 }
1023
1024
1025
1026 case llvm::Intrinsic::coro_alloc:
1027 case llvm::Intrinsic::coro_begin:
1028 case llvm::Intrinsic::coro_free: {
1030 Args.push_back(CurCoro.Data->CoroId);
1031 break;
1032 }
1033 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_id has"
1034 " been used earlier in this function");
1035
1036 [[fallthrough]];
1037 }
1038
1039
1040 case llvm::Intrinsic::coro_suspend:
1041 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
1042 break;
1043 }
1046
1047
1048 if (IID == llvm::Intrinsic::coro_end)
1049 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
1050
1051 llvm::Function *F = CGM.getIntrinsic(IID);
1052 llvm::CallInst *Call = Builder.CreateCall(F, Args);
1053
1054
1055
1056
1057
1058 if (IID == llvm::Intrinsic::coro_id) {
1060 }
1061 else if (IID == llvm::Intrinsic::coro_begin) {
1064 }
1065 else if (IID == llvm::Intrinsic::coro_free) {
1066
1067
1070 }
1072}
static SmallString< 32 > buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind)
Definition CGCoroutine.cpp:113
static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, const CoroutineSuspendExpr *E)
Definition CGCoroutine.cpp:404
static void emitBodyAndFallthrough(CodeGenFunction &CGF, const CoroutineBodyStmt &S, Stmt *Body)
Definition CGCoroutine.cpp:774
static bool StmtCanThrow(const Stmt *S)
Definition CGCoroutine.cpp:145
static bool FunctionCanThrow(const FunctionDecl *D)
Definition CGCoroutine.cpp:135
static SmallVector< llvm::OperandBundleDef, 1 > getBundlesForCoroEnd(CodeGenFunction &CGF)
Definition CGCoroutine.cpp:558
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 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)
Definition CGCoroutine.cpp:476
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)
Definition CGCoroutine.cpp:987
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)
Definition CGCoroutine.cpp:389
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)
Definition CGCoroutine.cpp:382
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)
Definition CGCoroutine.cpp:415
void EmitCoroutineBody(const CoroutineBodyStmt &S)
Definition CGCoroutine.cpp:783
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)
Definition CGCoroutine.cpp:486
RValue EmitCoawaitExpr(const CoawaitExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Definition CGCoroutine.cpp:375
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'.
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.
Definition CGCoroutine.cpp:32
unsigned AwaitNum
Definition CGCoroutine.cpp:37
llvm::Value * ResumeEHVar
Definition CGCoroutine.cpp:54
CodeGenFunction::JumpDest FinalJD
Definition CGCoroutine.cpp:63
Stmt * ExceptionHandler
Definition CGCoroutine.cpp:48
CallExpr const * CoroIdExpr
Definition CGCoroutine.cpp:83
CodeGenFunction::JumpDest CleanupJD
Definition CGCoroutine.cpp:59
llvm::BasicBlock * SuspendBB
Definition CGCoroutine.cpp:45
AwaitKind CurrentAwaitKind
Definition CGCoroutine.cpp:36
llvm::CallInst * CoroId
Definition CGCoroutine.cpp:69
llvm::CallInst * CoroBegin
Definition CGCoroutine.cpp:74
unsigned CoreturnCount
Definition CGCoroutine.cpp:42
llvm::CallInst * LastCoroFree
Definition CGCoroutine.cpp:78
unsigned YieldNum
Definition CGCoroutine.cpp:38
CGCoroInfo()
Definition CGCoroutine.cpp:87
std::unique_ptr< CGCoroData > Data
~CGCoroInfo()
Definition CGCoroutine.cpp:88
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::PointerType * VoidPtrTy
llvm::PointerType * Int8PtrTy