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 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 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); } } }