@Override public AbstractState getVariableExpandedStateForProofChecking( AbstractState pRootState, Block pReducedContext, AbstractState pReducedState) { PredicateAbstractState rootState = (PredicateAbstractState) pRootState; PredicateAbstractState reducedState = (PredicateAbstractState) pReducedState; if (!reducedState.isAbstractionState()) { return reducedState; } AbstractionFormula rootAbstraction = rootState.getAbstractionFormula(); AbstractionFormula reducedAbstraction = reducedState.getAbstractionFormula(); // create region predicates for every atom in formula pamgr.extractPredicates(reducedAbstraction.asInstantiatedFormula()); Collection<AbstractionPredicate> rootPredicates = pamgr.extractPredicates(rootAbstraction.asInstantiatedFormula()); Collection<AbstractionPredicate> relevantRootPredicates = cpa.getRelevantPredicatesComputer().getRelevantPredicates(pReducedContext, rootPredicates); // for each removed predicate, we have to lookup the old (expanded) value and insert it to the // reducedStates region PathFormula oldPathFormula = reducedState.getPathFormula(); SSAMap oldSSA = oldPathFormula.getSsa(); // pathFormula.getSSa() might not contain index for the newly added variables in predicates; // while the actual index is not really important at this point, // there still should be at least _some_ index for each variable of the abstraction formula. SSAMapBuilder builder = oldSSA.builder(); SSAMap rootSSA = rootState.getPathFormula().getSsa(); for (String var : rootSSA.allVariables()) { // if we do not have the index in the reduced map.. if (!oldSSA.containsVariable(var)) { // add an index (with the value of rootSSA) builder.setIndex(var, rootSSA.getType(var), rootSSA.getIndex(var)); } } SSAMap newSSA = builder.build(); PathFormula newPathFormula = pmgr.makeNewPathFormula(pmgr.makeEmptyPathFormula(), newSSA); Region reducedRegion = pamgr.buildRegionFromFormula(reducedAbstraction.asFormula()); Region rootRegion = pamgr.buildRegionFromFormula(rootAbstraction.asFormula()); AbstractionFormula newAbstractionFormula = pamgr.expand( reducedRegion, rootRegion, relevantRootPredicates, newSSA, reducedAbstraction.getBlockFormula()); PersistentMap<CFANode, Integer> abstractionLocations = rootState.getAbstractionLocationsOnPath(); return PredicateAbstractState.mkAbstractionState( newPathFormula, newAbstractionFormula, abstractionLocations); }
@Override public AbstractState rebuildStateAfterFunctionCall( AbstractState pRootState, AbstractState pEntryState, AbstractState pExpandedState, FunctionExitNode exitLocation) { final PredicateAbstractState rootState = (PredicateAbstractState) pRootState; final PredicateAbstractState entryState = (PredicateAbstractState) pEntryState; final PredicateAbstractState expandedState = (PredicateAbstractState) pExpandedState; final PersistentMap<CFANode, Integer> abstractionLocations = expandedState.getAbstractionLocationsOnPath(); // TODO why did I copy the next if-statement? when is it used? if (!expandedState.isAbstractionState()) { return expandedState; } // we have: // - abstraction of rootState with ssa --> use as it is // - callEdge-pathFormula with ssa (from rootState) --> use as it is, with updated SSAMap // - abstraction of functioncall (expandedSSA) --> instantiate, with updated SSAMap, so // that: // - only param and return-var overlap to callEdge // - all other vars are distinct final String calledFunction = exitLocation.getFunctionName(); final PathFormula functionCall = entryState.getAbstractionFormula().getBlockFormula(); final SSAMap entrySsaWithRet = functionCall.getSsa(); final SSAMapBuilder entrySsaWithRetBuilder = entrySsaWithRet.builder(); final SSAMapBuilder summSsa = rootState.getAbstractionFormula().getBlockFormula().getSsa().builder(); final SSAMap expandedSSA = expandedState.getAbstractionFormula().getBlockFormula().getSsa(); for (String var : expandedSSA.allVariables()) { final CType type = expandedSSA.getType(var); if (var.startsWith(calledFunction + "::") && var.endsWith(PARAM_VARIABLE_NAME)) { int newIndex = entrySsaWithRet.getIndex(var); assert entrySsaWithRet.containsVariable(var) : "param for function is not used in functioncall"; entrySsaWithRetBuilder.setIndex(var, type, newIndex); setFreshValueBasis(summSsa, var, newIndex); } else if (exitLocation.getEntryNode().getReturnVariable().isPresent() && exitLocation.getEntryNode().getReturnVariable().get().getQualifiedName().equals(var)) { // var.startsWith(calledFunction + "::") && var.endsWith(RETURN_VARIABLE_NAME) final int newIndex = Math.max(expandedSSA.getIndex(var), entrySsaWithRetBuilder.getFreshIndex(var)); entrySsaWithRetBuilder.setIndex(var, type, newIndex); summSsa.setIndex(var, type, newIndex); } else if (!entrySsaWithRet.containsVariable(var)) { // non-existent index for variable only used in functioncall, just copy final int newIndex = expandedSSA.getIndex(var); entrySsaWithRetBuilder.setIndex(var, type, newIndex); summSsa.setIndex(var, type, newIndex); } else { final int newIndex = entrySsaWithRetBuilder.getFreshIndex(var); entrySsaWithRetBuilder.setIndex(var, type, newIndex); setFreshValueBasis(summSsa, var, newIndex); } } final SSAMap newEntrySsaWithRet = entrySsaWithRetBuilder.build(); final SSAMap newSummSsa = summSsa.build(); // function-call needs have new retvars-indices. PathFormula functionCallWithSSA = new PathFormula( functionCall.getFormula(), newEntrySsaWithRet, functionCall.getPointerTargetSet(), functionCall.getLength()); // concat function-call with function-summary, // function-summary will be instantiated with indices for params and retvars. PathFormula executedFunction = pmgr.makeAnd(functionCallWithSSA, expandedState.getAbstractionFormula().asFormula()); // after function-execution we have to re-use the previous indices (fromouter scope), // thus lets change the SSAmap. PathFormula executedFunctionWithSSA = new PathFormula( executedFunction.getFormula(), newSummSsa, executedFunction.getPointerTargetSet(), executedFunction.getLength()); // everything is prepared, so build a new AbstractionState. // we do this as 'future abstraction', because we do not have enough information // (necessary classes and managers) for the abstraction-process at this place. PredicateAbstractState rebuildState = new PredicateAbstractState.ComputeAbstractionState( executedFunctionWithSSA, rootState.getAbstractionFormula(), exitLocation, abstractionLocations); logger.log( Level.ALL, "\noldAbs: ", rootState.getAbstractionFormula().asInstantiatedFormula(), "\ncall: ", functionCallWithSSA, "\nsumm: ", expandedState.getAbstractionFormula().asFormula(), "\nexe: ", executedFunction, "\nentrySsaRet", newEntrySsaWithRet, "\nsummSsaRet", newSummSsa); return rebuildState; }