14#include "mlir/Support/LLVM.h"
68struct GetParamRef :
public StmtVisitor<GetParamRef> {
73 assert(
expr ==
nullptr &&
"multilple declref in param move");
76 void VisitStmt(
Stmt *s) {
87struct ParamReferenceReplacerRAII {
92 : localDeclMap(localDeclMap) {}
94 void addCopy(
const DeclStmt *pm) {
98 const VarDecl *vd =
static_cast<const VarDecl *
>(pm->
getSingleDecl());
99 const Expr *initExpr = vd->
getInit();
101 visitor.Visit(
const_cast<Expr *
>(initExpr));
102 assert(visitor.expr);
103 DeclRefExpr *dreOrig = visitor.expr;
106 auto it = localDeclMap.find(pd);
107 assert(it != localDeclMap.end() &&
"parameter is not found");
108 savedLocals.insert({pd, it->second});
110 auto copyIt = localDeclMap.find(vd);
111 assert(copyIt != localDeclMap.end() &&
"parameter copy is not found");
112 it->second = copyIt->getSecond();
115 ~ParamReferenceReplacerRAII() {
116 for (
auto &&savedLocal : savedLocals) {
117 localDeclMap.insert({savedLocal.first, savedLocal.second});
133 cir::CoroIdOp coroId,
134 CallExpr const *coroIdExpr =
nullptr) {
138 cgf.
cgm.
error(coroIdExpr->getBeginLoc(),
139 "only one __builtin_coro_id can be used in a function");
141 cgf.
cgm.
error(coroIdExpr->getBeginLoc(),
142 "__builtin_coro_id shall not be used in a C++ coroutine");
144 llvm_unreachable(
"EmitCoroutineBodyStatement called twice?");
154static mlir::LogicalResult
164 if (cgf.
emitStmt(body,
true).failed())
165 return mlir::failure();
176 const bool canFallthrough = !currLexScope->
hasCoreturn();
179 if (cgf.
emitStmt(onFallthrough,
true).failed())
180 return mlir::failure();
182 return mlir::success();
192 auto coroId = cir::CoroIdOp::create(
cgm.getBuilder(), loc, args);
200 cgm.error(e->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
201 " been used earlier in this function");
205 return cir::CoroAllocOp::create(
206 cgm.getBuilder(), loc,
207 mlir::ValueRange{curCoro.data->coroId.getResult()});
214 cgm.error(e->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
215 " been used earlier in this function");
219 args.push_back(
curCoro.data->coroId.getResult());
223 auto coroBegin = cir::CoroBeginOp::create(
cgm.getBuilder(), loc, args);
224 curCoro.data->coroBegin = coroBegin;
235 args.push_back(cir::TokenNoneOp::create(builder, loc));
236 return cir::CoroEndOp::create(builder, loc, {
cgm.voidTy}, args);
243 cgm.error(e->
getBeginLoc(),
"this builtin expect that __builtin_coro_id has"
244 " been used earlier in this function");
249 cir::CoroFreeOp::create(
cgm.getBuilder(), loc,
250 mlir::ValueRange{curCoro.data->coroId.getResult(),
251 curCoro.data->coroBegin});
253 curCoro.data->lastCoroFree = coroFree;
259 return cir::CoroSizeOp::create(
cgm.getBuilder(), loc,
265 return cir::CoroAlignOp::create(
cgm.getBuilder(), loc,
277 auto coroPromise = cir::CoroPromiseOp::create(
cgm.getBuilder(), loc, args);
283 return cir::CoroDoneOp::create(
cgm.getBuilder(), loc,
289 return cir::CoroResumeOp::create(
cgm.getBuilder(), loc,
296 return cir::CoroDestroyOp::create(
cgm.getBuilder(), loc,
302 return cir::CoroNoopOp::create(
cgm.getBuilder(), loc);
309 args.push_back(cir::TokenNoneOp::create(builder, loc));
312 return cir::CoroSuspendOp::create(
cgm.getBuilder(), loc, args);
315static mlir::LogicalResult
329 ~handlerEmitter()
override =
default;
340 cir::ConstantOp nullPtrCst = builder.getNullPtr(
voidPtrTy, openCurlyLoc);
342 auto fn = mlir::cast<cir::FuncOp>(
curFn);
343 fn.setCoroutineKind(cir::CoroutineKind::Coroutine);
347 cir::CoroIdOp coroId = cir::CoroIdOp::create(
348 cgm.getBuilder(), openCurlyLoc,
349 mlir::ValueRange{builder.getUInt32(newAlign, openCurlyLoc), nullPtrCst,
350 nullPtrCst, nullPtrCst});
355 cir::CoroAllocOp coroAlloc = cir::CoroAllocOp::create(
356 cgm.getBuilder(), openCurlyLoc,
357 mlir::ValueRange{curCoro.data->coroId.getResult()});
364 openCurlyLoc,
"__coro_frame_addr",
367 mlir::Value storeAddr = coroFrame.
getPointer();
368 builder.CIRBaseBuilderTy::createStore(openCurlyLoc, nullPtrCst, storeAddr);
369 mlir::LogicalResult res = mlir::success();
371 builder, openCurlyLoc, coroAlloc.getResult(),
373 [&](mlir::OpBuilder &b, mlir::Location loc) {
374 mlir::Value allocatedPtr = emitScalarExpr(s.getAllocate());
375 builder.CIRBaseBuilderTy::createStore(loc, allocatedPtr, storeAddr);
377 if (Stmt *retOnAllocFailure = s.getReturnStmtOnAllocFailure()) {
378 mlir::Value isPtrNull = builder.createPtrIsNull(allocatedPtr);
379 assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
380 cir::IfOp::create(builder, loc, isPtrNull, false,
381 [&](mlir::OpBuilder &b, mlir::Location loc) {
382 res = emitStmt(retOnAllocFailure,
384 cir::UnreachableOp::create(builder, loc);
387 cir::YieldOp::create(builder, loc);
393 curCoro.
data->coroBegin = cir::CoroBeginOp::create(
396 curCoro.data->coroId.getResult(),
397 cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr)});
406 assert((paramMoves.size() == 0 || (paramMoves.size() ==
fnArgs.size())) &&
407 "ParamMoves and FnArgs should be the same size for coroutine "
416 for (
auto *pm : paramMoves) {
418 return mlir::failure();
423 auto initialSuspendBuilder = [&]() -> mlir::LogicalResult {
424 if (
emitStmt(s.getPromiseDeclStmt(),
true).failed())
425 return mlir::failure();
430 mlir::OpBuilder::InsertionGuard guard(builder);
431 builder.setInsertionPoint(coroId);
434 coroId.getPromiseMutable().assign(promisePtr);
450 s.getReturnValue()->getType().getQualifiers(),
453 curCoro.
data->currentAwaitKind = cir::AwaitKind::Init;
454 curCoro.
data->exceptionHandler = s.getExceptionHandler();
456 if (
emitStmt(s.getInitSuspendStmt(),
true).failed())
457 return mlir::failure();
459 cir::YieldOp::create(builder, openCurlyLoc);
460 return mlir::success();
465 auto bodyBuilder = [&]() -> mlir::LogicalResult {
466 curCoro.data->currentAwaitKind = cir::AwaitKind::User;
468 if (
curCoro.data->exceptionHandler) {
484 if (
curCoro.data->resumeEHVar.isValid()) {
485 mlir::Value shouldSkip = builder.createFlagLoad(
486 openCurlyLoc,
curCoro.data->resumeEHVar.getPointer());
487 mlir::LogicalResult res = mlir::success();
488 cir::IfOp::create(builder, openCurlyLoc, shouldSkip,
490 [&](mlir::OpBuilder &b, mlir::Location loc) {
492 builder.createYield(openCurlyLoc);
496 return mlir::failure();
499 return mlir::failure();
503 return mlir::failure();
506 return mlir::success();
511 auto finalSuspendBuilder = [&]() -> mlir::LogicalResult {
520 const bool canFallthrough =
curLexScope->hasCoreturn();
521 const bool hasCoreturns =
curCoro.data->coreturnCount > 0;
522 if (canFallthrough || hasCoreturns) {
523 curCoro.data->currentAwaitKind = cir::AwaitKind::Final;
524 if (
emitStmt(s.getFinalSuspendStmt(),
true)
526 return mlir::failure();
528 cir::YieldOp::create(builder, openCurlyLoc);
529 return mlir::success();
533 auto destroyBuilder = [&]() -> mlir::LogicalResult {
534 Stmt *deallocate = s.getDeallocate();
535 if (
emitStmt(deallocate,
true).failed()) {
537 "failed to emit coroutine deallocation expression");
538 return mlir::failure();
541 cir::CoroFreeOp coroFree =
curCoro.data->lastCoroFree;
545 "Deallocation expression does not refer to coro.free");
546 return mlir::failure();
549 mlir::OpBuilder::InsertionGuard guard(builder);
550 builder.setInsertionPointAfter(coroFree);
551 mlir::Value isPtrNotNull =
552 builder.createPtrIsNotNull(coroFree.getResult());
554 llvm::SmallVector<mlir::Operation *> opsToMove;
555 mlir::Block *block = builder.getInsertionBlock();
556 mlir::Block::iterator it(isPtrNotNull.getDefiningOp());
558 for (++it; it != block->end(); ++it)
559 opsToMove.push_back(&*it);
561 auto ifOp = cir::IfOp::create(
564 [&](mlir::OpBuilder &builder, mlir::Location loc) {
565 cir::YieldOp::create(builder, loc);
568 mlir::Operation *yieldOp = ifOp.getThenRegion().back().getTerminator();
569 for (
auto *op : opsToMove)
570 op->moveBefore(yieldOp);
573 cir::YieldOp::create(builder, openCurlyLoc);
574 return mlir::success();
581 auto exitBuilder = [&]() {
582 cir::ConstantOp nullHandler =
583 builder.getNullPtr(builder.getVoidPtrTy(), openCurlyLoc);
584 cir::ConstantOp noUnwind = builder.getBool(
false, openCurlyLoc);
585 auto tkNone = cir::TokenNoneOp::create(builder, openCurlyLoc);
586 cir::CoroEndOp::create(builder, openCurlyLoc, nullHandler, noUnwind,
589 if (
auto *ret = cast_or_null<ReturnStmt>(s.getReturnStmt())) {
592 Expr *previousRetValue = ret->getRetValue();
593 ret->setRetValue(
nullptr);
595 return mlir::failure();
596 mlir::Block *block = builder.getInsertionBlock();
602 ret->setRetValue(previousRetValue);
604 cir::ReturnOp::create(builder, openCurlyLoc);
607 return mlir::success();
610 cir::CoroutineOp coro = cir::CoroutineOp::create(
611 builder, openCurlyLoc,
613 [&](mlir::OpBuilder &b, mlir::Location loc) {
614 if (initialSuspendBuilder().failed())
615 res = mlir::failure();
618 [&](mlir::OpBuilder &b, mlir::Location loc) {
619 if (bodyBuilder().failed())
620 res = mlir::failure();
623 [&](mlir::OpBuilder &b, mlir::Location loc) {
624 if (finalSuspendBuilder().failed())
625 res = mlir::failure();
628 [&](mlir::OpBuilder &b, mlir::Location loc) {
629 if (destroyBuilder().failed())
630 res = mlir::failure();
633 [&](mlir::OpBuilder &b, mlir::Location loc) {
634 if (exitBuilder().failed())
635 res = mlir::failure();
638 if (coro && !coro.getBody().empty()) {
639 mlir::Block &lastBlock = coro.getBody().back();
640 mlir::Block *prevBlock = lastBlock.getPrevNode();
641 if (lastBlock.empty() && lastBlock.hasNoPredecessors() && prevBlock &&
644 }
else if (!lastBlock.mightHaveTerminator()) {
645 mlir::OpBuilder::InsertionGuard guard(builder);
646 builder.setInsertionPointToEnd(&lastBlock);
647 cir::YieldOp::create(builder, openCurlyLoc);
664 if (
const auto *ce = dyn_cast<CallExpr>(s)) {
671 if (
const auto *te = dyn_cast<CXXBindTemporaryExpr>(s))
675 return llvm::any_of(s->
children(), [](
const Stmt *child) {
676 return child && stmtCanThrow(child);
697struct LValueOrRValue {
713 mlir::Block *scopeParentBlock,
714 mlir::Value &tmpResumeRValAddr,
bool forLValue) {
715 [[maybe_unused]] mlir::LogicalResult awaitBuild = mlir::success();
716 LValueOrRValue awaitRes;
731 std::optional<CIRGenFunction::ConditionalEvaluation> resumeEval;
732 const bool resumeDefersCleanups =
736 else if (resumeDefersCleanups)
738 "resume expression cleanups without a full-expression "
748 resultBind = dyn_cast<CXXBindTemporaryExpr>(s.
getResumeExpr());
761 [[maybe_unused]] cir::AwaitOp awaitOp = cir::AwaitOp::create(
764 [&](mlir::OpBuilder &b, mlir::Location loc) {
765 Expr *condExpr = s.getReadyExpr()->IgnoreParens();
766 builder.createCondition(cgf.evaluateExprAsBool(condExpr));
769 [&](mlir::OpBuilder &b, mlir::Location loc) {
774 switch (s.getSuspendReturnType()) {
775 case CoroutineSuspendExpr::SuspendReturnType::SuspendBool: {
776 mlir::Value suspendRet = cgf.evaluateExprAsBool(s.getSuspendExpr());
778 cir::CoroSuspendPoint::create(builder, loc, suspendRet);
781 case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid:
782 cgf.emitScalarExpr(s.getSuspendExpr());
784 cir::CoroSuspendPoint::create(builder, loc);
786 case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle:
787 cgf.cgm.errorNYI(s.getSourceRange(),
788 "await_suspend returning handle");
789 cir::CoroSuspendPoint::create(builder, loc);
794 [&](mlir::OpBuilder &b, mlir::Location loc) {
796 resumeEval->beginEvaluation();
808 ASTContext &ctx = cgf.getContext();
809 SourceLocation resumeLoc = s.getResumeExpr()->getExprLoc();
810 mlir::Location mlirLoc = cgf.getLoc(resumeLoc);
811 coro.resumeEHVar = cgf.createTempAlloca(
814 builder.createFlagStore(mlirLoc,
false,
815 coro.resumeEHVar.getPointer());
817 CXXCatchStmt catchStmt(resumeLoc,
818 nullptr, coro.exceptionHandler);
821 resumeLoc, resumeLoc);
822 CXXTryStmt *tryStmt =
825 struct resumeEmitter final : CIRGenFunction::cxxTryBodyEmitter {
826 const CXXTryStmt &tryStmt;
827 const Expr *resumeExpr;
829 mlir::Value resumeEHVar;
830 resumeEmitter(
const CXXTryStmt &tryStmt,
const Expr *resumeExpr,
831 mlir::Location loc, Address resumeEHVar)
832 : tryStmt(tryStmt), resumeExpr(resumeExpr), loc(loc),
833 resumeEHVar(resumeEHVar.getPointer()) {}
835 mlir::LogicalResult operator()(CIRGenFunction &cgf)
override {
838 CIRGenFunction::FullExprCleanupScope fullExpr(cgf, resumeExpr);
839 mlir::LogicalResult res =
840 cgf.
emitStmt(tryStmt.getTryBlock(),
true);
846 ~resumeEmitter()
override =
default;
847 } emitter{*tryStmt, s.getResumeExpr(), mlirLoc, coro.resumeEHVar};
853 }
else if (forLValue) {
854 awaitRes.lv = cgf.
emitLValue(s.getResumeExpr());
855 assert(awaitRes.lv.isSimple() &&
856 "expected simple lvalue for coroutine resume");
857 mlir::Value ptr = awaitRes.lv.getPointer();
858 llvm::StringRef tmpName =
kind == cir::AwaitKind::Yield
859 ?
"__coyield_resume_lval"
860 :
"__coawait_resume_lval";
863 builder.getBestAllocaInsertPoint(scopeParentBlock));
864 builder.CIRBaseBuilderTy::createStore(loc, ptr, tmpResumeRValAddr);
867 cgf.
emitAnyExpr(s.getResumeExpr(), aggSlot, ignoreResult);
868 if (!awaitRes.rv.isIgnored()) {
869 RValue rv = awaitRes.rv;
874 "__coawait_resume_rval", value.getType(), loc,
876 builder.getBestAllocaInsertPoint(scopeParentBlock));
878 builder.CIRBaseBuilderTy::createStore(loc, value,
881 assert(rv.
isAggregate() &&
"unexpected rvalue kind");
887 resumeEval->endEvaluation();
890 cir::YieldOp::create(builder, loc);
894 (resumeDefersCleanups && !resumeEval)) &&
895 "a resume expression cleanup was pushed in the resume region");
903 aggSlot.getAddress());
905 assert(awaitBuild.succeeded() &&
"Should know how to codegen");
923 [[maybe_unused]] mlir::Value tmpResumeRValAddr;
928 ignoreResult, currEntryBlock, tmpResumeRValAddr,
967 assert(
isa<CallExpr>(re) &&
"unexpected suspend expression type");
973 cir::AwaitKind
kind) {
976 "Can't have a scalar return unless the return type is a "
980 mlir::Value tmpResumeLValAddr;
983 false, currEntryBlock,
984 tmpResumeLValAddr,
true)
986 if (!tmpResumeLValAddr) {
988 "expected resume in try/catch");
996 Address addr = lv.getAddress();
997 mlir::Value loadedPtr =
998 cir::LoadOp::create(cgf.
getBuilder(), scopeLoc,
999 addr.
getPointer().getType(), tmpResumeLValAddr);
1013 ++
curCoro.data->coreturnCount;
1024 return mlir::failure();
1026 cir::CoReturnOp::create(builder, loc);
1031 builder.createBlock(builder.getBlock()->getParent());
1032 return mlir::success();
static void createCoroData(CIRGenFunction &cgf, CIRGenFunction::CGCoroInfo &curCoro, cir::CoroIdOp coroId, CallExpr const *coroIdExpr=nullptr)
static QualType getCoroutineSuspendExprReturnType(const ASTContext &ctx, const CoroutineSuspendExpr *e)
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 LValue emitSuspendLValue(CIRGenFunction &cgf, const CoroutineSuspendExpr *e, cir::AwaitKind kind)
static bool stmtCanThrow(const Stmt *s)
static RValue emitSuspendExpr(CIRGenFunction &cgf, const CoroutineSuspendExpr &e, cir::AwaitKind kind, AggValueSlot aggSlot, bool ignoreResult)
static bool functionCanThrow(const FunctionDecl *d)
static bool isResumeExprInTryCatch(const CGCoroData &coro, cir::AwaitKind kind, const CoroutineSuspendExpr &s)
static mlir::LogicalResult coroutineBodyExceptionHelper(CIRGenFunction &cgf, const CoroutineBodyStmt &s)
static mlir::LogicalResult emitBodyAndFallthrough(CIRGenFunction &cgf, const CoroutineBodyStmt &s, Stmt *body, const CIRGenFunction::LexicalScope *currLexScope)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst)
cir::PointerType getPointerTo(mlir::Type ty)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
Address withPointer(mlir::Value newPtr) const
Return address with different pointer, but same element type and alignment.
mlir::Value getPointer() const
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
IsDestructed_t isExternallyDestructed() const
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
mlir::Type convertType(clang::QualType t)
mlir::LogicalResult emitCoreturnStmt(const CoreturnStmt &s)
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e)
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
cir::CoroNoopOp emitCoroNoopBuiltinCall(const CallExpr *e)
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
cir::CoroSuspendOp emitCoroSuspendBuiltinCall(const CallExpr *e)
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e)
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
static bool resumeExprDefersCleanups(const CoroutineSuspendExpr &s)
Whether the resume expression of s contains a construct that defers cleanups to the end of the enclos...
RValue emitCoyieldExpr(const CoyieldExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e)
LValue emitCoawaitLValue(const CoawaitExpr *e)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
AggValueSlot createAggTemp(QualType ty, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr)
Create a temporary memory object for the given aggregate type.
mlir::Type convertTypeForMem(QualType t)
RValue emitCoroutineFrame()
mlir::Value emitAlloca(llvm::StringRef name, mlir::Type ty, mlir::Location loc, clang::CharUnits alignment, bool insertIntoFnEntryBlock, mlir::Value arraySize=nullptr)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback, bool isFnTryBlock=false)
cir::CoroPromiseOp emitCoroPromiseBuiltinCall(const CallExpr *e)
Address returnValue
The temporary alloca to hold the return value.
cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e)
cir::CoroEndOp emitCoroEndBuiltinCall(const CallExpr *e)
void emitCXXTemporary(const CXXTemporary *temporary, QualType tempType, Address ptr)
Emits all the code to cause the given temporary to be cleaned up.
LValue emitCoyieldLValue(const CoyieldExpr *e)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
RValue emitCoawaitExpr(const CoawaitExpr &e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
RValue emitAnyExpr(const clang::Expr *e, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
Emit code to compute the specified expression which can have any type.
cir::CoroSizeOp emitCoroSizeBuiltinCall(const CallExpr *e)
cir::CleanupScopeOp currentFullExprCleanupScope
The cir.cleanup.scope of the innermost FullExprCleanupScope that materialized one,...
cir::CoroDoneOp emitCoroDoneBuiltinCall(const CallExpr *e)
cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e)
cir::CoroAlignOp emitCoroAlignBuiltinCall(const CallExpr *e)
LexicalScope * curLexScope
cir::CoroIdOp emitCoroIDBuiltinCall(const CallExpr *e)
clang::ASTContext & getContext() const
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
CIRGenBuilderTy & getBuilder()
void error(SourceLocation loc, llvm::StringRef error)
Emit a general error that something can't be done.
A saved depth on the scope stack.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
static RValue getComplex(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
mlir::Value getComplexValue() const
Return the value of this complex value.
static RValue getIgnored()
Represents binding an expression to a temporary.
CXXCatchStmt - This represents a C++ catch block.
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]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const
static CharUnits One()
Construct a CharUnits quantity of one.
Represents a 'co_await' expression.
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 * getFallthroughHandler() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...
Expr * getResumeExpr() const
OpaqueValueExpr * getOpaqueValue() const
getOpaqueValue - Return the opaque value placeholder.
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.
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
A (possibly-)qualified type.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
Exposes information about the current target.
unsigned getNewAlign() const
Return the largest alignment for which a suitably-sized allocation with 'operator new(size_t)' is gua...
unsigned getCharWidth() const
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
const Expr * getInit() const
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType)
U cast(CodeGen::Address addr)
static bool coroOutsideFrameMD()
static bool coroGetRetObjManager()
static bool generateDebugInfo()
cir::AwaitKind currentAwaitKind
CallExpr const * coroIdExpr
cir::CoroFreeOp lastCoroFree
std::unique_ptr< CGCoroData > data
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
mlir::Block * getEntryBlock()
clang::CharUnits getPointerAlign() const
cir::PointerType voidPtrTy
void* in address space 0