@@ -1320,51 +1320,98 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr {
13201320 }
13211321}
13221322
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+ */
13231338class TranslatedNotExpr extends TranslatedNonConstantExpr {
13241339 override NotExpr expr ;
13251340
13261341 override Type getExprType ( ) { result instanceof BoolType }
13271342
1343+ private Type getOperandType ( ) { result = this .getOperand ( ) .getExprType ( ) .getUnspecifiedType ( ) }
1344+
1345+ predicate shouldGenerateEq ( ) { not this .getOperandType ( ) instanceof BoolType }
1346+
13281347 final override Instruction getFirstInstruction ( EdgeKind kind ) {
13291348 result = this .getOperand ( ) .getFirstInstruction ( kind )
13301349 }
13311350
13321351 override Instruction getALastInstructionInternal ( ) {
1333- result = this .getInstruction ( OnlyInstructionTag ( ) )
1352+ result = this .getInstruction ( NotExprOperationTag ( ) )
13341353 }
13351354
13361355 final override TranslatedElement getChildInternal ( int id ) {
13371356 id = 0 and result = this .getOperand ( )
13381357 }
13391358
13401359 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
13441370 }
13451371
13461372 final override Instruction getInstructionSuccessorInternal ( InstructionTag tag , EdgeKind kind ) {
1347- tag = OnlyInstructionTag ( ) and
1373+ tag = NotExprOperationTag ( ) and
13481374 result = this .getParent ( ) .getChildSuccessor ( this , kind )
1375+ or
1376+ tag = NotExprConstantTag ( ) and
1377+ kind instanceof GotoEdge and
1378+ result = this .getInstruction ( NotExprOperationTag ( ) )
13491379 }
13501380
13511381 final override Instruction getChildSuccessorInternal ( TranslatedElement child , EdgeKind kind ) {
13521382 child = this .getOperand ( ) and
13531383 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 ( ) )
13551387 }
13561388
13571389 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+ )
13611402 }
13621403
13631404 private TranslatedExpr getOperand ( ) {
13641405 result = getTranslatedExpr ( expr .getOperand ( ) .getFullyConverted ( ) )
13651406 }
13661407
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+ }
13681415}
13691416
13701417/**
0 commit comments