@Override public Region[] visit(final CBinaryExpression pE) { final Region[] lVal = pE.getOperand1().accept(this); final Region[] rVal = pE.getOperand2().accept(this); if (lVal == null || rVal == null) { return null; } return calculateBinaryOperation(lVal, rVal, bvmgr, pE, machineModel); }
/** * This method calculates the exact result for a binary operation. * * @param lVal first operand * @param rVal second operand * @param machineModel information about types */ public static Region[] calculateBinaryOperation( Region[] lVal, Region[] rVal, final BitvectorManager bvmgr, final CBinaryExpression binaryExpr, final MachineModel machineModel) { final BinaryOperator binaryOperator = binaryExpr.getOperator(); final CType calculationType = binaryExpr.getCalculationType(); lVal = castCValue(lVal, calculationType, bvmgr, machineModel); if (binaryOperator != BinaryOperator.SHIFT_LEFT && binaryOperator != BinaryOperator.SHIFT_RIGHT) { /* For SHIFT-operations we do not cast the second operator. * We even do not need integer-promotion, * because the maximum SHIFT of 64 is lower than MAX_CHAR. * * ISO-C99 (6.5.7 #3): Bitwise shift operators * The integer promotions are performed on each of the operands. * The type of the result is that of the promoted left operand. * If the value of the right operand is negative or is greater than * or equal to the width of the promoted left operand, * the behavior is undefined. */ rVal = castCValue(rVal, calculationType, bvmgr, machineModel); } Region[] result; switch (binaryOperator) { case PLUS: case MINUS: case DIVIDE: case MODULO: case MULTIPLY: case SHIFT_LEFT: case SHIFT_RIGHT: case BINARY_AND: case BINARY_OR: case BINARY_XOR: { result = arithmeticOperation(lVal, rVal, bvmgr, binaryOperator, calculationType, machineModel); result = castCValue(result, binaryExpr.getExpressionType(), bvmgr, machineModel); break; } case EQUALS: case NOT_EQUALS: case GREATER_THAN: case GREATER_EQUAL: case LESS_THAN: case LESS_EQUAL: { final Region tmp = booleanOperation(lVal, rVal, bvmgr, binaryOperator, calculationType, machineModel); // return 1 if expression holds, 0 otherwise int size = 32; if (calculationType instanceof CSimpleType) { final CSimpleType st = (CSimpleType) calculationType; if (st.getType() == CBasicType.INT || st.getType() == CBasicType.CHAR) { final int bitPerByte = machineModel.getSizeofCharInBits(); final int numBytes = machineModel.getSizeof(st); size = bitPerByte * numBytes; } } result = bvmgr.wrapLast(tmp, size); // we do not cast here, because 0 and 1 should be small enough for every type. break; } default: throw new AssertionError("unhandled binary operator"); } return result; }