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

1

2

3

4

5

6

7

8

9

10

11

12

14#include "mlir/Support/LLVM.h"

20

21using namespace clang;

23

25

26

27

29

30

32

33

35

36

38};

39

40

43

44namespace {

45

46

47

48

49struct GetParamRef : public StmtVisitor {

50public:

52 GetParamRef() {}

54 assert(expr == nullptr && "multilple declref in param move");

56 }

57 void VisitStmt(Stmt *s) {

58 for (Stmt *c : s->children()) {

59 if (c)

60 Visit(c);

61 }

62 }

63};

64

65

66

67

68struct ParamReferenceReplacerRAII {

71

73 : localDeclMap(localDeclMap) {}

74

75 void addCopy(const DeclStmt *pm) {

76

77

79 const VarDecl *vd = static_cast<const VarDecl *>(pm->getSingleDecl());

80 const Expr *initExpr = vd->getInit();

81 GetParamRef visitor;

82 visitor.Visit(const_cast<Expr *>(initExpr));

83 assert(visitor.expr);

84 DeclRefExpr *dreOrig = visitor.expr;

85 auto *pd = dreOrig->getDecl();

86

87 auto it = localDeclMap.find(pd);

88 assert(it != localDeclMap.end() && "parameter is not found");

89 savedLocals.insert({pd, it->second});

90

91 auto copyIt = localDeclMap.find(vd);

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

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

94 }

95

96 ~ParamReferenceReplacerRAII() {

97 for (auto &&savedLocal : savedLocals) {

98 localDeclMap.insert({savedLocal.first, savedLocal.second});

99 }

100 }

101};

102}

103

107 }

108 cgm.errorNYI("NYI");

110}

111

114 cir::CallOp coroId) {

115 assert(curCoro.data && "EmitCoroutineBodyStatement called twice?");

116

117 curCoro.data = std::make_unique();

119}

120

122 mlir::Value nullPtr) {

123 cir::IntType int32Ty = builder.getUInt32Ty();

124

125 const TargetInfo &ti = cgm.getASTContext().getTargetInfo();

127

128 mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroId);

129

130 cir::FuncOp fnOp;

131 if (!builtin) {

132 fnOp = cgm.createCIRBuiltinFunction(

133 loc, cgm.builtinCoroId,

134 cir::FuncType::get({int32Ty, voidPtrTy, voidPtrTy, voidPtrTy}, int32Ty),

135 nullptr);

136 assert(fnOp && "should always succeed");

137 } else {

139 }

140

141 return builder.createCallOp(loc, fnOp,

142 mlir::ValueRange{builder.getUInt32(newAlign, loc),

143 nullPtr, nullPtr, nullPtr});

144}

145

147 cir::BoolType boolTy = builder.getBoolTy();

148

149 mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroAlloc);

150

151 cir::FuncOp fnOp;

152 if (!builtin) {

153 fnOp = cgm.createCIRBuiltinFunction(loc, cgm.builtinCoroAlloc,

154 cir::FuncType::get({uInt32Ty}, boolTy),

155 nullptr);

156 assert(fnOp && "should always succeed");

157 } else {

159 }

160

161 return builder.createCallOp(

162 loc, fnOp, mlir::ValueRange{curCoro.data->coroId.getResult()});

163}

164

165cir::CallOp

167 mlir::Value coroframeAddr) {

168 mlir::Operation *builtin = cgm.getGlobalValue(cgm.builtinCoroBegin);

169

170 cir::FuncOp fnOp;

171 if (!builtin) {

172 fnOp = cgm.createCIRBuiltinFunction(

173 loc, cgm.builtinCoroBegin,

174 cir::FuncType::get({uInt32Ty, voidPtrTy}, voidPtrTy),

175 nullptr);

176 assert(fnOp && "should always succeed");

177 } else {

179 }

180

181 return builder.createCallOp(

182 loc, fnOp,

183 mlir::ValueRange{curCoro.data->coroId.getResult(), coroframeAddr});

184}

185

186mlir::LogicalResult

188 mlir::Location openCurlyLoc = getLoc(s.getBeginLoc());

189 cir::ConstantOp nullPtrCst = builder.getNullPtr(voidPtrTy, openCurlyLoc);

190

191 auto fn = mlir::castcir::FuncOp(curFn);

192 fn.setCoroutine(true);

195

196

197

199

200

201 CanQualType astVoidPtrTy = cgm.getASTContext().VoidPtrTy;

205 openCurlyLoc, "__coro_frame_addr",

206 nullptr);

207

208 mlir::Value storeAddr = coroFrame.getPointer();

209 builder.CIRBaseBuilderTy::createStore(openCurlyLoc, nullPtrCst, storeAddr);

210 cir::IfOp::create(

211 builder, openCurlyLoc, coroAlloc.getResult(),

212 false,

213 [&](mlir::OpBuilder &b, mlir::Location loc) {

214 builder.CIRBaseBuilderTy::createStore(

215 loc, emitScalarExpr(s.getAllocate()), storeAddr);

216 cir::YieldOp::create(builder, loc);

217 });

218 curCoro.data->coroBegin =

220 openCurlyLoc,

221 cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr))

222 .getResult();

223

224

225 if (s.getReturnStmtOnAllocFailure())

226 cgm.errorNYI("handle coroutine return alloc failure");

227

228 {

230 ParamReferenceReplacerRAII paramReplacer(localDeclMap);

231

232

234 assert((paramMoves.size() == 0 || (paramMoves.size() == fnArgs.size())) &&

235 "ParamMoves and FnArgs should be the same size for coroutine "

236 "function");

237

239

240

241

242

244 for (auto *pm : paramMoves) {

245 if (emitStmt(pm, true).failed())

246 return mlir::failure();

248 }

249

250 if (emitStmt(s.getPromiseDeclStmt(), true).failed())

251 return mlir::failure();

252

253

254 assert(returnValue.isValid() == (bool)s.getReturnStmt());

255

256

257

258

259

260

261

262

263

266 s.getReturnValue()->getType().getQualifiers(),

267 true);

