clang: lib/CodeGen/CGCoroutine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

15#include "llvm/ADT/ScopeExit.h"

18

19using namespace clang;

20using namespace CodeGen;

21

22using llvm::Value;

23using llvm::BasicBlock;

24

25namespace {

26enum class AwaitKind { Init, Normal, Yield, Final };

27static constexpr llvm::StringLiteral AwaitKindStr[] = {"init", "await", "yield",

28 "final"};

29}

30

32

33

34

38

39

40

42

43

45

46

48

49

50

51

52

54

55

56

57

59

60

61

63

64

65

66

67

68 llvm::CallInst *CoroId = nullptr;

69

70

71

72

74

75

76

78

79

80

81

83};

84

85

88

90 CodeGenFunction::CGCoroInfo &CurCoro,

91 llvm::CallInst *CoroId,

92 CallExpr const *CoroIdExpr = nullptr) {

95 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),

96 "only one __builtin_coro_id can be used in a function");

97 else if (CoroIdExpr)

98 CGF.CGM.Error(CoroIdExpr->getBeginLoc(),

99 "__builtin_coro_id shall not be used in a C++ coroutine");

100 else

101 llvm_unreachable("EmitCoroutineBodyStatement called twice?");

102

103 return;

104 }

105

106 CurCoro.Data = std::make_unique();

109}

110

111

113 unsigned No = 0;

114 switch (Kind) {

115 case AwaitKind::Init:

116 case AwaitKind::Final:

117 break;

118 case AwaitKind::Normal:

120 break;

121 case AwaitKind::Yield:

123 break;

124 }

125 SmallString<32> Prefix(AwaitKindStr[static_cast<unsigned>(Kind)]);

126 if (No > 1) {

127 Twine(No).toVector(Prefix);

128 }

129 return Prefix;

130}

131

132

133

136 if (!Proto) {

137

138 return true;

139 }

142}

143

145 if (const auto *CE = dyn_cast(S)) {

146 const auto *Callee = CE->getDirectCallee();

147 if (!Callee)

148

149 return true;

150

152 return true;

153

154

155 }

156

157 if (const auto *TE = dyn_cast(S)) {

158

159

160

161

162 const auto *Dtor = TE->getTemporary()->getDestructor();

164 return true;

165

166

167 }

168

169 for (const auto *child : S->children())

171 return true;

172

173 return false;

174}

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

216namespace {

217 struct LValueOrRValue {

220 };

221}

225 bool ignoreResult, bool forLValue) {

226 auto *E = S.getCommonExpr();

227

228 auto CommonBinder =

230 auto UnbindCommonOnExit =

231 llvm::make_scope_exit([&] { CommonBinder.unbind(CGF); });

232

234 BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready"));

235 BasicBlock *SuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend"));

236 BasicBlock *CleanupBlock = CGF.createBasicBlock(Prefix + Twine(".cleanup"));

237

238

240

241

243

245 llvm::Function *CoroSave = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_save);

246 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);

247 auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});

248

250 CGF.CurFn->getName(), Prefix, S);

251

253

255 "expected to be called in coroutine context");

256

258 SuspendIntrinsicCallArgs.push_back(

260

261 SuspendIntrinsicCallArgs.push_back(CGF.CurCoro.Data->CoroBegin);

262 SuspendIntrinsicCallArgs.push_back(SuspendWrapper);

263

264 const auto SuspendReturnType = S.getSuspendReturnType();

265 llvm::Intrinsic::ID AwaitSuspendIID;

266

267 switch (SuspendReturnType) {

269 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;

270 break;

272 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;

273 break;

275 AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;

276 break;

277 }

278

279 llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID);

280

281

282 const bool AwaitSuspendCanThrow =

283 SuspendReturnType ==

286

287 llvm::CallBase *SuspendRet = nullptr;

288

289 if (AwaitSuspendCanThrow)

290 SuspendRet =

