@@ -1320,51 +1320,98 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
1320
1320
}
1321
1321
}
1322
1322
1323
+ /**
1324
+ * The IR translation of a `NotExpr`.
1325
+ *
1326
+ * In C++ an operation such as `!x` where `x` is an `int` will generate
1327
+ * ```
1328
+ * r1(glval<int>) = VariableAddress[x] :
1329
+ * r2(int) = Load : &r1
1330
+ * r3(int) = Constant[0] :
1331
+ * r4(bool) = CompareNE : r2, r3
1332
+ * r5(bool) = LogicalNot : r4
1333
+ * ```
1334
+ * since C does not do implicit int-to-bool casts we need to generate the
1335
+ * `Constant[0]`, `CompareNE`, and `LogicalNot` instructions manually, but
1336
+ * we simplify this and generate `Constant[0]`, `CompareEQ` instead.
1337
+ */
1323
1338
class TranslatedNotExpr extends TranslatedNonConstantExpr {
1324
1339
override NotExpr expr ;
1325
1340
1326
1341
override Type getExprType ( ) { result instanceof BoolType }
1327
1342
1343
+ private Type getOperandType ( ) { result = this .getOperand ( ) .getExprType ( ) .getUnspecifiedType ( ) }
1344
+
1345
+ predicate shouldGenerateEq ( ) { not this .getOperandType ( ) instanceof BoolType }
1346
+
1328
1347
final override Instruction getFirstInstruction ( EdgeKind kind ) {
1329
1348
result = this .getOperand ( ) .getFirstInstruction ( kind )
1330
1349
}
1331
1350
1332
1351
override Instruction getALastInstructionInternal ( ) {
1333
- result = this .getInstruction ( OnlyInstructionTag ( ) )
1352
+ result = this .getInstruction ( NotExprOperationTag ( ) )
1334
1353
}
1335
1354
1336
1355
final override TranslatedElement getChildInternal ( int id ) {
1337
1356
id = 0 and result = this .getOperand ( )
1338
1357
}
1339
1358
1340
1359
override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
1341
- tag = OnlyInstructionTag ( ) and
1342
- opcode instanceof Opcode:: LogicalNot and
1343
- resultType = getBoolType ( )
1360
+ this .shouldGenerateEq ( ) and
1361
+ tag = NotExprConstantTag ( ) and
1362
+ opcode instanceof Opcode:: Constant and
1363
+ resultType = getTypeForPRValue ( this .getOperandType ( ) )
1364
+ or
1365
+ resultType = getBoolType ( ) and
1366
+ tag = NotExprOperationTag ( ) and
1367
+ if this .shouldGenerateEq ( )
1368
+ then opcode instanceof Opcode:: CompareEQ
1369
+ else opcode instanceof Opcode:: LogicalNot
1344
1370
}
1345
1371
1346
1372
final override Instruction getInstructionSuccessorInternal ( InstructionTag tag , EdgeKind kind ) {
1347
- tag = OnlyInstructionTag ( ) and
1373
+ tag = NotExprOperationTag ( ) and
1348
1374
result = this .getParent ( ) .getChildSuccessor ( this , kind )
1375
+ or
1376
+ tag = NotExprConstantTag ( ) and
1377
+ kind instanceof GotoEdge and
1378
+ result = this .getInstruction ( NotExprOperationTag ( ) )
1349
1379
}
1350
1380
1351
1381
final override Instruction getChildSuccessorInternal ( TranslatedElement child , EdgeKind kind ) {
1352
1382
child = this .getOperand ( ) and
1353
1383
kind instanceof GotoEdge and
1354
- result = this .getInstruction ( OnlyInstructionTag ( ) )
1384
+ if this .shouldGenerateEq ( )
1385
+ then result = this .getInstruction ( NotExprConstantTag ( ) )
1386
+ else result = this .getInstruction ( NotExprOperationTag ( ) )
1355
1387
}
1356
1388
1357
1389
final override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
1358
- tag = OnlyInstructionTag ( ) and
1359
- operandTag instanceof UnaryOperandTag and
1360
- result = this .getOperand ( ) .getResult ( )
1390
+ tag = NotExprOperationTag ( ) and
1391
+ if this .shouldGenerateEq ( )
1392
+ then (
1393
+ result = this .getOperand ( ) .getResult ( ) and
1394
+ operandTag instanceof LeftOperandTag
1395
+ or
1396
+ result = this .getInstruction ( NotExprConstantTag ( ) ) and
1397
+ operandTag instanceof RightOperandTag
1398
+ ) else (
1399
+ operandTag instanceof UnaryOperandTag and
1400
+ result = this .getOperand ( ) .getResult ( )
1401
+ )
1361
1402
}
1362
1403
1363
1404
private TranslatedExpr getOperand ( ) {
1364
1405
result = getTranslatedExpr ( expr .getOperand ( ) .getFullyConverted ( ) )
1365
1406
}
1366
1407
1367
- final override Instruction getResult ( ) { result = this .getInstruction ( OnlyInstructionTag ( ) ) }
1408
+ final override Instruction getResult ( ) { result = this .getInstruction ( NotExprOperationTag ( ) ) }
1409
+
1410
+ override string getInstructionConstantValue ( InstructionTag tag ) {
1411
+ this .shouldGenerateEq ( ) and
1412
+ tag = NotExprConstantTag ( ) and
1413
+ result = "0"
1414
+ }
1368
1415
}
1369
1416
1370
1417
/**
0 commit comments