1515#include " clang/AST/StmtCXX.h"
1616#include " clang/Basic/TargetInfo.h"
1717#include " clang/CIR/Dialect/IR/CIRTypes.h"
18+ #include " clang/CIR/MissingFeatures.h"
1819
1920using namespace clang ;
2021using namespace clang ::CIRGen;
@@ -23,6 +24,9 @@ struct clang::CIRGen::CGCoroData {
2324 // Stores the __builtin_coro_id emitted in the function so that we can supply
2425 // it as the first argument to other builtins.
2526 cir::CallOp coroId = nullptr ;
27+
28+ // Stores the result of __builtin_coro_begin call.
29+ mlir::Value coroBegin = nullptr ;
2630};
2731
2832// Defining these here allows to keep CGCoroData private to this file.
@@ -63,6 +67,46 @@ cir::CallOp CIRGenFunction::emitCoroIDBuiltinCall(mlir::Location loc,
6367 nullPtr, nullPtr, nullPtr});
6468}
6569
70+ cir::CallOp CIRGenFunction::emitCoroAllocBuiltinCall (mlir::Location loc) {
71+ cir::BoolType boolTy = builder.getBoolTy ();
72+
73+ mlir::Operation *builtin = cgm.getGlobalValue (cgm.builtinCoroAlloc );
74+
75+ cir::FuncOp fnOp;
76+ if (!builtin) {
77+ fnOp = cgm.createCIRBuiltinFunction (loc, cgm.builtinCoroAlloc ,
78+ cir::FuncType::get ({UInt32Ty}, boolTy),
79+ /* fd=*/ nullptr );
80+ assert (fnOp && " should always succeed" );
81+ } else {
82+ fnOp = cast<cir::FuncOp>(builtin);
83+ }
84+
85+ return builder.createCallOp (
86+ loc, fnOp, mlir::ValueRange{curCoro.data ->coroId .getResult ()});
87+ }
88+
89+ cir::CallOp
90+ CIRGenFunction::emitCoroBeginBuiltinCall (mlir::Location loc,
91+ mlir::Value coroframeAddr) {
92+ mlir::Operation *builtin = cgm.getGlobalValue (cgm.builtinCoroBegin );
93+
94+ cir::FuncOp fnOp;
95+ if (!builtin) {
96+ fnOp = cgm.createCIRBuiltinFunction (
97+ loc, cgm.builtinCoroBegin ,
98+ cir::FuncType::get ({UInt32Ty, VoidPtrTy}, VoidPtrTy),
99+ /* fd=*/ nullptr );
100+ assert (fnOp && " should always succeed" );
101+ } else {
102+ fnOp = cast<cir::FuncOp>(builtin);
103+ }
104+
105+ return builder.createCallOp (
106+ loc, fnOp,
107+ mlir::ValueRange{curCoro.data ->coroId .getResult (), coroframeAddr});
108+ }
109+
66110mlir::LogicalResult
67111CIRGenFunction::emitCoroutineBody (const CoroutineBodyStmt &s) {
68112 mlir::Location openCurlyLoc = getLoc (s.getBeginLoc ());
@@ -73,10 +117,39 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt &s) {
73117 cir::CallOp coroId = emitCoroIDBuiltinCall (openCurlyLoc, nullPtrCst);
74118 createCoroData (*this , curCoro, coroId);
75119
76- assert (!cir::MissingFeatures::coroAllocBuiltinCall ());
77-
78- assert (!cir::MissingFeatures::coroBeginBuiltinCall ());
120+ // Backend is allowed to elide memory allocations, to help it, emit
121+ // auto mem = coro.alloc() ? 0 : ... allocation code ...;
122+ cir::CallOp coroAlloc = emitCoroAllocBuiltinCall (openCurlyLoc);
123+
124+ // Initialize address of coroutine frame to null
125+ CanQualType astVoidPtrTy = cgm.getASTContext ().VoidPtrTy ;
126+ mlir::Type allocaTy = convertTypeForMem (astVoidPtrTy);
127+ Address coroFrame =
128+ createTempAlloca (allocaTy, getContext ().getTypeAlignInChars (astVoidPtrTy),
129+ openCurlyLoc, " __coro_frame_addr" ,
130+ /* ArraySize=*/ nullptr );
131+
132+ mlir::Value storeAddr = coroFrame.getPointer ();
133+ builder.CIRBaseBuilderTy ::createStore (openCurlyLoc, nullPtrCst, storeAddr);
134+ cir::IfOp::create (
135+ builder, openCurlyLoc, coroAlloc.getResult (),
136+ /* withElseRegion=*/ false ,
137+ /* thenBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) {
138+ builder.CIRBaseBuilderTy ::createStore (
139+ loc, emitScalarExpr (s.getAllocate ()), storeAddr);
140+ cir::YieldOp::create (builder, loc);
141+ });
142+ curCoro.data ->coroBegin =
143+ emitCoroBeginBuiltinCall (
144+ openCurlyLoc,
145+ cir::LoadOp::create (builder, openCurlyLoc, allocaTy, storeAddr))
146+ .getResult ();
147+
148+ // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
149+ if (s.getReturnStmtOnAllocFailure ())
150+ cgm.errorNYI (" handle coroutine return alloc failure" );
79151
80152 assert (!cir::MissingFeatures::generateDebugInfo ());
153+ assert (!cir::MissingFeatures::emitBodyAndFallthrough ());
81154 return mlir::success ();
82155}
0 commit comments