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