/** * */ package bixie.checker.transition_relation; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.joogie.cfgPlugin.CFGPlugin; import org.joogie.cfgPlugin.Util.Dag; import util.Log; import ap.parser.IFormula; import bixie.checker.GlobalsCache; import bixie.prover.Prover; import bixie.prover.ProverExpr; import bixie.prover.ProverFun; import bixie.prover.ProverType; import bixie.prover.princess.PrincessProver; import boogie.ProgramFactory; import boogie.controlflow.AbstractControlFlowFactory; import boogie.controlflow.BasicBlock; import boogie.controlflow.CfgAxiom; import boogie.controlflow.CfgFunction; import boogie.controlflow.CfgParentEdge; import boogie.controlflow.CfgProcedure; import boogie.controlflow.CfgVariable; import boogie.controlflow.expression.CfgArrayAccessExpression; import boogie.controlflow.expression.CfgArrayStoreExpression; import boogie.controlflow.expression.CfgBinaryExpression; import boogie.controlflow.expression.CfgBooleanLiteral; import boogie.controlflow.expression.CfgExpression; import boogie.controlflow.expression.CfgFunctionApplication; import boogie.controlflow.expression.CfgIdentifierExpression; import boogie.controlflow.expression.CfgIfThenElseExpression; import boogie.controlflow.expression.CfgIntegerLiteral; import boogie.controlflow.expression.CfgQuantifierExpression; import boogie.controlflow.expression.CfgUnaryExpression; import boogie.controlflow.statement.CfgAssertStatement; import boogie.controlflow.statement.CfgAssignStatement; import boogie.controlflow.statement.CfgAssumeStatement; import boogie.controlflow.statement.CfgHavocStatement; import boogie.controlflow.statement.CfgStatement; import boogie.controlflow.util.HasseDiagram; import boogie.type.ArrayType; import boogie.type.BoogieType; /** * @author schaef * */ public class AbstractTransitionRelation { protected Prover prover; protected CfgProcedure procedure; // TODO: bad idea to use HashMap<Integer, ProverExpr> because // we want to be able to iterate over the iterations of a variable protected HashMap<CfgVariable, SortedMap<Integer, ProverExpr>> proverVariables = new HashMap<CfgVariable, SortedMap<Integer, ProverExpr>>(); protected HashMap<String, ProverFun> proverFunctions = new HashMap<String, ProverFun>(); protected AbstractControlFlowFactory controlFlowFactory; protected ProverFun partialOrderOperator; protected HashMap<CfgAxiom, ProverExpr> preludeAxioms = new HashMap<CfgAxiom, ProverExpr>(); protected HashMap<BasicBlock, LinkedList<ProverExpr>> proofObligations = new HashMap<BasicBlock, LinkedList<ProverExpr>>(); protected HashMap<BasicBlock, ProverExpr> reachabilityVariables = new HashMap<BasicBlock, ProverExpr>(); protected ProverExpr requires, ensures; private HashSet<CfgVariable> usedPOVariables = new HashSet<CfgVariable>(); // helper maps for subsitution. protected HashMap<ProverExpr, CfgVariable> invertProverVariables = new HashMap<ProverExpr, CfgVariable>(); protected HashMap<ProverExpr, Integer> invertIncarnationMap = new HashMap<ProverExpr, Integer>(); protected HasseDiagram hasse; protected String procedureName; public AbstractTransitionRelation(CfgProcedure cfg, AbstractControlFlowFactory cff, Prover p) { this.prover = p; this.controlFlowFactory = cff; this.procedure = cfg; this.hasse = new HasseDiagram(cfg); this.procedureName = cfg.getProcedureName(); } public AbstractControlFlowFactory getControlFlowFactory() { return this.controlFlowFactory; } public CfgProcedure getProcedure() { return this.procedure; } /** * * @return */ public String getProcedureName() { return this.procedureName; } /** * Returns the prover expression of the ssa-version of the precondition. * This is meant to be asserted with the verification condition, it is not what * you want to use on the caller side. * @return ProverExpr of the procedure precondition */ public ProverExpr getRequires() { return this.requires; } /** * Returns the prover expression of the ssa-version of the postcondition. * This is meant to be asserted with the verification condition, it is not what * you want to use on the caller side. * @return ProverExpr of the procedure postcondition */ public ProverExpr getEnsures() { return this.ensures; } public Set<BasicBlock> getEffectualSet() { return this.hasse.getEffectualSet(); } public HasseDiagram getHasseDiagram() { return this.hasse; } // public ProverExpr getProverExpr(CfgVariable v, Integer i) { // if (i == null) // return null; // // TODO DSN fix this to not crash if non existant. // SortedMap<Integer, ProverExpr> m = proverVariables.get(v); // if (m == null) { // return null; // } else { // return m.get(i); // } // } // public HashMap<ProverExpr, CfgVariable> getInvertProverVariables() { // return invertProverVariables; // } // // public HashMap<ProverExpr, Integer> getInvertIncarnationMap() { // return invertIncarnationMap; // } /** * returns the map from BasicBlocks to their corresponding ProverExpression * * @return */ public HashMap<BasicBlock, ProverExpr> getReachabilityVariables() { return reachabilityVariables; } /** * This returns a map from basic block to the corresponding proof * obligation. The conjunction of all proof obligations together with the * prelude axioms is the verification condition. * * @return */ public HashMap<BasicBlock, LinkedList<ProverExpr>> getProofObligations() { return proofObligations; } /** * This returns the assertions for all axioms The conjunction of all proof * obligations together with the prelude axioms is the verification * condition. * * @return */ public HashMap<CfgAxiom, ProverExpr> getPreludeAxioms() { return preludeAxioms; } protected void makePrelude() { ProverType[] argTypes = { this.prover.getIntType(), this.prover.getIntType() }; this.partialOrderOperator = this.prover.mkUnintFunction("$poCompare", argTypes, this.prover.getBooleanType()); // Full partial order axioms // Does not work very well in this version, too many axioms, slows // down everything drastically // //genFullPOConstraints(); // First, translate all prelude axioms // TODO: This could be done more efficiently. for (CfgAxiom axiom : this.controlFlowFactory.getGlobalAxioms()) { this.preludeAxioms.put(axiom, expression2proverExpression(axiom.getFormula())); } } protected Dag<IFormula> procToPrincessDag(CfgProcedure proc, HashMap<BasicBlock, ProverExpr> reachVars) { // First transform the CFG into a list and record // the index of each block // it is imporatant that the list starts with the // exitblock LinkedList<BasicBlock> todo = new LinkedList<BasicBlock>(); LinkedList<BasicBlock> done = new LinkedList<BasicBlock>(); todo.add(proc.getRootNode()); while (!todo.isEmpty()) { BasicBlock current = todo.pollLast(); boolean allDone = true; for (BasicBlock pre : current.getPredecessors()) { if (!done.contains(pre)) { allDone = false; continue; } } if (!allDone) { todo.addFirst(current); continue; } // store the position the block will have in the 'done' list. done.addLast(current); for (BasicBlock suc : current.getSuccessors()) { if (!todo.contains(suc) && !done.contains(suc)) { if (suc != current) { todo.addLast(suc); } else { // This has to be checked Log.error("The node has a self-loop! This is not supposed to happen."); } } } } Dag<IFormula> currentNode = CFGPlugin.mkDagEmpty(); // TODO: assert that the first one in the list is actually the ExitBlock for (int j = done.size() - 1; j >= 0; j--) { BasicBlock b = done.get(j); List<Integer> succIndices = new LinkedList<Integer>(); for (BasicBlock suc : b.getSuccessors()) { // TODO: @Philipp willst du die absolute position oder den // offset? int idx = done.indexOf(suc) - done.indexOf(b); succIndices.add(idx); // Log.error("\t " +idx+":"+suc.getName() ); } // TODO: review. can be done better if (reachVars.get(b)==null) throw new RuntimeException("Cannot find var for "+b.getLabel()); IFormula d = ((PrincessProver) this.prover) .proverExpToIFormula(reachVars.get(b)); int[] succidx = new int[succIndices.size()]; for (int i = 0; i < succIndices.size(); i++) { succidx[i] = succIndices.get(i); } currentNode = CFGPlugin.mkDagNode(d, succidx, currentNode); } // currentNode.prettyPrint(); return currentNode; } /* * private void genFullPOConstraints() { //TODO: @Philipp: * this.usedPOVariables haelt alle variablen die in dem aktuellen //scope * benutzt werden und ParentEdges haben. final Prover p = this.prover; final * ProverFun po = this.partialOrderOperator; final ProverType IT = * p.getIntType(); final ProverExpr v0 = p.mkBoundVariable(0, * p.getIntType()); final ProverExpr v1 = p.mkBoundVariable(1, * p.getIntType()); final ProverExpr v2 = p.mkBoundVariable(2, * p.getIntType()); * * { // $poCompare is a reflexive, transitive, anti-symmetric relation * * // reflexivity p.addAssertion(p.mkAll(po.mkExpr(new ProverExpr[] { v0, v0 * }), IT)); * * // transitivity p.addAssertion(p.mkAll(p.mkAll(p.mkAll(p.mkTrigger( * p.mkImplies( p.mkAnd(po.mkExpr(new ProverExpr[] { v0, v1 }), * po.mkExpr(new ProverExpr[] { v1, v2 })), po.mkExpr(new ProverExpr[] { v0, * v2 })), new ProverExpr[] { // Triggers po.mkExpr(new ProverExpr[] { v0, * v1 }), po.mkExpr(new ProverExpr[] { v1, v2 }) }), IT), IT), IT)); * * // anti-symmetry p.addAssertion(p.mkAll(p.mkAll(p.mkTrigger( p.mkImplies( * p.mkAnd(po.mkExpr(new ProverExpr[] { v0, v1 }), po.mkExpr(new * ProverExpr[] { v1, v0 })), p.mkEq(v0, v1)), new ProverExpr[] { // * Triggers po.mkExpr(new ProverExpr[] { v0, v1 }), po.mkExpr(new * ProverExpr[] { v1, v0 }) }), IT), IT)); } * * // Declare constants // TODO: we need axioms about uniqueness for * (Entry<String, CfgVariable> entry : * this.controlFlowFactory.getGlobalVars().entrySet()) { CfgVariable var = * entry.getValue(); if (var.isConstant() && * !var.getParentEdges().isEmpty()) { createProverVar(var, 0); for * (CfgParentEdge edge : var.getParentEdges()) { final CfgVariable parent = * edge.getVaraible(); createProverVar(parent, 0); } } } * * // Add partial-order constraints for (Entry<String, CfgVariable> entry : * this.controlFlowFactory.getGlobalVars().entrySet()) { CfgVariable var = * entry.getValue(); if (var.isConstant() && * !var.getParentEdges().isEmpty()) { final ProverExpr proverVar = * createProverVar(var, 0); * * ProverExpr parentDisj = p.mkEq(v0, proverVar); * * for (CfgParentEdge edge : var.getParentEdges()) { final CfgVariable * parent = edge.getVaraible(); final ProverExpr parentVar = * createProverVar(parent, 0); p.addAssertion(po.mkExpr(new ProverExpr[] { * proverVar, parentVar })); parentDisj = p.mkOr(parentDisj, po.mkExpr(new * ProverExpr[] { parentVar, v0 })); } * * p.addAssertion(p.mkAll(p.mkTrigger( p.mkImplies(po.mkExpr(new * ProverExpr[] { proverVar, v0 }), parentDisj), new ProverExpr[] { * po.mkExpr(new ProverExpr[] { proverVar, v0 }) }), IT)); } } } */ protected void finalizeAxioms() { genGroundPOConstraints(); } private void genGroundPOConstraints() { final Prover p = this.prover; final ProverFun po = this.partialOrderOperator; for (CfgVariable var : new LinkedList<CfgVariable>(usedPOVariables)) { if (var.isConstant() && var.isGlobal()) { // transitively compute all parents final LinkedHashSet<CfgVariable> todo = new LinkedHashSet<CfgVariable>(); final LinkedHashSet<CfgVariable> ancestors = new LinkedHashSet<CfgVariable>(); todo.add(var); while (!todo.isEmpty()) { CfgVariable v = todo.iterator().next(); todo.remove(v); if (ancestors.add(v)) { for (CfgParentEdge edge : v.getParentEdges()) todo.add(edge.getVaraible()); } } // add constraints for (CfgVariable var2 : new LinkedList<CfgVariable>(usedPOVariables)) { final ProverExpr pred = po .mkExpr(new ProverExpr[] { createProverVar(var, 0), createProverVar(var2, 0) }); if (ancestors.contains(var2)) { //System.err.println(" "+pred); p.addAssertion(pred); } else { //System.err.println(" !"+pred); p.addAssertion(p.mkNot(pred)); } } } else { throw new RuntimeException ("unexpected."); } } } public HashMap<ProverExpr, CfgStatement> pe2StmtMap = new HashMap<ProverExpr, CfgStatement>(); protected List<ProverExpr> statements2proverExpression(List<CfgStatement> stmts) { LinkedList<ProverExpr> res = new LinkedList<ProverExpr>(); for (CfgStatement s : stmts) { if (s instanceof CfgAssumeStatement && ((CfgAssumeStatement)s).getCondition() instanceof CfgBooleanLiteral && ((CfgBooleanLiteral)((CfgAssumeStatement)s).getCondition()).getValue()==true) { //do nothing continue; } if (s instanceof CfgAssertStatement && ((CfgAssertStatement)s).getCondition() instanceof CfgBooleanLiteral && ((CfgBooleanLiteral)((CfgAssertStatement)s).getCondition()).getValue()==true) { //do nothing continue; } ProverExpr pe = statement2proverExpression(s); this.pe2StmtMap.put(pe, s); res.add(pe); } return res; } protected ProverExpr statement2proverExpression(CfgStatement s) { if (s instanceof CfgAssertStatement) { CfgAssertStatement assrt = (CfgAssertStatement) s; return expression2proverExpression(assrt.getCondition()); } else if (s instanceof CfgAssignStatement) { CfgAssignStatement assgn = (CfgAssignStatement) s; if (assgn.getLeft().length != assgn.getRight().length) { throw new RuntimeException("malformed assignment."); } ProverExpr[] conj = new ProverExpr[assgn.getLeft().length]; for (int i = 0; i < assgn.getLeft().length; i++) { ProverExpr left = expression2proverExpression(assgn.getLeft()[i]); ProverExpr right = expression2proverExpression(assgn.getRight()[i]); conj[i] = this.prover.mkEq(left, right); } return this.prover.mkAnd(conj); } else if (s instanceof CfgAssumeStatement) { CfgAssumeStatement assme = (CfgAssumeStatement) s; return expression2proverExpression(assme.getCondition()); } else if (s instanceof CfgHavocStatement) { // s Log.error("BUG: no havoc should be in the passive program!"); // Havoc is a no-op after SSA, so no need to keep it // in the transition relation return prover.mkLiteral(true); } else { //E.g. s instanceof CfgCallStatement throw new RuntimeException("Unknown statement type: " + s.getClass().toString()); } } /** * wraps an expression into an int-type expression using a cast TODO: only * implemented for boolean * * @param e * the expression * @param type * the type of the expression * @return a new expression casting e to int */ protected ProverExpr wrapInInt(ProverExpr e, BoogieType type) { if (type == null) throw new RuntimeException("wrapInInt has type null! Did you forget to run the typechecker?"); if (GlobalsCache.v().getProgramFactory()!=null && type == GlobalsCache.v().getProgramFactory().getBoolType()) return this.prover.mkIte(e, this.prover.mkLiteral(0), this.prover.mkLiteral(1)); else return e; } /** * casts expressions of Bool sort to Int expressions * * @param e * @param type * @return */ protected ProverExpr unwrapFromInt(ProverExpr e, BoogieType type) { if (type == null) throw new RuntimeException("wrapInInt has type null! Did you forget to run the typechecker? "+e.toString() ); if (GlobalsCache.v().getProgramFactory()!=null && type == GlobalsCache.v().getProgramFactory().getBoolType()) return this.prover.mkEq(e, this.prover.mkLiteral(0)); else return e; } protected ProverExpr expression2proverExpression(CfgExpression e) { return expression2proverExpression(e, new LinkedHashMap<CfgVariable, ProverExpr>()); } protected ProverExpr expression2proverExpression(CfgExpression e, LinkedHashMap<CfgVariable, ProverExpr> boundVariables) { if (e instanceof CfgArrayAccessExpression) { CfgArrayAccessExpression exp = (CfgArrayAccessExpression) e; ProverExpr ar = expression2proverExpression( exp.getBaseExpression(), boundVariables); ProverExpr[] indexes = new ProverExpr[exp.getIndices().length]; for (int i = 0; i < indexes.length; i++) { CfgExpression ind = exp.getIndices()[i]; indexes[i] = wrapInInt( expression2proverExpression(ind, boundVariables), ind.getType()); } return unwrapFromInt(this.prover.mkSelect(ar, indexes), e.getType()); } else if (e instanceof CfgArrayStoreExpression) { CfgArrayStoreExpression exp = (CfgArrayStoreExpression) e; ProverExpr ar = expression2proverExpression( exp.getBaseExpression(), boundVariables); ProverExpr[] indexes = new ProverExpr[exp.getIndices().length]; for (int i = 0; i < indexes.length; i++) { CfgExpression ind = exp.getIndices()[i]; indexes[i] = wrapInInt( expression2proverExpression(ind, boundVariables), ind.getType()); } CfgExpression val = exp.getValueExpression(); ProverExpr value = wrapInInt( expression2proverExpression(val, boundVariables), val.getType()); return this.prover.mkStore(ar, indexes, value); } else if (e instanceof CfgBinaryExpression) { CfgBinaryExpression exp = (CfgBinaryExpression) e; return binopExpression2proverExpression(exp, boundVariables); } else if (e instanceof CfgBooleanLiteral) { CfgBooleanLiteral exp = (CfgBooleanLiteral) e; return this.prover.mkLiteral(exp.getValue()); } else if (e instanceof CfgFunctionApplication) { CfgFunctionApplication exp = (CfgFunctionApplication) e; return functionApplication2proverExpression(exp, boundVariables); } else if (e instanceof CfgIdentifierExpression) { CfgIdentifierExpression exp = (CfgIdentifierExpression) e; return indentifierExpression2proverExpression(exp, boundVariables); } else if (e instanceof CfgIfThenElseExpression) { CfgIfThenElseExpression exp = (CfgIfThenElseExpression) e; return this.prover.mkIte( expression2proverExpression(exp.getCondition(), boundVariables), expression2proverExpression(exp.getThenExpression(), boundVariables), expression2proverExpression(exp.getElseExpression(), boundVariables)); } else if (e instanceof CfgIntegerLiteral) { CfgIntegerLiteral exp = (CfgIntegerLiteral) e; return this.prover.mkLiteral(exp.getValue().intValue()); } else if (e instanceof CfgQuantifierExpression) { CfgQuantifierExpression exp = (CfgQuantifierExpression) e; LinkedHashMap<CfgVariable, ProverExpr> boundVariables2 = new LinkedHashMap<CfgVariable, ProverExpr>(boundVariables); for (CfgVariable cfgvar : exp.getParameters()) { boundVariables2.put(cfgvar, createProverVar(cfgvar, 0)); } ProverExpr body = expression2proverExpression(exp.getSubformula(), boundVariables2); ProverType type = boogieType2ProverType(exp.getType()); if (exp.isUniversal()) { return this.prover.mkAll(body, type); } else { return this.prover.mkEx(body, type); } } else if (e instanceof CfgUnaryExpression) { CfgUnaryExpression exp = (CfgUnaryExpression) e; if (exp.getOperator() == boogie.enums.UnaryOperator.ARITHNEGATIVE) { return this.prover.mkMult( expression2proverExpression(exp.getExpression(), boundVariables), this.prover.mkLiteral(-1)); } else if (exp.getOperator() == boogie.enums.UnaryOperator.LOGICNEG) { return this.prover.mkNot(expression2proverExpression( exp.getExpression(), boundVariables)); } else { throw new RuntimeException("Unknown Unary Operator "+e); } } else { throw new RuntimeException("Unknown CfgExpression type " + e.getClass().toString()); } } private boolean insideOldExpression = false; protected ProverExpr binopExpression2proverExpression( CfgBinaryExpression exp, LinkedHashMap<CfgVariable, ProverExpr> boundVariables) { ProverExpr left = expression2proverExpression(exp.getLeftOp(), boundVariables); ProverExpr right = expression2proverExpression(exp.getRightOp(), boundVariables); // if (exp.getOperator() == boogie.enums.BinaryOperator.ARITHDIV) { // return this.prover.mkTDiv(left, right); if (exp.getOperator() == boogie.enums.BinaryOperator.ARITHMINUS) { return this.prover.mkMinus(left, right); // } else if (exp.getOperator() == boogie.enums.BinaryOperator.ARITHMOD) { // return this.prover.mkTMod(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.ARITHMUL) { return this.prover.mkMult(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.ARITHPLUS) { return this.prover.mkPlus(left, right); // } else if (exp.getOperator() == boogie.enums.BinaryOperator.BITVECCONCAT) { // throw new RuntimeException("BITVECCONCAT not imeplemented"); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPEQ) { return this.prover.mkEq(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPGEQ) { return this.prover.mkGeq(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPGT) { return this.prover.mkGt(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPLEQ) { return this.prover.mkLeq(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPLT) { return this.prover.mkLt(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPNEQ) { return this.prover.mkNot(this.prover.mkEq(left, right)); } else if (exp.getOperator() == boogie.enums.BinaryOperator.COMPPO) { ProverExpr[] args = { left, right }; ProverExpr pe = this.partialOrderOperator.mkExpr(args); return pe; } else if (exp.getOperator() == boogie.enums.BinaryOperator.LOGICAND) { return this.prover.mkAnd(left, right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.LOGICIFF) { ProverExpr l = this.prover.mkImplies(left, right); ProverExpr r = this.prover.mkImplies(right, left); return this.prover.mkAnd(l, r); } else if (exp.getOperator() == boogie.enums.BinaryOperator.LOGICIMPLIES) { return this.prover.mkOr(this.prover.mkNot(left), right); } else if (exp.getOperator() == boogie.enums.BinaryOperator.LOGICOR) { return this.prover.mkOr(left, right); } else { throw new RuntimeException("Unknown binary operator: " + exp.getOperator()); } } protected ProverExpr functionApplication2proverExpression( CfgFunctionApplication exp, LinkedHashMap<CfgVariable, ProverExpr> boundVariables) { String funname = sanitizeName(exp.getFunction().getIndentifier()); if (!this.proverFunctions.containsKey(funname)) { ProverType[] argTypes = new ProverType[exp.getFunction() .getInParams().length]; for (int i = 0; i < exp.getFunction().getInParams().length; i++) { argTypes[i] = boogieType2ProverType(exp.getFunction() .getInParams()[i].getType()); } ProverFun fun; CfgFunction cfgfun = this.controlFlowFactory.findCfgFunction(exp .getFunction().getIndentifier()); if (cfgfun != null && cfgfun.getBody() != null) { LinkedHashMap<CfgVariable, ProverExpr> localbound = new LinkedHashMap<CfgVariable, ProverExpr>(); int boundvarcounter = 0; for (CfgVariable invar : cfgfun.getInParams()) { localbound.put(invar, this.prover.mkBoundVariable( boundvarcounter++, boogieType2ProverType(invar.getType()))); } ProverExpr body = expression2proverExpression(cfgfun.getBody(), localbound); fun = this.prover.mkDefinedFunction(funname, argTypes, body); } else { fun = this.prover.mkUnintFunction(funname, argTypes, boogieType2ProverType(exp.getFunction().getOutParam() .getType())); } this.proverFunctions.put(funname, fun); } ProverFun fun = this.proverFunctions.get(funname); ProverExpr[] args = new ProverExpr[exp.getArguments().length]; for (int i = 0; i < exp.getArguments().length; i++) { args[i] = expression2proverExpression(exp.getArguments()[i], boundVariables); } return fun.mkExpr(args); } protected ProverExpr indentifierExpression2proverExpression( CfgIdentifierExpression exp, LinkedHashMap<CfgVariable, ProverExpr> boundVariables) { // First check if we are talking about a bound variable if (boundVariables.containsKey(exp.getVariable())) { return boundVariables.get(exp.getVariable()); } return createProverVar(exp.getVariable(), exp.getCurrentIncarnation()); } private ProverExpr createProverVar(CfgVariable var, int incarnation) { final BoogieType type = var.getType(); if (insideOldExpression) { incarnation = 0; } if (!this.proverVariables.containsKey(var)) { this.proverVariables.put(var, new TreeMap<Integer, ProverExpr>()); } if (!this.proverVariables.get(var).containsKey(incarnation)) { // don't add a ssa suffix if the incarnation in 0 String varname = sanitizeName(var.getVarname()) + ((incarnation == 0) ? "" : ("__" + incarnation)); ProverExpr newvar = this.prover.mkVariable(varname, boogieType2ProverType(type)); this.proverVariables.get(var).put(incarnation, newvar); this.invertProverVariables.put(newvar, var); this.invertIncarnationMap.put(newvar, incarnation); if (var.getParentEdges() != null && var.getParentEdges().size() > 0) { this.usedPOVariables.add(var); } } return this.proverVariables.get(var).get(incarnation); } /* * TODO: check if it is safe to do this In the prover, we treat references * as integers. TODO: Actually, we must not use SootPrelude types here, as * this part must work on generic Boogie programs without knowing anything * joogie-specific. */ protected ProverType boogieType2ProverType(BoogieType type) { ProgramFactory pf = GlobalsCache.v().getProgramFactory(); if (pf == null) { throw new RuntimeException(" bug "); } if (type == pf.getIntType()) { return this.prover.getIntType(); } else if (type == pf.getBoolType()) { return this.prover.getBooleanType(); } else if (type == pf.getRealType()) { // TODO return this.prover.getIntType(); } else if (type instanceof ArrayType) { ArrayType atype = (ArrayType) type; ProverType[] args = new ProverType[atype.getIndexCount()]; for (int i = 0; i < atype.getIndexCount(); i++) { args[i] = boogieType2ProverType(atype.getIndexType(i)); } return this.prover.getArrayType(args, boogieType2ProverType(atype.getValueType())); } else { //TOOD maybe we should distinguish other built-in types as well. } return this.prover.getIntType(); } protected String sanitizeName(String name) { return name; } }