14#include "mlir/Support/LLVM.h"
46struct GetParamRef :
public StmtVisitor<GetParamRef> {
51 assert(
expr ==
nullptr &&
"multilple declref in param move");
54 void VisitStmt(
Stmt *
s) {
55 for (
Stmt *
c :
s->children()) {
65struct ParamReferenceReplacerRAII {
70 : localDeclMap(localDeclMap) {}
72 void addCopy(
const DeclStmt *pm) {
76 const VarDecl *vd =
static_cast<const VarDecl *
>(pm->
getSingleDecl());
77 const Expr *initExpr = vd->
getInit();
79 visitor.Visit(
const_cast<Expr *
>(initExpr));
81 DeclRefExpr *dreOrig = visitor.expr;
84 auto it = localDeclMap.find(pd);
85 assert(it != localDeclMap.end() &&
"parameter is not found");
86 savedLocals.insert({pd, it->second});
88 auto copyIt = localDeclMap.find(vd);
89 assert(copyIt != localDeclMap.end() &&
"parameter copy is not found");
90 it->second = copyIt->getSecond();
93 ~ParamReferenceReplacerRAII() {
94 for (
auto &&savedLocal : savedLocals) {
95 localDeclMap.insert({savedLocal.first, savedLocal.second});
102 cir::CallOp coroId) {
103 assert(!
curCoro.
data &&
"EmitCoroutineBodyStatement called twice?");
110 mlir::Value nullPtr) {
111 cir::IntType int32Ty = builder.getUInt32Ty();
116 mlir::Operation *builtin =
cgm.getGlobalValue(
cgm.builtinCoroId);
120 fnOp =
cgm.createCIRBuiltinFunction(
121 loc,
cgm.builtinCoroId,
122 cir::FuncType::get({int32Ty, voidPtrTy, voidPtrTy, voidPtrTy}, int32Ty),
124 assert(fnOp &&
"should always succeed");
129 return builder.createCallOp(loc, fnOp,
130 mlir::ValueRange{builder.getUInt32(newAlign, loc),
131 nullPtr, nullPtr, nullPtr});
135 cir::BoolType boolTy = builder.getBoolTy();
137 mlir::Operation *builtin =
cgm.getGlobalValue(
cgm.builtinCoroAlloc);
141 fnOp =
cgm.createCIRBuiltinFunction(loc,
cgm.builtinCoroAlloc,
142 cir::FuncType::get({uInt32Ty}, boolTy),
144 assert(fnOp &&
"should always succeed");
149 return builder.createCallOp(
150 loc, fnOp, mlir::ValueRange{
curCoro.data->coroId.getResult()});
155 mlir::Value coroframeAddr) {
156 mlir::Operation *builtin =
cgm.getGlobalValue(
cgm.builtinCoroBegin);
160 fnOp =
cgm.createCIRBuiltinFunction(
161 loc,
cgm.builtinCoroBegin,
162 cir::FuncType::get({uInt32Ty, voidPtrTy},
voidPtrTy),
164 assert(fnOp &&
"should always succeed");
169 return builder.createCallOp(
171 mlir::ValueRange{
curCoro.data->coroId.getResult(), coroframeAddr});
176 mlir::Location openCurlyLoc =
getLoc(
s.getBeginLoc());
177 cir::ConstantOp nullPtrCst = builder.getNullPtr(
voidPtrTy, openCurlyLoc);
179 auto fn = mlir::cast<cir::FuncOp>(
curFn);
180 fn.setCoroutine(
true);
193 openCurlyLoc,
"__coro_frame_addr",
196 mlir::Value storeAddr = coroFrame.
getPointer();
197 builder.CIRBaseBuilderTy::createStore(openCurlyLoc, nullPtrCst, storeAddr);
199 builder, openCurlyLoc, coroAlloc.getResult(),
201 [&](mlir::OpBuilder &
b, mlir::Location loc) {
202 builder.CIRBaseBuilderTy::createStore(
203 loc, emitScalarExpr(s.getAllocate()), storeAddr);
204 cir::YieldOp::create(builder, loc);
209 cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr))
213 if (
s.getReturnStmtOnAllocFailure())
214 cgm.errorNYI(
"handle coroutine return alloc failure");
222 assert((paramMoves.size() == 0 || (paramMoves.size() ==
fnArgs.size())) &&
223 "ParamMoves and FnArgs should be the same size for coroutine "
232 for (
auto *pm : paramMoves) {
234 return mlir::failure();
238 if (
emitStmt(
s.getPromiseDeclStmt(),
true).failed())
239 return mlir::failure();
242 assert(
returnValue.isValid() == (
bool)
s.getReturnStmt());
254 s.getReturnValue()->getType().getQualifiers(),
259 curCoro.data->currentAwaitKind = cir::AwaitKind::Init;
260 if (
emitStmt(
s.getInitSuspendStmt(),
true).failed())
261 return mlir::failure();
264 return mlir::success();
283struct LValueOrRValue {
293 mlir::Block *scopeParentBlock,
294 mlir::Value &tmpResumeRValAddr,
bool forLValue) {
295 [[maybe_unused]] mlir::LogicalResult awaitBuild = mlir::success();
296 LValueOrRValue awaitRes;
301 [[maybe_unused]] cir::AwaitOp awaitOp = cir::AwaitOp::create(
302 builder, cgf.
getLoc(
s.getSourceRange()), kind,
304 [&](mlir::OpBuilder &
b, mlir::Location loc) {
305 builder.createCondition(
306 cgf.createDummyValue(loc, cgf.getContext().BoolTy));
309 [&](mlir::OpBuilder &
b, mlir::Location loc) {
310 cir::YieldOp::create(builder, loc);
313 [&](mlir::OpBuilder &
b, mlir::Location loc) {
314 cir::YieldOp::create(builder, loc);
317 assert(awaitBuild.succeeded() &&
"Should know how to codegen");
335 [[maybe_unused]] mlir::Value tmpResumeRValAddr;
340 ignoreResult, currEntryBlock, tmpResumeRValAddr,
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 RValue emitSuspendExpr(CIRGenFunction &cgf, const CoroutineSuspendExpr &e, cir::AwaitKind kind, AggValueSlot aggSlot, bool ignoreResult)
static void createCoroData(CIRGenFunction &cgf, CIRGenFunction::CGCoroInfo &curCoro, cir::CallOp coroId)
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
mlir::Value getPointer() const
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
cir::CallOp emitCoroIDBuiltinCall(mlir::Location loc, mlir::Value nullPtr)
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,...
llvm::DenseMap< const clang::Decl *, Address > DeclMapTy
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
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.
mlir::Operation * curFn
The current function or global initializer that is generated code for.
llvm::SmallVector< const ParmVarDecl * > fnArgs
Save Parameter Decl for coroutine.
mlir::Type convertTypeForMem(QualType t)
cir::CallOp emitCoroAllocBuiltinCall(mlir::Location loc)
Address returnValue
The temporary alloca to hold the return value.
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)
LexicalScope * curLexScope
clang::ASTContext & getContext() const
mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)
cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc, mlir::Value coroframeAddr)
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
Represents a 'co_await' expression.
Represents the body of a coroutine.
Represents an expression that might suspend coroutine execution; either a co_await or co_yield expres...
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
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...
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
const Expr * getInit() const
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
U cast(CodeGen::Address addr)
static bool ehCleanupScope()
static bool emitBodyAndFallthrough()
static bool coroOutsideFrameMD()
static bool generateDebugInfo()
cir::AwaitKind currentAwaitKind
std::unique_ptr< CGCoroData > data
mlir::Block * getEntryBlock()
cir::PointerType voidPtrTy
void* in address space 0