291 CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendIntrinsicCallArgs);

292 else

294 SuspendIntrinsicCallArgs);

295

296 assert(SuspendRet);

298

299 switch (SuspendReturnType) {

301 assert(SuspendRet->getType()->isVoidTy());

302 break;

304 assert(SuspendRet->getType()->isIntegerTy());

305

306

307 BasicBlock *RealSuspendBlock =

309 CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);

311 break;

312 }

314 assert(SuspendRet->getType()->isVoidTy());

315 break;

316 }

317 }

318

319

320 const bool IsFinalSuspend = (Kind == AwaitKind::Final);

321 llvm::Function *CoroSuspend =

323 auto *SuspendResult = Builder.CreateCall(

324 CoroSuspend, {SaveCall, Builder.getInt1(IsFinalSuspend)});

325

326

329 Switch->addCase(Builder.getInt8(1), CleanupBlock);

330

331

334

335

337

338

339

346

347 auto Loc = S.getResumeExpr()->getExprLoc();

355

356

359 LValueOrRValue Res;

360

362 return Res;

363 }

364

365 LValueOrRValue Res;

366 if (forLValue)

367 Res.LV = CGF.EmitLValue(S.getResumeExpr());

368 else

369 Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);

370

371 return Res;

372}

373

376 bool ignoreResult) {

379 ignoreResult, false).RV;

380}

383 bool ignoreResult) {

385 aggSlot, ignoreResult, false).RV;

386}

387

390 const Expr *RV = S.getOperand();

391 if (RV && RV->getType()->isVoidType() && !isa(RV)) {

392

393

394 RunCleanupsScope cleanupScope(*this);

396 }

397 EmitStmt(S.getPromiseCall());

399}

400

401

402#ifndef NDEBUG

405 const auto *RE = E->getResumeExpr();

406

407

408 assert(isa(RE) && "unexpected suspend expression type");

409 return cast(RE)->getCallReturnType(Ctx);

410}

411#endif

412

413llvm::Function *

415 Twine const &SuspendPointName,

417 std::string FuncName =

418 (CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str();

419

421

423

426 QualType ReturnTy = S.getSuspendExpr()->getType();

427

428 args.push_back(&AwaiterDecl);

429 args.push_back(&FrameDecl);

430

433

435

436 llvm::Function *Fn = llvm::Function::Create(

437 LTy, llvm::GlobalValue::PrivateLinkage, FuncName, &CGM.getModule());

438

439 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);

440 Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);

441

442 Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);

443

444 Fn->setMustProgress();

445 Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);

446

448

449

451 auto AwaiterLValue =

453

456

458 *this, S.getOpaqueValue(), AwaiterLValue);

459

460 auto *SuspendRet = EmitScalarExpr(S.getSuspendExpr());

461

462 auto UnbindCommonOnExit =

463 llvm::make_scope_exit([&] { AwaiterBinder.unbind(*this); });

464 if (SuspendRet != nullptr) {

465 Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);

467 }

468

471 return Fn;

472}

473

477 "Can't have a scalar return unless the return type is a "

478 "reference type!");

481 false, true).LV;

482}

483

487 "Can't have a scalar return unless the return type is a "

488 "reference type!");

491 false, true).LV;

492}

493

494

495namespace {

496struct GetParamRef : public StmtVisitor {

497public:

499 GetParamRef() {}

501 assert(Expr == nullptr && "multilple declref in param move");

503 }

504 void VisitStmt(Stmt *S) {

505 for (auto *C : S->children()) {

506 if (C)

507 Visit(C);

508 }

509 }

510};

511}

512

513

514

515

516

