@Override public Region[] visit(final CUnaryExpression unaryExpression) { final UnaryOperator unaryOperator = unaryExpression.getOperator(); final CExpression unaryOperand = unaryExpression.getOperand(); if (unaryOperator == UnaryOperator.SIZEOF) { return getSizeof(unaryOperand.getExpressionType()); } final Region[] value = unaryOperand.accept(this); if (value == null) { return null; } switch (unaryOperator) { case MINUS: // -X == (0-X) return bvmgr.makeSub(bvmgr.makeNumber(BigInteger.ZERO, value.length), value); case SIZEOF: throw new AssertionError("SIZEOF should be handled before!"); case AMPER: // valid expression, but it's a pointer value // TODO Not precise enough return getSizeof(unaryOperand.getExpressionType()); case TILDE: default: // TODO handle unimplemented operators return null; } }
protected static Region booleanOperation( final Region[] l, final Region[] r, final BitvectorManager bvmgr, final BinaryOperator op, final CType calculationType, final MachineModel machineModel) { boolean signed = true; if (calculationType instanceof CSimpleType) { signed = !((CSimpleType) calculationType).isUnsigned(); } switch (op) { case EQUALS: return bvmgr.makeLogicalEqual(l, r); case NOT_EQUALS: return bvmgr.makeNot(bvmgr.makeLogicalEqual(l, r)); case GREATER_THAN: // A>B <--> B<A return bvmgr.makeLess(r, l, signed); case GREATER_EQUAL: // A>=B <--> B<=A return bvmgr.makeLessOrEqual(r, l, signed); case LESS_THAN: return bvmgr.makeLess(l, r, signed); case LESS_EQUAL: return bvmgr.makeLessOrEqual(l, r, signed); default: throw new AssertionError("unknown binary operation: " + op); } }
private static Region[] arithmeticOperation( final Region[] l, final Region[] r, final BitvectorManager bvmgr, final BinaryOperator op, final CType calculationType, final MachineModel machineModel) { switch (op) { case PLUS: return bvmgr.makeAdd(l, r); case MINUS: return bvmgr.makeSub(l, r); case DIVIDE: case MODULO: case MULTIPLY: // TODO implement multiplier circuit for Regions/BDDs? // this would be working for constant numbers (2*3), however timeout for variables (a*b -> // exponential bdd-size). return null; case SHIFT_LEFT: case SHIFT_RIGHT: // TODO implement shift circuit? this should be easier than multiplier, // because 'r' is smaller (max 64 for longlong), so many positions can be ignored return null; case BINARY_AND: return bvmgr.makeBinaryAnd(l, r); case BINARY_OR: return bvmgr.makeBinaryOr(l, r); case BINARY_XOR: return bvmgr.makeXor(l, r); default: throw new AssertionError("unknown binary operation: " + op); } }
@Override public Region[] visit(CIdExpression idExp) { if (idExp.getDeclaration() instanceof CEnumerator) { CEnumerator enumerator = (CEnumerator) idExp.getDeclaration(); if (enumerator.hasValue()) { return bvmgr.makeNumber(enumerator.getValue(), getSize(idExp.getExpressionType())); } else { return null; } } return predMgr.createPredicate( idExp.getDeclaration().getQualifiedName(), idExp.getExpressionType(), location, getSize(idExp.getExpressionType()), precision); }
/** * 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; }
private Region[] getSizeof(CType pType) { return bvmgr.makeNumber(machineModel.getSizeof(pType), machineModel.getSizeofInt()); }
@Override public Region[] visit(CIntegerLiteralExpression pE) { return bvmgr.makeNumber(pE.asLong(), getSize(pE.getExpressionType())); }
@Override public Region[] visit(CCharLiteralExpression pE) { return bvmgr.makeNumber(pE.getCharacter(), getSize(pE.getExpressionType())); }
/** * 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; }