/* * (C) Copyright 2010-2015 SAP SE. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * */ package com.logicalhacking.dasca.dataflow.util; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import com.ibm.wala.cast.ir.ssa.CAstBinaryOp; import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction; import com.ibm.wala.shrikeBT.BinaryOpInstruction; import com.ibm.wala.shrikeBT.IBinaryOpInstruction.IOperator; import com.ibm.wala.ssa.ConstantValue; import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.SSABinaryOpInstruction; import com.ibm.wala.ssa.SSACFG.BasicBlock; import com.ibm.wala.ssa.SSAConditionalBranchInstruction; import com.ibm.wala.ssa.SSAConversionInstruction; import com.ibm.wala.ssa.SSAGetInstruction; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAPhiInstruction; import com.ibm.wala.ssa.SSAUnaryOpInstruction; import com.ibm.wala.ssa.SymbolTable; import com.ibm.wala.types.FieldReference; import com.ibm.wala.types.TypeReference; import cvc3.Expr; import cvc3.ValidityChecker; public class SMTChecker { private static Logger log = AnalysisUtil.getLogger(SMTChecker.class); public static Expr getExprForCondition(ValidityChecker vc, BasicBlock basicBlock, IR entryIR) { // According to WALA documentation these blocks contain exactly one instruction SSAConditionalBranchInstruction inst = (SSAConditionalBranchInstruction) basicBlock.getLastInstruction(); int var = inst.getUse(0); // This Instruction contains exactly two uses (0, 1) and use 1 is always 0. Expr expr = getExprForInstruction(vc, var, entryIR, null); return expr; } /** * Returns simple expression for loop-condition. Expects for-loop with simple comparison with constant on the right hand side * *
TODO: implement correct for all kinds of loops * @param vc * @param inst * @param entryIR * @return */ public static Expr getExprForLoop(ValidityChecker vc, SSAInstruction inst, IR entryIR) { // According to WALA documentation these blocks contain exactly one instruction SSAConditionalBranchInstruction condInst = (SSAConditionalBranchInstruction) inst; int var = condInst.getUse(0); // This Instruction contains exactly the two uses 0 and 1. Use 1 has always the value 0, since it stands for TRUE. SymbolTable symTab = entryIR.getSymbolTable(); DefUse du = new DefUse(entryIR); SSAInstruction useInst = du.getDef(var); SSABinaryOpInstruction binOpInstruction = (SSABinaryOpInstruction) useInst; int varNo0 = useInst.getUse(0); // value at the left hand side Expr exprLhs = null; SSAInstruction leftInstruction = du.getDef(varNo0); SSAPhiInstruction phiInstruction = (SSAPhiInstruction) leftInstruction; for(int i = 0; i< phiInstruction.getNumberOfUses(); i++) { // TODO: use bit array to identify overflows int varNo = phiInstruction.getUse(i); if(symTab.isIntegerConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Integer integer = (Integer) value.getValue(); exprLhs = vc.exprFromString("" + integer.intValue()); break; } else if(symTab.isLongConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Long longValue = (Long) value.getValue(); exprLhs = vc.exprFromString("" + longValue.longValue()); break; } else if(symTab.isDoubleConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Double doubleValue = (Double) value.getValue(); exprLhs = vc.exprFromString("" + doubleValue.doubleValue()); break; } else if(symTab.isFloatConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Float floatValue = (Float) value.getValue(); exprLhs = vc.exprFromString("" + floatValue.floatValue()); break; } } int varNo1 = useInst.getUse(1); // value at the right hand side Expr exprRhs; if(symTab.isIntegerConstant(varNo1)) { // TODO: use bit array to identify overflows ConstantValue value = (ConstantValue) symTab.getValue(varNo1); Integer integer = (Integer) value.getValue(); exprRhs = vc.exprFromString("" + integer.intValue()); } else if(symTab.isLongConstant(varNo1)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo1); Long longValue = (Long) value.getValue(); exprRhs = vc.exprFromString("" + longValue.longValue()); } else if(symTab.isDoubleConstant(varNo1)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo1); Double doubleValue = (Double) value.getValue(); exprRhs = vc.exprFromString("" + doubleValue.doubleValue()); } else if(symTab.isFloatConstant(varNo1)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo1); Float floatValue = (Float) value.getValue(); exprRhs = vc.exprFromString("" + floatValue.floatValue()); } else { exprRhs = vc.varExpr(String.format("v%d",varNo1), vc.realType()); } IOperator op = binOpInstruction.getOperator(); if(op == BinaryOpInstruction.Operator.OR) { return vc.orExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.AND) { return vc.andExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.SUB) { return vc.minusExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.ADD) { return vc.plusExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.DIV) { return vc.divideExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.MUL) { return vc.multExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.LT) { return vc.ltExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.LE) { return vc.leExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.EQ) { return vc.eqExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.GE) { return vc.geExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.GT) { return vc.gtExpr(exprLhs, exprRhs); } else { return vc.notExpr(vc.eqExpr(exprLhs, exprRhs)); } } public static Expr getExprForConditionalBranchInstruction(ValidityChecker vc, SSAInstruction inst, IR entryIR) { // According to WALA documentation these blocks contain exactly one instruction SSAConditionalBranchInstruction condInst = (SSAConditionalBranchInstruction) inst; int var = condInst.getUse(0); // This Instruction contains exactly two uses (0, 1) and use 1 is always 0. Expr expr = getExprForInstruction(vc, var, entryIR, BinaryOpInstruction.Operator.AND); // The AND operator identifies the expression as a boolean type return expr; } private static Expr getExprForInstruction(ValidityChecker vc, int varNo, IR ir, IOperator op2) { SymbolTable symTab = ir.getSymbolTable(); if(symTab.isConstant(varNo)) { if(symTab.isBooleanConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); boolean isTrueConstant = value.isTrueConstant(); if(symTab.isTrue(varNo)) { return vc.trueExpr(); } else if(symTab.isFalse(varNo)) { return vc.falseExpr(); } return vc.varExpr(String.format("v%d",varNo), vc.boolType(), (isTrueConstant) ? vc.trueExpr() : vc.falseExpr()); } else if(symTab.isNumberConstant(varNo)) { // TODO: use bit array to identify overflows if(symTab.isIntegerConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Integer integer = (Integer) value.getValue(); return vc.exprFromString("" + integer.intValue()); } else if(symTab.isLongConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Long longValue = (Long) value.getValue(); return vc.exprFromString("" + longValue.longValue()); } else if(symTab.isDoubleConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Double doubleValue = (Double) value.getValue(); return vc.exprFromString("" + doubleValue.doubleValue()); } else if(symTab.isFloatConstant(varNo)) { ConstantValue value = (ConstantValue) symTab.getValue(varNo); Float floatValue = (Float) value.getValue(); return vc.exprFromString("" + floatValue.floatValue()); } } else if(symTab.isTrue(varNo)) { return vc.trueExpr(); } else if(symTab.isFalse(varNo)) { return vc.falseExpr(); } else if(symTab.isNullConstant(varNo)) { return vc.nullExpr(); } } else { DefUse du = new DefUse(ir); SSAInstruction defInst = du.getDef(varNo); if(defInst == null) { if(op2 == BinaryOpInstruction.Operator.OR || op2 == BinaryOpInstruction.Operator.AND) { return vc.varExpr(String.format("v%d",varNo), vc.boolType()); } else { return vc.varExpr(String.format("v%d",varNo), vc.realType()); } } else if(defInst instanceof SSAGetInstruction) { // def refers to static value SSAGetInstruction inst = (SSAGetInstruction) defInst; FieldReference fr = inst.getDeclaredField(); TypeReference tr = fr.getFieldType(); if(tr.equals(TypeReference.Boolean)) { return vc.varExpr(String.format("v%d",varNo), vc.boolType()); } } if(defInst instanceof SSABinaryOpInstruction) { SSABinaryOpInstruction binaryInst = (SSABinaryOpInstruction) defInst; IOperator op = binaryInst.getOperator(); // BinaryInstructions always contain exactly two uses // left hand side int var1 = binaryInst.getUse(0); Expr exprLhs = getExprForInstruction(vc, var1, ir, op); // right hand side int var2 = binaryInst.getUse(1); Expr exprRhs = getExprForInstruction(vc, var2, ir, op); if(op == BinaryOpInstruction.Operator.OR) { return vc.orExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.AND) { return vc.andExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.SUB) { return vc.minusExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.ADD) { return vc.plusExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.DIV) { return vc.divideExpr(exprLhs, exprRhs); } else if(op == BinaryOpInstruction.Operator.MUL) { return vc.multExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.LT) { return vc.ltExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.LE) { return vc.leExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.EQ) { return vc.eqExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.GE) { return vc.geExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.GT) { return vc.gtExpr(exprLhs, exprRhs); } else if(op == CAstBinaryOp.NE) { return vc.notExpr(vc.eqExpr(exprLhs, exprRhs)); } } else if(defInst instanceof SSAUnaryOpInstruction) { // WALA uses unary operation ONLY for negation SSAUnaryOpInstruction unaryInst = (SSAUnaryOpInstruction) defInst; int var = unaryInst.getUse(0); Expr expr = getExprForInstruction(vc, var, ir, BinaryOpInstruction.Operator.AND); return vc.notExpr(expr); } else if(defInst instanceof SSAConversionInstruction) { SSAConversionInstruction conversionInst = (SSAConversionInstruction) defInst; // ConversionInstructions always contain exactly one use int var = conversionInst.getUse(0); return getExprForInstruction(vc, var, ir, op2); } else if(defInst instanceof SSAPhiInstruction) { SSAPhiInstruction phiInst = (SSAPhiInstruction) defInst; List expr = new ArrayList(); for(int i = 0; i