public static Dictionary<CFGBlock, List<CFGBlock>> ComputeContainingLoopMap(ICFG cfg) { Contract.Requires(cfg != null); Contract.Ensures(Contract.Result<Dictionary<CFGBlock, List<CFGBlock>>>() != null); var result = new Dictionary<CFGBlock, List<CFGBlock>>(); var visitedSubroutines = new Set<int>(); var pendingSubroutines = new Stack<Subroutine>(); var pendingAPCs = new Stack<APC>(); var graph = cfg.AsBackwardGraph(includeExceptionEdges:false, skipContracts:true); foreach (var loophead in cfg.LoopHeads) { // push back-edge sources var loopPC = new APC(loophead, 0, null); foreach (var pred in cfg.Predecessors(loopPC)) { if (cfg.IsForwardBackEdge(pred, loopPC)) { var normalizedPred = new APC(pred.Block, 0, null); pendingAPCs.Push(normalizedPred); } } var visit = new DepthFirst.Visitor<APC, Unit>(graph, (APC pc) => { if (pc.SubroutineContext != null) { // push continuation PC pendingAPCs.Push(new APC(pc.SubroutineContext.Head.One, 0, null)); if (visitedSubroutines.AddQ(pc.Block.Subroutine.Id)) { pendingSubroutines.Push(pc.Block.Subroutine); } return false; // stop exploration } return !pc.Equals(loopPC); }); while (pendingAPCs.Count > 0) { var root = pendingAPCs.Pop(); visit.VisitSubGraphNonRecursive(root); while (pendingSubroutines.Count > 0) { var sub = pendingSubroutines.Pop(); pendingAPCs.Push(new APC(sub.Exit, 0, null)); } } foreach (var visited in visit.Visited) { if (visited.SubroutineContext != null) continue; // ignore non-primary pcs MaterializeContainingLoop(result, visited.Block).AssumeNotNull().Add(loophead); } } return result; }
private void FixpointComputation(APC entry, Postconditions initialState) { var todo = new List <Tuple <APC, Preconditions> >() { new Tuple <APC, Preconditions>(entry, initialState) }; var stable = new Set <APC>(); while (todo.Count != 0) { this.timeout.CheckTimeOut("backwards postcondition propagation"); var next = todo.ExtractFirst(); var nextPC = next.Item1; var nextState = next.Item2; var newPre = nextState; // do the block { APC pred; while (CFG.HasSinglePredecessor(nextPC, out pred) && !CFG.IsJoinPoint(nextPC)) { this.timeout.CheckTimeOut("backwards postcondition propagation (block)"); //var post = CFG.Predecessors(nextPC).First(); newPre = this.Mdriver.BackwardTransfer(nextPC, pred, newPre, this); // no pre, killing the path if (newPre == null) { break; } // TODO: check for contraddictions nextPC = pred; } } if (nextPC.Equals(CFG.EntryAfterRequires) || nextPC.Equals(CFG.Entry)) { this.invariants = newPre; continue; } var fixpointReached = false; if (CFG.IsJoinPoint(nextPC)) { Preconditions prev; if (this.joinPoints.TryGetValue(nextPC, out prev)) { newPre = Join(prev, newPre, CFG.IsForwardBackEdgeTarget(nextPC.Block.First), out fixpointReached); if (fixpointReached) { stable.Add(nextPC.Block.First); } } joinPoints[nextPC] = newPre; } // Split in the backwards analysis foreach (var pred in CFG.Predecessors(nextPC)) { if (fixpointReached && CFG.IsForwardBackEdge(pred, nextPC)) { continue; } if (this.Mdriver.IsUnreachable(nextPC)) { continue; } var transf = this.Mdriver.BackwardTransfer(nextPC, pred, newPre, this); if (transf != null) { todo.Add(new Tuple <APC, Preconditions>(pred, transf)); } } } }
public static Dictionary <CFGBlock, List <CFGBlock> > ComputeContainingLoopMap(ICFG cfg) { Contract.Requires(cfg != null); Contract.Ensures(Contract.Result <Dictionary <CFGBlock, List <CFGBlock> > >() != null); var result = new Dictionary <CFGBlock, List <CFGBlock> >(); var visitedSubroutines = new Set <int>(); var pendingSubroutines = new Stack <Subroutine>(); var pendingAPCs = new Stack <APC>(); var graph = cfg.AsBackwardGraph(includeExceptionEdges: false, skipContracts: true); foreach (var loophead in cfg.LoopHeads) { // push back-edge sources var loopPC = new APC(loophead, 0, null); foreach (var pred in cfg.Predecessors(loopPC)) { if (cfg.IsForwardBackEdge(pred, loopPC)) { var normalizedPred = new APC(pred.Block, 0, null); pendingAPCs.Push(normalizedPred); } } var visit = new DepthFirst.Visitor <APC, Unit>(graph, (APC pc) => { if (pc.SubroutineContext != null) { // push continuation PC pendingAPCs.Push(new APC(pc.SubroutineContext.Head.One, 0, null)); if (visitedSubroutines.AddQ(pc.Block.Subroutine.Id)) { pendingSubroutines.Push(pc.Block.Subroutine); } return(false); // stop exploration } return(!pc.Equals(loopPC)); }); while (pendingAPCs.Count > 0) { var root = pendingAPCs.Pop(); visit.VisitSubGraphNonRecursive(root); while (pendingSubroutines.Count > 0) { var sub = pendingSubroutines.Pop(); pendingAPCs.Push(new APC(sub.Exit, 0, null)); } } foreach (var visited in visit.Visited) { if (visited.SubroutineContext != null) { continue; // ignore non-primary pcs } MaterializeContainingLoop(result, visited.Block).AssumeNotNull().Add(loophead); } } return(result); }
public bool IsForwardBackEdge(APC from, APC to) { return(underlying.IsForwardBackEdge(from, to)); }