517namespace {

518 struct ParamReferenceReplacerRAII {

519 CodeGenFunction::DeclMapTy SavedLocals;

520 CodeGenFunction::DeclMapTy& LocalDeclMap;

521

522 ParamReferenceReplacerRAII(CodeGenFunction::DeclMapTy &LocalDeclMap)

523 : LocalDeclMap(LocalDeclMap) {}

524

525 void addCopy(DeclStmt const *PM) {

526

527

531 GetParamRef Visitor;

532 Visitor.Visit(const_cast<Expr*>(InitExpr));

533 assert(Visitor.Expr);

535 auto *PD = DREOrig->getDecl();

536

537 auto it = LocalDeclMap.find(PD);

538 assert(it != LocalDeclMap.end() && "parameter is not found");

539 SavedLocals.insert({ PD, it->second });

540

541 auto copyIt = LocalDeclMap.find(VD);

542 assert(copyIt != LocalDeclMap.end() && "parameter copy is not found");

543 it->second = copyIt->getSecond();

544 }

545

546 ~ParamReferenceReplacerRAII() {

547 for (auto&& SavedLocal : SavedLocals) {

548 LocalDeclMap.insert({SavedLocal.first, SavedLocal.second});

549 }

550 }

551 };

552}

553

554

555

559

561 BundleList.emplace_back("funclet", EHPad);

562

563 return BundleList;

564}

565

566namespace {

567

568

569

572 auto &CGM = CGF.CGM;

573 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);

574 llvm::Function *CoroEndFn = CGM.getIntrinsic(llvm::Intrinsic::coro_end);

575

577 auto *CoroEnd =

578 CGF.Builder.CreateCall(CoroEndFn,

579 {NullPtr, CGF.Builder.getTrue(),

580 llvm::ConstantTokenNone::get(CoroEndFn->getContext())},

581 Bundles);

582 if (Bundles.empty()) {

583

584

587 CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB);

589 }

590 }

591};

592}

593

594namespace {

595

597 Stmt *Deallocate;

598

599

600

601

602

603

604

605

607

608

609

610 BasicBlock *SaveInsertBlock = CGF.Builder.GetInsertBlock();

611

615

618

619

620 auto *CoroFree = CGF.CurCoro.Data->LastCoroFree;

621 if (!CoroFree) {

622 CGF.CGM.Error(Deallocate->getBeginLoc(),

623 "Deallocation expressoin does not refer to coro.free");

624 return;

625 }

626

627

628 auto *InsertPt = SaveInsertBlock->getTerminator();

629 CoroFree->moveBefore(InsertPt);

630 CGF.Builder.SetInsertPoint(InsertPt);

631

632

633 auto *NullPtr = llvm::ConstantPointerNull::get(CGF.Int8PtrTy);

634 auto *Cond = CGF.Builder.CreateICmpNE(CoroFree, NullPtr);

635 CGF.Builder.CreateCondBr(Cond, FreeBB, AfterFreeBB);

636

637

638 InsertPt->eraseFromParent();

639 CGF.Builder.SetInsertPoint(AfterFreeBB);

640 }

641 explicit CallCoroDelete(Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}

642};

643}

644

645namespace {

646struct GetReturnObjectManager {

650

651 bool DirectEmit = false;

652

654 CodeGenFunction::AutoVarEmission GroEmission;

655

657 : CGF(CGF), Builder(CGF.Builder), S(S), GroActiveFlag(Address::invalid()),

658 GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678 DirectEmit = [&]() {

679 auto *RVI = S.getReturnValueInit();

680 assert(RVI && "expected RVI");

681 auto GroType = RVI->getType();

683 }();

684 }

685

686

687

688

689

690

691 void EmitGroAlloca() {

692 if (DirectEmit)

693 return;

694

695 auto *GroDeclStmt = dyn_cast_or_null(S.getResultDecl());

696 if (!GroDeclStmt) {

697

698 return;

699 }

700

701 auto *GroVarDecl = cast(GroDeclStmt->getSingleDecl());

702

703

705 "gro.active");

706 Builder.CreateStore(Builder.getFalse(), GroActiveFlag);

707

709 auto *GroAlloca = dyn_cast_or_nullllvm::AllocaInst(

710 GroEmission.getOriginalAllocatedAddress().getPointer());

711 assert(GroAlloca && "expected alloca to be emitted");

712 GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,

714

715

719

720

722 b++) {

723 if (auto *Cleanup = dyn_cast(&*b)) {

724 assert(!Cleanup->hasActiveFlag() && "cleanup already has active flag?");

725 Cleanup->setActiveFlag(GroActiveFlag);

726 Cleanup->setTestFlagInEHCleanup();

727 Cleanup->setTestFlagInNormalCleanup();

728 }

729 }

