@@ -1259,9 +1259,7 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
12591259 expr instanceof NotExpr or
12601260 expr instanceof ComplementExpr or
12611261 expr instanceof UnaryPlusExpr or
1262- expr instanceof UnaryMinusExpr or
1263- expr instanceof CoAwaitExpr or
1264- expr instanceof CoYieldExpr
1262+ expr instanceof UnaryMinusExpr
12651263 }
12661264
12671265 final override Instruction getFirstInstruction ( EdgeKind kind ) {
@@ -1301,19 +1299,153 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
13011299 expr instanceof UnaryPlusExpr and result instanceof Opcode:: CopyValue
13021300 or
13031301 expr instanceof UnaryMinusExpr and result instanceof Opcode:: Negate
1304- or
1305- // TODO: Use a new opcode to represent "awaiting the value"
1306- expr instanceof CoAwaitExpr and result instanceof Opcode:: CopyValue
1307- or
1308- // TODO: Use a new opcode to represent "awaiting the value"
1309- expr instanceof CoYieldExpr and result instanceof Opcode:: CopyValue
13101302 }
13111303
13121304 private TranslatedExpr getOperand ( ) {
13131305 result = getTranslatedExpr ( expr .( UnaryOperation ) .getOperand ( ) .getFullyConverted ( ) )
13141306 }
13151307}
13161308
1309+ /**
1310+ * IR translation of a `co_await` or `co_yield` expression.
1311+ *
1312+ * The translation of `x = co_await ...` is essentially:
1313+ * ```cpp
1314+ * if !awaiter.await_ready() {
1315+ * awaiter.await_suspend()
1316+ * }
1317+ * x = awaiter.await_resume();
1318+ * ```
1319+ * where `awaiter` is an object constructed from programmer-supplied
1320+ * input, and for IR construction purposes these are resolved by the C/C++
1321+ * front-end.
1322+ *
1323+ * See https://en.cppreference.com/w/cpp/language/coroutines#co_await for the
1324+ * specification on how `awaiter` is obtained.
1325+ */
1326+ abstract private class TranslatedCoExpr extends TranslatedNonConstantExpr {
1327+ /** Gets the operand of this operation. */
1328+ abstract Expr getOperand ( ) ;
1329+
1330+ /**
1331+ * Gets the expression that decides if the enclosing coroutine should be
1332+ * suspended.
1333+ */
1334+ abstract Expr getAwaitReady ( ) ;
1335+
1336+ /**
1337+ * Gets the expression that is evaluated when the enclosing coroutine is
1338+ * suspended.
1339+ */
1340+ abstract Expr getAwaitSuspend ( ) ;
1341+
1342+ /**
1343+ * Gets the expression that represents the resume point if the enclosing
1344+ * coroutine was suspended.
1345+ */
1346+ abstract Expr getAwaitResume ( ) ;
1347+
1348+ final override Instruction getFirstInstruction ( EdgeKind kind ) {
1349+ result = this .getTranslatedOperand ( ) .getFirstInstruction ( kind )
1350+ }
1351+
1352+ override Instruction getALastInstructionInternal ( ) {
1353+ result = this .getTranslatedAwaitResume ( ) .getALastInstruction ( )
1354+ }
1355+
1356+ final override TranslatedElement getChildInternal ( int id ) {
1357+ id = 0 and result = this .getTranslatedOperand ( )
1358+ or
1359+ id = 1 and result = this .getTranslatedAwaitReady ( )
1360+ or
1361+ id = 2 and result = this .getTranslatedAwaitResume ( )
1362+ or
1363+ id = 3 and result = this .getTranslatedAwaitSuspend ( )
1364+ }
1365+
1366+ final override Instruction getInstructionSuccessorInternal ( InstructionTag tag , EdgeKind kind ) {
1367+ tag = CoAwaitBranchTag ( ) and
1368+ (
1369+ kind instanceof TrueEdge and
1370+ result = this .getTranslatedAwaitResume ( ) .getFirstInstruction ( any ( GotoEdge goto ) )
1371+ or
1372+ kind instanceof FalseEdge and
1373+ result = this .getTranslatedAwaitSuspend ( ) .getFirstInstruction ( any ( GotoEdge goto ) )
1374+ )
1375+ }
1376+
1377+ override Instruction getResult ( ) { result = this .getTranslatedAwaitResume ( ) .getResult ( ) }
1378+
1379+ final override Instruction getChildSuccessorInternal ( TranslatedElement child , EdgeKind kind ) {
1380+ child = this .getTranslatedOperand ( ) and
1381+ result = this .getTranslatedAwaitReady ( ) .getFirstInstruction ( kind )
1382+ or
1383+ child = this .getTranslatedAwaitReady ( ) and
1384+ kind instanceof GotoEdge and
1385+ result = this .getInstruction ( CoAwaitBranchTag ( ) )
1386+ or
1387+ child = this .getTranslatedAwaitSuspend ( ) and
1388+ result = this .getTranslatedAwaitResume ( ) .getFirstInstruction ( kind )
1389+ or
1390+ child = this .getTranslatedAwaitResume ( ) and
1391+ result = this .getParent ( ) .getChildSuccessor ( this , kind )
1392+ }
1393+
1394+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
1395+ tag = CoAwaitBranchTag ( ) and
1396+ opcode instanceof Opcode:: ConditionalBranch and
1397+ resultType = getVoidType ( )
1398+ }
1399+
1400+ override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
1401+ tag = CoAwaitBranchTag ( ) and
1402+ operandTag instanceof ConditionOperandTag and
1403+ result = this .getTranslatedAwaitReady ( ) .getResult ( )
1404+ }
1405+
1406+ private TranslatedExpr getTranslatedOperand ( ) {
1407+ result = getTranslatedExpr ( this .getOperand ( ) .getFullyConverted ( ) )
1408+ }
1409+
1410+ private TranslatedExpr getTranslatedAwaitReady ( ) {
1411+ result = getTranslatedExpr ( this .getAwaitReady ( ) .getFullyConverted ( ) )
1412+ }
1413+
1414+ private TranslatedExpr getTranslatedAwaitResume ( ) {
1415+ result = getTranslatedExpr ( this .getAwaitResume ( ) .getFullyConverted ( ) )
1416+ }
1417+
1418+ private TranslatedExpr getTranslatedAwaitSuspend ( ) {
1419+ result = getTranslatedExpr ( this .getAwaitSuspend ( ) .getFullyConverted ( ) )
1420+ }
1421+ }
1422+
1423+ /** IR translation of `co_await`. */
1424+ class TranslatedCoAwaitExpr extends TranslatedCoExpr {
1425+ override CoAwaitExpr expr ;
1426+
1427+ final override Expr getOperand ( ) { result = expr .getOperand ( ) }
1428+
1429+ final override Expr getAwaitReady ( ) { result = expr .getAwaitReady ( ) }
1430+
1431+ final override Expr getAwaitSuspend ( ) { result = expr .getAwaitSuspend ( ) }
1432+
1433+ final override Expr getAwaitResume ( ) { result = expr .getAwaitResume ( ) }
1434+ }
1435+
1436+ /** IR translation of `co_yield`. */
1437+ class TranslatedCoYieldxpr extends TranslatedCoExpr {
1438+ override CoYieldExpr expr ;
1439+
1440+ final override Expr getOperand ( ) { result = expr .getOperand ( ) }
1441+
1442+ final override Expr getAwaitReady ( ) { result = expr .getAwaitReady ( ) }
1443+
1444+ final override Expr getAwaitSuspend ( ) { result = expr .getAwaitSuspend ( ) }
1445+
1446+ final override Expr getAwaitResume ( ) { result = expr .getAwaitResume ( ) }
1447+ }
1448+
13171449abstract class TranslatedConversion extends TranslatedNonConstantExpr {
13181450 override Conversion expr ;
13191451
0 commit comments