/// <summary> /// Converts a Boolean Expression into a logically equivalent ITE statement that returns /// a bitvector instead. If the Expression is not Boolean, it is returned unchanged. /// </summary> /// /// <param name="exprString">SMT-LIB v2.0-compliant string that represents /// the Expression to convert.</param> /// <param name="exprType">Type of the Expression.</param> /// <param name="bitSize">Bit-size of the resulting bitvector.</param> /// <returns>Logically equivalent ITE statement if the Expression is Boolean; /// unchanged input Expression otherwise.</returns> private static string BooleanToIte(string exprString, ExpressionType exprType, uint bitSize) { string result = null; switch (exprType) { case ExpressionType.DEFAULT: result = exprString; break; case ExpressionType.BOOLEAN: string zeroBv = SmtHelper.MakeConstantBv("0", bitSize); string oneBv = SmtHelper.MakeConstantBv("1", bitSize); result = "(ite " + exprString + " " + oneBv + " " + zeroBv + ")"; break; default: Trace.Fail("PHOENIX: Unrecognized Expression type: " + exprType.ToString()); break; } return(result); }
/// <summary> /// Returns a pair whose first element is a string that complies with the SMT-LIB v2.0 /// standard and that corresponds to the input Expression, and whose second element /// is the type of the Expression. /// </summary> /// /// <param name="expr">Expression to convert.</param> /// <returns>Pair whose first element is a string that complies with the SMT-LIB v2.0 /// standard and that corresponds to the input Expression, and whose second element /// is the type of the Expression.</returns> private static Pair <string, ExpressionType> ConvertToSmtLib2(Expression expr) { Pair <string, ExpressionType> result = null; string resultString = ""; OperatorType exprOpType = expr.Op.Type; switch (exprOpType) { case OperatorType.True: result = new Pair <string, ExpressionType>("true", ExpressionType.BOOLEAN); break; case OperatorType.False: result = new Pair <string, ExpressionType>("false", ExpressionType.BOOLEAN); break; case OperatorType.Constant: resultString = SmtHelper.MakeConstantBv(expr.Value, expr.BitSize); result = new Pair <string, ExpressionType>(resultString, ExpressionType.DEFAULT); break; case OperatorType.Variable: case OperatorType.ArrayVariable: result = new Pair <string, ExpressionType>(expr.Value, ExpressionType.DEFAULT); break; case OperatorType.ZeroExtend: case OperatorType.SignExtend: Expression toExtendExpr = expr.GetParameter(0); Expression extendByExpr = expr.GetParameter(1); Pair <string, ExpressionType> convertedToExtendExpr = SmtHelper.ConvertToSmtLib2(toExtendExpr); resultString = "((_ " + (exprOpType == OperatorType.ZeroExtend ? "zero_extend" : "sign_extend") + " " + extendByExpr.Value + ") "; resultString += SmtHelper.BooleanToIte(convertedToExtendExpr.First, convertedToExtendExpr.Second, toExtendExpr.BitSize) + ")"; result = new Pair <string, ExpressionType>(resultString, ExpressionType.DEFAULT); break; case OperatorType.BitExtract: Expression toExtractExpr = expr.GetParameter(0); Expression lowIndexExpr = expr.GetParameter(1); Expression highIndexExpr = expr.GetParameter(2); Pair <string, ExpressionType> convertedToExtractExpr = SmtHelper.ConvertToSmtLib2(toExtractExpr); resultString = "((_ extract " + highIndexExpr.Value + " " + lowIndexExpr.Value + ") "; resultString += SmtHelper.BooleanToIte(convertedToExtractExpr.First, convertedToExtractExpr.Second, toExtractExpr.BitSize) + ")"; result = new Pair <string, ExpressionType>(resultString, ExpressionType.DEFAULT); break; case OperatorType.Ite: Expression conditionalExpr = expr.GetParameter(0); Expression consequentExpr = expr.GetParameter(1); Expression alternateExpr = expr.GetParameter(2); Pair <string, ExpressionType> convertedConditionalExpr = SmtHelper.ConvertToSmtLib2(conditionalExpr); Pair <string, ExpressionType> convertedConsequentExpr = SmtHelper.ConvertToSmtLib2(consequentExpr); Pair <string, ExpressionType> convertedAlternateExpr = SmtHelper.ConvertToSmtLib2(alternateExpr); resultString = "(ite " + convertedConditionalExpr.First + " "; resultString += SmtHelper.BooleanToIte(convertedConsequentExpr.First, convertedConsequentExpr.Second, consequentExpr.BitSize) + " "; resultString += SmtHelper.BooleanToIte(convertedAlternateExpr.First, convertedAlternateExpr.Second, alternateExpr.BitSize) + ")"; result = new Pair <string, ExpressionType>(resultString, ExpressionType.DEFAULT); break; case OperatorType.And: case OperatorType.Or: case OperatorType.Not: resultString = SmtHelper.MakeBooleanExpr(expr); result = new Pair <string, ExpressionType>(resultString, ExpressionType.BOOLEAN); break; case OperatorType.NotEqual: Expression firstParam = expr.GetParameter(0); Expression secondParam = expr.GetParameter(1); Pair <string, ExpressionType> convertedFirstParam = SmtHelper.ConvertToSmtLib2(firstParam); Pair <string, ExpressionType> convertedSecondParam = SmtHelper.ConvertToSmtLib2(secondParam); resultString = "(not (= "; resultString += SmtHelper.BooleanToIte(convertedFirstParam.First, convertedFirstParam.Second, firstParam.BitSize) + " "; resultString += SmtHelper.BooleanToIte(convertedSecondParam.First, convertedSecondParam.Second, secondParam.BitSize) + "))"; result = new Pair <string, ExpressionType>(resultString, ExpressionType.BOOLEAN); break; default: string convertedParams = ""; foreach (Expression paramExpr in expr.ParameterList) { Pair <string, ExpressionType> convertedParam = SmtHelper.ConvertToSmtLib2(paramExpr); convertedParams += " " + SmtHelper.BooleanToIte(convertedParam.First, convertedParam.Second, paramExpr.BitSize); } OperatorType opType = expr.Op.Type; ExpressionType resultType = SmtHelper.IsComparisonOp(opType) ? ExpressionType.BOOLEAN : ExpressionType.DEFAULT; string functionForOp = ""; int numParams = expr.ParameterList.Count; switch (numParams) { case 1: functionForOp = SmtHelper.GetFunctionForUnary(opType); break; case 2: functionForOp = SmtHelper.GetFunctionForBinary(opType); break; case 3: functionForOp = SmtHelper.GetFunctionForTernary(opType); break; default: throw new NotImplementedException("PHOENIX: " + "No support for operators with arity " + numParams.ToString() + "."); } resultString = "(" + functionForOp + convertedParams + ")"; result = new Pair <string, ExpressionType>(resultString, resultType); break; } Trace.Assert(result != null, "PHOENIX: Result should not be null."); return(result); }