@Override protected String declareConversionFunction( final ILocation loc, final CPrimitive oldType, final CPrimitive newType) { final String functionName = "convert" + oldType.toString() + "To" + newType.toString(); final String prefixedFunctionName = "~" + functionName; if (!mFunctionDeclarations.getDeclaredFunctions().containsKey(prefixedFunctionName)) { final Attribute[] attributes; final ASTType paramASTType = mTypeHandler.ctype2asttype(loc, oldType); if (newType.isFloatingType()) { attributes = generateAttributes(loc, mOverapproximateFloatingPointOperations, "to_real", null); } else if (newType.isIntegerType()) { attributes = generateAttributes(loc, mOverapproximateFloatingPointOperations, "to_int", null); } else { throw new AssertionError("unhandled case"); } final ASTType[] params = new ASTType[] {paramASTType}; final ASTType resultASTType = mTypeHandler.ctype2asttype(loc, newType); mFunctionDeclarations.declareFunction( loc, prefixedFunctionName, attributes, resultASTType, params); } return prefixedFunctionName; }
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 constructArithmeticFloatingPointExpression( final ILocation loc, final int nodeOperator, final Expression exp1, final CPrimitive type1, final Expression exp2, final CPrimitive type2) { if (mOverapproximateFloatingPointOperations) { final String functionName = "someBinaryArithmetic" + type1.toString() + "operation"; 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 astType = mTypeHandler.ctype2asttype(loc, type1); mFunctionDeclarations.declareFunction( loc, prefixedFunctionName, attributes, astType, astType, astType); } return new FunctionApplication(loc, prefixedFunctionName, new Expression[] {exp1, exp2}); } else { return constructArithmeticExpression(loc, nodeOperator, exp1, exp2); } }
public void oldConvertPointerToInt( final ILocation loc, final ExpressionResult rexp, final CPrimitive newType) { assert newType.isIntegerType(); assert rexp.lrVal.getCType() instanceof CPointer; if (OVERAPPROXIMATE_INT_POINTER_CONVERSION) { super.convertPointerToInt(loc, rexp, newType); } else { final Expression pointerExpression = rexp.lrVal.getValue(); final Expression intExpression; if (mTypeSizes.useFixedTypeSizes()) { final BigInteger maxPtrValuePlusOne = mTypeSizes.getMaxValueOfPointer().add(BigInteger.ONE); final IntegerLiteral maxPointer = new IntegerLiteral(loc, maxPtrValuePlusOne.toString()); intExpression = constructArithmeticExpression( loc, IASTBinaryExpression.op_plus, constructArithmeticExpression( loc, IASTBinaryExpression.op_multiply, MemoryHandler.getPointerBaseAddress(pointerExpression, loc), newType, maxPointer, newType), newType, MemoryHandler.getPointerOffset(pointerExpression, loc), newType); } else { intExpression = MemoryHandler.getPointerOffset(pointerExpression, loc); } final RValue rValue = new RValue(intExpression, newType, false, true); rexp.lrVal = rValue; } }
@Override public void convertIntToInt_NonBool( final ILocation loc, final ExpressionResult operand, final CPrimitive resultType) { if (resultType.isIntegerType()) { convertToIntegerType(loc, operand, resultType); } else { throw new UnsupportedOperationException("not yet supported: conversion to " + resultType); } }
@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); } }
@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"); } }
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); } }
@Override public Expression constructArithmeticIntegerExpression( final ILocation loc, final int nodeOperator, final Expression leftExp, final CPrimitive leftType, final Expression rightExp, final CPrimitive rightType) { assert leftType.getGeneralType() == CPrimitiveCategory.INTTYPE; assert rightType.getGeneralType() == CPrimitiveCategory.INTTYPE; Expression leftExpr = leftExp; Expression rightExpr = rightExp; if (leftType.isIntegerType() && mTypeSizes.isUnsigned(leftType)) { assert rightType.isIntegerType() && mTypeSizes.isUnsigned(rightType) : "incompatible types"; if (nodeOperator == IASTBinaryExpression.op_divide || nodeOperator == IASTBinaryExpression.op_divideAssign || nodeOperator == IASTBinaryExpression.op_modulo || nodeOperator == IASTBinaryExpression.op_moduloAssign) { // apply wraparound to ensure that Nutz transformation is sound // (see examples/programs/regression/c/NutzTransformation02.c) leftExpr = applyWraparound(loc, mTypeSizes, leftType, leftExpr); rightExpr = applyWraparound(loc, mTypeSizes, rightType, rightExpr); } } final boolean bothAreIntegerLiterals = leftExpr instanceof IntegerLiteral && rightExpr instanceof IntegerLiteral; BigInteger leftValue = null; BigInteger rightValue = null; // TODO: add checks for UnaryExpression (otherwise we don't catch negative constants, here) --> // or remove all // the cases // (if-then-else conditions are checked for being constant in RCFGBuilder anyway, so this is // merely a decision // of readability of Boogie code..) if (leftExpr instanceof IntegerLiteral) { leftValue = new BigInteger(((IntegerLiteral) leftExpr).getValue()); } if (rightExpr instanceof IntegerLiteral) { rightValue = new BigInteger(((IntegerLiteral) rightExpr).getValue()); } switch (nodeOperator) { case IASTBinaryExpression.op_minusAssign: case IASTBinaryExpression.op_minus: case IASTBinaryExpression.op_multiplyAssign: case IASTBinaryExpression.op_multiply: case IASTBinaryExpression.op_plusAssign: case IASTBinaryExpression.op_plus: return constructArithmeticExpression(loc, nodeOperator, leftExp, rightExp); case IASTBinaryExpression.op_divideAssign: case IASTBinaryExpression.op_divide: return constructArIntExprDiv( loc, leftExpr, rightExpr, bothAreIntegerLiterals, leftValue, rightValue); case IASTBinaryExpression.op_moduloAssign: case IASTBinaryExpression.op_modulo: return constructArIntExprMod( loc, leftExpr, rightExpr, bothAreIntegerLiterals, leftValue, rightValue); default: final String msg = "Unknown or unsupported arithmetic expression"; throw new UnsupportedSyntaxException(loc, msg); } }