268

270

271 curCoro.data->currentAwaitKind = cir::AwaitKind::Init;

272 if (emitStmt(s.getInitSuspendStmt(), true).failed())

273 return mlir::failure();

275 }

276 return mlir::success();

277}

278

280 if (const auto *ce = dyn_cast(e))

281 if (const auto *proto =

285 return false;

286 return true;

287}

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305namespace {

306struct LValueOrRValue {

307 LValue lv;

308 RValue rv;

309};

310}

311

312static LValueOrRValue

316 mlir::Block *scopeParentBlock,

317 mlir::Value &tmpResumeRValAddr, bool forLValue) {

318 [[maybe_unused]] mlir::LogicalResult awaitBuild = mlir::success();

319 LValueOrRValue awaitRes;

320

324 [[maybe_unused]] cir::AwaitOp awaitOp = cir::AwaitOp::create(

325 builder, cgf.getLoc(s.getSourceRange()), kind,

326

327 [&](mlir::OpBuilder &b, mlir::Location loc) {

328 Expr *condExpr = s.getReadyExpr()->IgnoreParens();

329 builder.createCondition(cgf.evaluateExprAsBool(condExpr));

330 },

331

332 [&](mlir::OpBuilder &b, mlir::Location loc) {

333

334

335

336

337

338 mlir::Value suspendRet = cgf.emitScalarExpr(s.getSuspendExpr());

339

340

341 if (suspendRet) {

342 cgf.cgm.errorNYI("Veto await_suspend");

343 }

344

345

346 cir::YieldOp::create(builder, loc);

347 },

348

349 [&](mlir::OpBuilder &b, mlir::Location loc) {

350

351

352

353 CXXTryStmt *tryStmt = nullptr;

354 if (coro.exceptionHandler && kind == cir::AwaitKind::Init &&

356 cgf.cgm.errorNYI("Coro resume Exception");

357

358

359

360 if (forLValue) {

362 } else {

363 awaitRes.rv =

364 cgf.emitAnyExpr(s.getResumeExpr(), aggSlot, ignoreResult);

365 if (!awaitRes.rv.isIgnored())

366

367

369 }

370

371 if (tryStmt)

372 cgf.cgm.errorNYI("Coro tryStmt");

373

374

375 cir::YieldOp::create(builder, loc);

376 });

377

378 assert(awaitBuild.succeeded() && "Should know how to codegen");

379 return awaitRes;

380}

381

385 bool ignoreResult) {

388

389

390

391

392

393

394

396 [[maybe_unused]] mlir::Value tmpResumeRValAddr;

397

398

399

401 ignoreResult, currEntryBlock, tmpResumeRValAddr,

402 false)

403 .rv;

404

405 if (ignoreResult || rval.isIgnored())

406 return rval;

407

411 tmpResumeRValAddr));

413

414

415 cgf.cgm.errorNYI("emitSuspendExpr Aggregate");

416 } else {

417 cgf.cgm.errorNYI("emitSuspendExpr Complex");

418 }

419 return rval;

420}

421

424 bool ignoreResult) {

426 ignoreResult);

427}

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)

Definition CIRGenCoroutine.cpp:313

static RValue emitSuspendExpr(CIRGenFunction &cgf, const CoroutineSuspendExpr &e, cir::AwaitKind kind, AggValueSlot aggSlot, bool ignoreResult)

Definition CIRGenCoroutine.cpp:382

static bool memberCallExpressionCanThrow(const Expr *e)

Definition CIRGenCoroutine.cpp:279

static void createCoroData(CIRGenFunction &cgf, CIRGenFunction::CGCoroInfo &curCoro, cir::CallOp coroId)

Definition CIRGenCoroutine.cpp:112

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

Definition CIRGenCoroutine.cpp:121

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)

Definition CIRGenCoroutine.cpp:146

RValue emitCoroutineFrame()

Definition CIRGenCoroutine.cpp:104

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)

Definition CIRGenCoroutine.cpp:422

LexicalScope * curLexScope

clang::ASTContext & getContext() const

mlir::LogicalResult emitCoroutineBody(const CoroutineBodyStmt &s)

Definition CIRGenCoroutine.cpp:187

cir::CallOp emitCoroBeginBuiltinCall(mlir::Location loc, mlir::Value coroframeAddr)

Definition CIRGenCoroutine.cpp:166

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

This represents one expression.

Represents a prototype with parameter type info, e.g.

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.

bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType)

U cast(CodeGen::Address addr)

static bool ehCleanupScope()

static bool coroCoReturn()

static bool emitBodyAndFallthrough()

static bool coroOutsideFrameMD()

static bool coroCoYield()

static bool generateDebugInfo()

Definition CIRGenCoroutine.cpp:24

cir::AwaitKind currentAwaitKind

Definition CIRGenCoroutine.cpp:28

cir::CallOp coroId

Definition CIRGenCoroutine.cpp:31

mlir::Value coroBegin

Definition CIRGenCoroutine.cpp:34

Stmt * exceptionHandler

Definition CIRGenCoroutine.cpp:37

CGCoroInfo()

Definition CIRGenCoroutine.cpp:41

std::unique_ptr< CGCoroData > data

~CGCoroInfo()

Definition CIRGenCoroutine.cpp:42

mlir::Block * getEntryBlock()

cir::PointerType voidPtrTy

void* in address space 0