/** * This method returns the input-value, casted to match the type. If the value matches the type, * it is returned unchanged. This method handles overflows and print warnings for the user. * Example: This method is called, when an value of type 'integer' is assigned to a variable of * type 'char'. * * @param value will be casted. If value is null, null is returned. * @param targetType value will be casted to targetType. * @param machineModel contains information about types */ public static Region[] castCValue( @Nullable final Region[] value, final CType targetType, final BitvectorManager bvmgr, final MachineModel machineModel) { if (value == null) { return null; } final CType type = targetType.getCanonicalType(); if (type instanceof CSimpleType) { final CSimpleType st = (CSimpleType) type; if (st.getType() == CBasicType.INT || st.getType() == CBasicType.CHAR) { final int bitPerByte = machineModel.getSizeofCharInBits(); final int numBytes = machineModel.getSizeof(st); final int size = bitPerByte * numBytes; final Region[] result = bvmgr.toBitsize(size, st.isSigned(), value); return result; } } // currently we do not handle floats, doubles or voids, pointers, so lets ignore this case. return value; }
/** * 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; }