730 }

731

732 void EmitGroInit() {

733 if (DirectEmit) {

734

735

737

738

739

740

741

742

743

744

745

748 S.getReturnValue()->getType().getQualifiers(),

749 true);

750 }

751 return;

752 }

753

754 if (!GroActiveFlag.isValid()) {

755

756

757 CGF.EmitStmt(S.getResultDecl());

758 return;

759 }

760

762 Builder.CreateStore(Builder.getTrue(), GroActiveFlag);

763 }

764};

765}

766

770 const bool CanFallthrough = CGF.Builder.GetInsertBlock();

771 if (CanFallthrough)

772 if (Stmt *OnFallthrough = S.getFallthroughHandler())

774}

775

777 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());

779 unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();

780

781 auto *EntryBB = Builder.GetInsertBlock();

786

787 auto *CoroId = Builder.CreateCall(

789 {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});

792 assert(ShouldEmitLifetimeMarkers &&

793 "Must emit lifetime intrinsics for coroutines");

794

795

796

797 auto *CoroAlloc = Builder.CreateCall(

798 CGM.getIntrinsic(llvm::Intrinsic::coro_alloc), {CoroId});

799

800 Builder.CreateCondBr(CoroAlloc, AllocBB, InitBB);

801

803 auto *AllocateCall = EmitScalarExpr(S.getAllocate());

804 auto *AllocOrInvokeContBB = Builder.GetInsertBlock();

805

806

807 if (auto *RetOnAllocFailure = S.getReturnStmtOnAllocFailure()) {

808 auto *RetOnFailureBB = createBasicBlock("coro.ret.on.failure");

809

810

811 auto *NullPtr = llvm::ConstantPointerNull::get(Int8PtrTy);

812 auto *Cond = Builder.CreateICmpNE(AllocateCall, NullPtr);

813

814 emitCondLikelihoodViaExpectIntrinsic(Cond, Stmt::LH_Likely);

815 Builder.CreateCondBr(Cond, InitBB, RetOnFailureBB);

816

817

820 }

821 else {

822 Builder.CreateBr(InitBB);

823 }

824

826

827

829 Phi->addIncoming(NullPtr, EntryBB);

830 Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);

831 auto *CoroBegin = Builder.CreateCall(

832 CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});

834

835 GetReturnObjectManager GroManager(*this, S);

836 GroManager.EmitGroAlloca();

837

839 {

841 ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);

842 CodeGenFunction::RunCleanupsScope ResumeScope(*this);

844

845

847 assert(

848 (ParamMoves.size() == 0 || (ParamMoves.size() == FnArgs.size())) &&

849 "ParamMoves and FnArgs should be the same size for coroutine function");

850 if (ParamMoves.size() == FnArgs.size() && DI)

851 for (const auto Pair : llvm::zip(FnArgs, ParamMoves))

853 {std::get<0>(Pair), std::get<1>(Pair)});

854

855

856

857

858 for (auto *PM : S.getParamMoves()) {

860 ParamReplacer.addCopy(cast(PM));

861

862

863

864 }

865

866 EmitStmt(S.getPromiseDeclStmt());

867

869 auto *PromiseAddrVoidPtr =

871 CoroId->getIterator());

872

873

874 CoroId->setArgOperand(1, PromiseAddrVoidPtr);

875

876

877 GroManager.EmitGroInit();

878

880

881 CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;

