@Override public Expression constructBinaryEqualityExpressionInteger( final ILocation loc, final int nodeOperator, final Expression exp1, final CType type1, final Expression exp2, final CType type2) { Expression leftExpr = exp1; Expression rightExpr = exp2; if ((type1 instanceof CPrimitive) && (type2 instanceof CPrimitive)) { final CPrimitive primitive1 = (CPrimitive) type1; final CPrimitive primitive2 = (CPrimitive) type2; if (mUnsignedTreatment == UnsignedTreatment.WRAPAROUND && mTypeSizes.isUnsigned(primitive1)) { assert mTypeSizes.isUnsigned(primitive2); leftExpr = applyWraparound(loc, mTypeSizes, primitive1, leftExpr); rightExpr = applyWraparound(loc, mTypeSizes, primitive2, rightExpr); } } if (nodeOperator == IASTBinaryExpression.op_equals) { return ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPEQ, leftExpr, rightExpr); } else if (nodeOperator == IASTBinaryExpression.op_notequals) { return ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPNEQ, leftExpr, rightExpr); } else { throw new IllegalArgumentException("operator is neither equals nor not equals"); } }
private Expression getLeftSmallerZeroAndThereIsRemainder( final ILocation loc, final Expression exp1, final Expression exp2) { final Expression leftModRight = ExpressionFactory.newBinaryExpression(loc, Operator.ARITHMOD, exp1, exp2); final Expression thereIsRemainder = ExpressionFactory.newBinaryExpression( loc, Operator.COMPNEQ, leftModRight, new IntegerLiteral(loc, SFO.NR0)); final Expression leftSmallerZero = ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPLT, exp1, new IntegerLiteral(loc, SFO.NR0)); return ExpressionFactory.newBinaryExpression( loc, Operator.LOGICAND, leftSmallerZero, thereIsRemainder); }
private Expression constructArithmeticExpression( final ILocation loc, final int nodeOperator, final Expression exp1, final Expression exp2) { final BinaryExpression.Operator operator; switch (nodeOperator) { case IASTBinaryExpression.op_minusAssign: case IASTBinaryExpression.op_minus: operator = Operator.ARITHMINUS; break; case IASTBinaryExpression.op_multiplyAssign: case IASTBinaryExpression.op_multiply: operator = Operator.ARITHMUL; break; case IASTBinaryExpression.op_divideAssign: case IASTBinaryExpression.op_divide: operator = Operator.ARITHDIV; break; case IASTBinaryExpression.op_moduloAssign: case IASTBinaryExpression.op_modulo: operator = Operator.ARITHMOD; break; case IASTBinaryExpression.op_plusAssign: case IASTBinaryExpression.op_plus: operator = Operator.ARITHPLUS; break; default: final String msg = "Unknown or unsupported arithmetic expression"; throw new UnsupportedSyntaxException(loc, msg); } return ExpressionFactory.newBinaryExpression(loc, operator, exp1, exp2); }
@Override public Expression constructBinaryComparisonFloatingPointExpression( final ILocation loc, final int nodeOperator, final Expression exp1, final CPrimitive type1, final Expression exp2, final CPrimitive type2) { if (mOverapproximateFloatingPointOperations) { final String functionName = "someBinary" + type1.toString() + "ComparisonOperation"; final String prefixedFunctionName = "~" + functionName; if (!mFunctionDeclarations.getDeclaredFunctions().containsKey(prefixedFunctionName)) { final Attribute attribute = new NamedAttribute( loc, FunctionDeclarations.s_OVERAPPROX_IDENTIFIER, new Expression[] {new StringLiteral(loc, functionName)}); final Attribute[] attributes = new Attribute[] {attribute}; final ASTType paramAstType = mTypeHandler.ctype2asttype(loc, type1); final ASTType resultAstType = new PrimitiveType(loc, SFO.BOOL); mFunctionDeclarations.declareFunction( loc, prefixedFunctionName, attributes, resultAstType, paramAstType, paramAstType); } return new FunctionApplication(loc, prefixedFunctionName, new Expression[] {exp1, exp2}); } else { BinaryExpression.Operator op; switch (nodeOperator) { case IASTBinaryExpression.op_equals: op = BinaryExpression.Operator.COMPEQ; break; case IASTBinaryExpression.op_greaterEqual: op = BinaryExpression.Operator.COMPGEQ; break; case IASTBinaryExpression.op_greaterThan: op = BinaryExpression.Operator.COMPGT; break; case IASTBinaryExpression.op_lessEqual: op = BinaryExpression.Operator.COMPLEQ; break; case IASTBinaryExpression.op_lessThan: op = BinaryExpression.Operator.COMPLT; break; case IASTBinaryExpression.op_notequals: op = BinaryExpression.Operator.COMPNEQ; break; default: throw new AssertionError("Unknown BinaryExpression operator " + nodeOperator); } return ExpressionFactory.newBinaryExpression(loc, op, exp1, exp2); } }
private Expression constructUnaryIntExprMinus( final ILocation loc, final Expression expr, final CPrimitive type) { if (type.getGeneralType() == CPrimitiveCategory.INTTYPE) { return ExpressionFactory.newUnaryExpression( loc, UnaryExpression.Operator.ARITHNEGATIVE, expr); } else if (type.getGeneralType() == CPrimitiveCategory.FLOATTYPE) { // TODO: having boogie deal with negative real literals would be the nice solution.. return ExpressionFactory.newBinaryExpression( loc, Operator.ARITHMINUS, new RealLiteral(loc, "0.0"), expr); } else { throw new IllegalArgumentException("unsupported " + type); } }
@Override public Expression constructBinaryComparisonIntegerExpression( final ILocation loc, final int nodeOperator, final Expression exp1, final CPrimitive type1, final Expression exp2, final CPrimitive type2) { if (!type1.equals(type2)) { throw new IllegalArgumentException("incompatible types " + type1 + " and " + type2); } Expression leftExpr = exp1; Expression rightExpr = exp2; if (mUnsignedTreatment == UnsignedTreatment.WRAPAROUND && mTypeSizes.isUnsigned(type1)) { assert mTypeSizes.isUnsigned(type2); leftExpr = applyWraparound(loc, mTypeSizes, type1, leftExpr); rightExpr = applyWraparound(loc, mTypeSizes, type2, rightExpr); } BinaryExpression.Operator op; switch (nodeOperator) { case IASTBinaryExpression.op_equals: op = BinaryExpression.Operator.COMPEQ; break; case IASTBinaryExpression.op_greaterEqual: op = BinaryExpression.Operator.COMPGEQ; break; case IASTBinaryExpression.op_greaterThan: op = BinaryExpression.Operator.COMPGT; break; case IASTBinaryExpression.op_lessEqual: op = BinaryExpression.Operator.COMPLEQ; break; case IASTBinaryExpression.op_lessThan: op = BinaryExpression.Operator.COMPLT; break; case IASTBinaryExpression.op_notequals: op = BinaryExpression.Operator.COMPNEQ; break; default: throw new AssertionError("Unknown BinaryExpression operator " + nodeOperator); } return ExpressionFactory.newBinaryExpression(loc, op, leftExpr, rightExpr); }
public static Expression applyWraparound( final ILocation loc, final TypeSizes typeSizes, final CPrimitive cPrimitive, final Expression operand) { if (cPrimitive.getGeneralType() == CPrimitiveCategory.INTTYPE) { if (typeSizes.isUnsigned(cPrimitive)) { final BigInteger maxValuePlusOne = typeSizes.getMaxValueOfPrimitiveType(cPrimitive).add(BigInteger.ONE); return ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMOD, operand, new IntegerLiteral(loc, maxValuePlusOne.toString())); } else { throw new AssertionError("wraparound only for unsigned types"); } } else { throw new AssertionError("wraparound only for integer types"); } }
/** Returns "assume (minValue <= lrValue && lrValue <= maxValue)" */ private AssumeStatement constructAssumeInRangeStatement( final TypeSizes typeSizes, final ILocation loc, final Expression expr, final CPrimitive type) { final Expression minValue = constructLiteralForIntegerType(loc, type, typeSizes.getMinValueOfPrimitiveType(type)); final Expression maxValue = constructLiteralForIntegerType(loc, type, typeSizes.getMaxValueOfPrimitiveType(type)); final Expression biggerMinInt = constructBinaryComparisonExpression( loc, IASTBinaryExpression.op_lessEqual, minValue, type, expr, type); final Expression smallerMaxValue = constructBinaryComparisonExpression( loc, IASTBinaryExpression.op_lessEqual, expr, type, maxValue, type); final AssumeStatement inRange = new AssumeStatement( loc, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.LOGICAND, biggerMinInt, smallerMaxValue)); return inRange; }
private void convertToIntegerType( final ILocation loc, final ExpressionResult operand, final CPrimitive resultType) { assert resultType.isIntegerType(); final CPrimitive oldType = (CPrimitive) operand.lrVal.getCType(); if (oldType.isIntegerType()) { final Expression newExpression; if (mTypeSizes.isUnsigned(resultType)) { final Expression oldWrappedIfNeeded; if (mTypeSizes.isUnsigned(oldType) && mTypeSizes.getSize(resultType.getType()) > mTypeSizes.getSize(oldType.getType())) { // required for sound Nutz transformation // (see examples/programs/regression/c/NutzTransformation03.c) oldWrappedIfNeeded = applyWraparound(loc, mTypeSizes, oldType, operand.lrVal.getValue()); } else { oldWrappedIfNeeded = operand.lrVal.getValue(); } if (mUnsignedTreatment == UnsignedTreatment.ASSERT) { final BigInteger maxValuePlusOne = mTypeSizes.getMaxValueOfPrimitiveType(resultType).add(BigInteger.ONE); final AssertStatement assertGeq0 = new AssertStatement( loc, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPGEQ, oldWrappedIfNeeded, new IntegerLiteral(loc, SFO.NR0))); final Check chk1 = new Check(Spec.UINT_OVERFLOW); chk1.addToNodeAnnot(assertGeq0); operand.stmt.add(assertGeq0); final AssertStatement assertLtMax = new AssertStatement( loc, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPLT, oldWrappedIfNeeded, new IntegerLiteral(loc, maxValuePlusOne.toString()))); final Check chk2 = new Check(Spec.UINT_OVERFLOW); chk2.addToNodeAnnot(assertLtMax); operand.stmt.add(assertLtMax); } else { // do nothing } newExpression = oldWrappedIfNeeded; } else { assert !mTypeSizes.isUnsigned(resultType); final Expression oldWrappedIfUnsigned; if (mTypeSizes.isUnsigned(oldType)) { // required for sound Nutz transformation // (see examples/programs/regression/c/NutzTransformation01.c) oldWrappedIfUnsigned = applyWraparound(loc, mTypeSizes, oldType, operand.lrVal.getValue()); } else { oldWrappedIfUnsigned = operand.lrVal.getValue(); } if (mTypeSizes.getSize(resultType.getType()) > mTypeSizes.getSize(oldType.getType()) || (mTypeSizes .getSize(resultType.getType()) .equals(mTypeSizes.getSize(oldType.getType())) && !mTypeSizes.isUnsigned(oldType))) { newExpression = oldWrappedIfUnsigned; } else { // According to C11 6.3.1.3.3 the result is implementation-defined // it the value cannot be represented by the new type // We have chosen an implementation that is similar to // taking the lowest bits in a two's complement representation: // First we take the value modulo the cardinality of the // data range (which is 2*(MAX_VALUE+1) for signed ) // If the number is strictly larger than MAX_VALUE we // subtract the cardinality of the data range. final CPrimitive correspondingUnsignedType = mTypeSizes.getCorrespondingUnsignedType(resultType); final Expression wrapped = applyWraparound(loc, mTypeSizes, correspondingUnsignedType, oldWrappedIfUnsigned); final Expression maxValue = constructLiteralForIntegerType( loc, oldType, mTypeSizes.getMaxValueOfPrimitiveType(resultType)); final Expression condition = ExpressionFactory.newBinaryExpression(loc, Operator.COMPLEQ, wrapped, maxValue); final Expression range = constructLiteralForIntegerType( loc, oldType, mTypeSizes .getMaxValueOfPrimitiveType(correspondingUnsignedType) .add(BigInteger.ONE)); newExpression = ExpressionFactory.newIfThenElseExpression( loc, condition, wrapped, ExpressionFactory.newBinaryExpression(loc, Operator.ARITHMINUS, wrapped, range)); } } final RValue newRValue = new RValue(newExpression, resultType, false, false); operand.lrVal = newRValue; } else { throw new UnsupportedOperationException("not yet supported: conversion from " + oldType); } }
private Expression constructArIntExprMod( final ILocation loc, final Expression exp1, final Expression exp2, final boolean bothAreIntegerLiterals, final BigInteger leftValue, final BigInteger rightValue) { final BinaryExpression.Operator operator; operator = Operator.ARITHMOD; /* * In C the semantics of integer division is "rounding towards zero". In Boogie euclidian division is used. We * translate a % b into (a < 0 && a%b != 0) ? ( (b < 0) ? (a%b)-b : (a%b)+b) : a%b */ // modulo on bigInteger does not seem to follow the "multiply, add, and get the result // back"-rule, together // with its division.. if (bothAreIntegerLiterals) { final String constantResult; if (leftValue.signum() == 1 || leftValue.signum() == 0) { if (rightValue.signum() == 1) { constantResult = leftValue.mod(rightValue).toString(); } else if (rightValue.signum() == -1) { constantResult = leftValue.mod(rightValue.negate()).toString(); } else { constantResult = "0"; } } else if (leftValue.signum() == -1) { if (rightValue.signum() == 1) { constantResult = (leftValue.negate().mod(rightValue)).negate().toString(); } else if (rightValue.signum() == -1) { constantResult = (leftValue.negate().mod(rightValue.negate())).negate().toString(); } else { constantResult = "0"; } } else { throw new UnsupportedOperationException("constant is not assigned"); } return new IntegerLiteral(loc, constantResult); } else { final Expression leftSmallerZeroAndThereIsRemainder = getLeftSmallerZeroAndThereIsRemainder(loc, exp1, exp2); final Expression rightSmallerZero = ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPLT, exp2, new IntegerLiteral(loc, SFO.NR0)); final Expression normalModulo = ExpressionFactory.newBinaryExpression(loc, operator, exp1, exp2); if (exp1 instanceof IntegerLiteral) { if (leftValue.signum() == 1) { return normalModulo; } else if (leftValue.signum() == -1) { return ExpressionFactory.newIfThenElseExpression( loc, rightSmallerZero, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2), ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2)); } else { return new IntegerLiteral(loc, SFO.NR0); } } else if (exp2 instanceof IntegerLiteral) { if (rightValue.signum() == 1 || rightValue.signum() == 0) { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2), normalModulo); } else if (rightValue.signum() == -1) { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2), normalModulo); } throw new UnsupportedOperationException( "Is it expected that this is a fall-through switch?"); } else { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newIfThenElseExpression( loc, rightSmallerZero, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalModulo, exp2), ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalModulo, exp2)), normalModulo); } } }
private Expression constructArIntExprDiv( final ILocation loc, final Expression exp1, final Expression exp2, final boolean bothAreIntegerLiterals, final BigInteger leftValue, final BigInteger rightValue) { final BinaryExpression.Operator operator; operator = Operator.ARITHDIV; /* * In C the semantics of integer division is "rounding towards zero". In Boogie euclidian division is used. We * translate a / b into (a < 0 && a%b != 0) ? ( (b < 0) ? (a/b)+1 : (a/b)-1) : a/b */ if (bothAreIntegerLiterals) { final String constantResult = leftValue.divide(rightValue).toString(); return new IntegerLiteral(loc, constantResult); } else { final Expression leftSmallerZeroAndThereIsRemainder = getLeftSmallerZeroAndThereIsRemainder(loc, exp1, exp2); final Expression rightSmallerZero = ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.COMPLT, exp2, new IntegerLiteral(loc, SFO.NR0)); final Expression normalDivision = ExpressionFactory.newBinaryExpression(loc, operator, exp1, exp2); if (exp1 instanceof IntegerLiteral) { if (leftValue.signum() == 1) { return normalDivision; } else if (leftValue.signum() == -1) { return ExpressionFactory.newIfThenElseExpression( loc, rightSmallerZero, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalDivision, new IntegerLiteral(loc, SFO.NR1)), ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalDivision, new IntegerLiteral(loc, SFO.NR1))); } else { return new IntegerLiteral(loc, SFO.NR0); } } else if (exp2 instanceof IntegerLiteral) { if (rightValue.signum() == 1 || rightValue.signum() == 0) { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalDivision, new IntegerLiteral(loc, SFO.NR1)), normalDivision); } else if (rightValue.signum() == -1) { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalDivision, new IntegerLiteral(loc, SFO.NR1)), normalDivision); } throw new UnsupportedOperationException( "Is it expected that this is a fall-through switch?"); } else { return ExpressionFactory.newIfThenElseExpression( loc, leftSmallerZeroAndThereIsRemainder, ExpressionFactory.newIfThenElseExpression( loc, rightSmallerZero, ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHMINUS, normalDivision, new IntegerLiteral(loc, SFO.NR1)), ExpressionFactory.newBinaryExpression( loc, BinaryExpression.Operator.ARITHPLUS, normalDivision, new IntegerLiteral(loc, SFO.NR1))), normalDivision); } } }