@@ -1259,9 +1259,7 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
1259
1259
expr instanceof NotExpr or
1260
1260
expr instanceof ComplementExpr or
1261
1261
expr instanceof UnaryPlusExpr or
1262
- expr instanceof UnaryMinusExpr or
1263
- expr instanceof CoAwaitExpr or
1264
- expr instanceof CoYieldExpr
1262
+ expr instanceof UnaryMinusExpr
1265
1263
}
1266
1264
1267
1265
final override Instruction getFirstInstruction ( EdgeKind kind ) {
@@ -1301,19 +1299,153 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
1301
1299
expr instanceof UnaryPlusExpr and result instanceof Opcode:: CopyValue
1302
1300
or
1303
1301
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
1310
1302
}
1311
1303
1312
1304
private TranslatedExpr getOperand ( ) {
1313
1305
result = getTranslatedExpr ( expr .( UnaryOperation ) .getOperand ( ) .getFullyConverted ( ) )
1314
1306
}
1315
1307
}
1316
1308
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
+
1317
1449
abstract class TranslatedConversion extends TranslatedNonConstantExpr {
1318
1450
override Conversion expr ;
1319
1451
0 commit comments