882 CurCoro.Data->ExceptionHandler = S.getExceptionHandler();

883 EmitStmt(S.getInitSuspendStmt());

885

886 CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;

887

889

890

891

892

893

894 BasicBlock *ContBB = nullptr;

899 "coro.resumed.eh");

900 Builder.CreateCondBr(SkipBody, ContBB, BodyBB);

902 }

903

904 auto Loc = S.getBeginLoc();

907 auto *TryStmt =

909

913

914 if (ContBB)

916 }

917 else {

919 }

920

921

922 const bool CanFallthrough = Builder.GetInsertBlock();

923 const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;

924 if (CanFallthrough || HasCoreturns) {

926 CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;

927 EmitStmt(S.getFinalSuspendStmt());

928 } else {

929

930 EmitBlock(FinalBB, true);

931 }

932 }

933

935

936

937 llvm::Function *CoroEnd = CGM.getIntrinsic(llvm::Intrinsic::coro_end);

938 Builder.CreateCall(CoroEnd,

939 {NullPtr, Builder.getFalse(),

940 llvm::ConstantTokenNone::get(CoroEnd->getContext())});

941

942 if (Stmt *Ret = S.getReturnStmt()) {

943

944

945 if (GroManager.DirectEmit)

946 cast(Ret)->setRetValue(nullptr);

948 }

949

950

951 CurFn->setPresplitCoroutine();

952

954 RD && RD->hasAttr())

955 CurFn->setCoroDestroyOnlyWhenComplete();

956}

957

958

960 unsigned int IID) {

962 switch (IID) {

963 default:

964 break;

965

966

967 case llvm::Intrinsic::coro_frame: {

970 }

971

974 }

975

977 "has been used earlier in this function");

978 auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());

980 }

981 case llvm::Intrinsic::coro_size: {

985 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);

987 }

988 case llvm::Intrinsic::coro_align: {

992 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);

994 }

995

996

997

998 case llvm::Intrinsic::coro_alloc:

999 case llvm::Intrinsic::coro_begin:

1000 case llvm::Intrinsic::coro_free: {

1003 break;

1004 }

1005 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_id has"

1006 " been used earlier in this function");

1007

1008 [[fallthrough]];

1009 }

1010

1011

1012 case llvm::Intrinsic::coro_suspend:

1013 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));

1014 break;

1015 }

1016 for (const Expr *Arg : E->arguments())

1018

1019

1020 if (IID == llvm::Intrinsic::coro_end)

1021 Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));

1022

1024 llvm::CallInst *Call = Builder.CreateCall(F, Args);

1025

1026

1027

1028

1029

1030 if (IID == llvm::Intrinsic::coro_id) {

1032 }

1033 else if (IID == llvm::Intrinsic::coro_begin) {

1036 }

1037 else if (IID == llvm::Intrinsic::coro_free) {

1038

1039

1042 }

1044}

static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Coro, CoroutineSuspendExpr const &S, AwaitKind Kind, AggValueSlot aggSlot, bool ignoreResult, bool forLValue)

static SmallString< 32 > buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind)

static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, const CoroutineSuspendExpr *E)

static void createCoroData(CodeGenFunction &CGF, CodeGenFunction::CGCoroInfo &CurCoro, llvm::CallInst *CoroId, CallExpr const *CoroIdExpr=nullptr)

static void emitBodyAndFallthrough(CodeGenFunction &CGF, const CoroutineBodyStmt &S, Stmt *Body)

static bool StmtCanThrow(const Stmt *S)

static bool FunctionCanThrow(const FunctionDecl *D)

static SmallVector< llvm::OperandBundleDef, 1 > getBundlesForCoroEnd(CodeGenFunction &CGF)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

CanQualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

const TargetInfo & getTargetInfo() const

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]).

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 * 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.

llvm::StoreInst * CreateFlagStore(bool Value, llvm::Value *Addr)

Emit a store to an i1 flag variable.

llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)

llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")

llvm::LoadInst * CreateFlagLoad(llvm::Value *Addr, const llvm::Twine &Name="")

Emit a load from an i1 flag variable.

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.

static OpaqueValueMappingData bind(CodeGenFunction &CGF, const OpaqueValueExpr *ov, const Expr *e)

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

void FinishFunction(SourceLocation EndLoc=SourceLocation())

FinishFunction - Complete IR generation of the current function.

void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)

EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.

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...

LValue EmitCoawaitLValue(const CoawaitExpr *E)

LValue getOrCreateOpaqueLValueMapping(const OpaqueValueExpr *e)

Given an opaque value expression, return its LValue mapping if it exists, otherwise create one.

AwaitSuspendWrapperInfo CurAwaitSuspendWrapper

LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

EmitLValue - Emit code to compute a designator that specifies the location of the expression.

llvm::BasicBlock * getEHResumeBlock(bool isCleanup)

llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)

createBasicBlock - Create an LLVM basic block.

void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)

EmitBlock - Emit the given block.

llvm::Function * generateAwaitSuspendWrapper(Twine const &CoroName, Twine const &SuspendPointName, CoroutineSuspendExpr const &S)

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...

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...

void EmitIgnoredExpr(const Expr *E)

EmitIgnoredExpr - Emit an expression in a context which ignores the result.

void EmitAutoVarInit(const AutoVarEmission &emission)

LValue EmitCoyieldLValue(const CoyieldExpr *E)

RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID)

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 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()

void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)

void EmitCoroutineBody(const CoroutineBodyStmt &S)

llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")

ASTContext & getContext() const

void EmitBranchThroughCleanup(JumpDest Dest)

EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...

AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)

void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})

EmitStmt - Emit the code for the statement.

void EmitAutoVarCleanups(const AutoVarEmission &emission)

llvm::CallBase * EmitCallOrInvoke(llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const Twine &Name="")

llvm::SmallVector< const ParmVarDecl *, 4 > FnArgs

Save Parameter Decl for coroutine.

RValue EmitCoawaitExpr(const CoawaitExpr &E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)

LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)

Address GetAddrOfLocalVar(const VarDecl *VD)

GetAddrOfLocalVar - Return the address of a local variable.

void EmitCoreturnStmt(const CoreturnStmt &S)

Address ReturnValue

ReturnValue - The temporary alloca to hold the return value.

void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock=false)

llvm::Instruction * CurrentFuncletPad

llvm::LLVMContext & getLLVMContext()

llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)

EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...

llvm::Module & getModule() const

CodeGenTypes & getTypes()

void Error(SourceLocation loc, StringRef error)

Emit a general error that something can't be done.

ASTContext & getContext() const

llvm::LLVMContext & getLLVMContext()

llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})

llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)

GetFunctionType - Get the LLVM function type for.

const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)

A builtin function is a freestanding function using the default C conventions.

Information for lazily generating a cleanup.

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)

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.

Represents the body of a coroutine.

Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...

Represents a 'co_yield' expression.

A reference to a declared variable, function, enum, etc.

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

bool isSingleDecl() const

isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.

const Decl * getSingleDecl() const

This represents one expression.

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.

A (possibly-)qualified type.

StmtVisitor - This class implements a simple visitor for Stmt subclasses.

Stmt - This represents one statement.

@ LH_Likely

Branch has the [[likely]] attribute.

SourceLocation getBeginLoc() const LLVM_READONLY

unsigned getNewAlign() const

Return the largest alignment for which a suitably-sized allocation with '::operator new(size_t)' is g...

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

Represents a variable declaration or definition.

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 isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType)

const FunctionProtoType * T

@ Other

Other implicit parameter.

llvm::Value * ResumeEHVar

CodeGenFunction::JumpDest FinalJD

CallExpr const * CoroIdExpr

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::IntegerType * SizeTy

llvm::PointerType * Int8PtrTy