public StronglyConnectedComponents (ControlFlowGraph cfg) { this.cfg = cfg; this.sccMap = null; IEnumerable/*<StronglyConnectedComponent<CfgBlock>>*/ all_sccs = StronglyConnectedComponent.ConstructSCCs(this.cfg.Blocks(), new BackwardGraphNavigator(this.cfg)); this.sccs = GraphUtil.TopologicallySortComponentGraph(DataStructUtil.DefaultSetFactory, all_sccs); }
/// <summary> /// Starts the analysis at the first instruction of the given block /// </summary> protected virtual void Run (ControlFlowGraph cfg, CfgBlock startBlock, IDataFlowState startState) { this.Reinitialize(cfg); pendingStates[startBlock.Index] = startState; joinWorkItems.Enqueue(startBlock); while (joinWorkItems.Count > 0) { //joinWorkItems.Dump(); CfgBlock currentBlock = joinWorkItems.Dequeue(); if (Analyzer.Debug) { Console.WriteLine("\n*** Working on block {0} [{1} statements, line {2}]\n", ((currentBlock).UniqueKey), currentBlock.Length, (currentBlock.Length == 0)? -1 : ((Statement)currentBlock[0]).SourceContext.StartLine); } // Flow the current state through the block. IDataFlowState currentState = PopPendingState(currentBlock); currentState = VisitBlock(currentBlock, currentState); // NOTE: VisitBlock may have explicitly pushed states onto some successors. In that case // it should return null to avoid this code pushing the same state onto all successors. if (currentState != null) { foreach (CfgBlock succ in currentBlock.NormalSuccessors) { PushState(currentBlock, succ, currentState); } } } //while }
/// <summary> /// Starts the analysis from the entry block of the CFG /// </summary> protected virtual void Run (ControlFlowGraph cfg, IDataFlowState startState) { this.Run(cfg, cfg.Entry, startState); }
private void Reinitialize (ControlFlowGraph cfg) { this.cfg = cfg; this.pendingStates = new IDataFlowState[cfg.BlockCount]; this.doneStates = new IDataFlowState[cfg.BlockCount]; // initialize work queue and disabled queue joinWorkItems = new WorkQueue(cfg.PreOrderCompare); }
/// <summary> /// Compute a pre order (ignoring back edges) of the CFG reachable from the entry node /// /// As a side effect, assigns each block its DF finishing number. /// </summary> public static FList/*<BasicBlocks>*/ Compute(ControlFlowGraph cfg) { // depth-first search bool[] markBit = new bool[cfg.BlockCount]; FList result = null; int DFTime = 0; // Use a stack to represent the state of the search. // Each stack element consists of a basic block and the // the index of the next successor of that block to process. Stack stack = new Stack(); CfgBlock[] blocks = cfg.Blocks(); CfgBlock start = cfg.Entry; // invariant: all blocks pushed on the stack are marked. markBit[start.Index] = true; stack.Push(new StackElem(start)); while (stack.Count > 0) { StackElem elem = (StackElem) stack.Peek(); CfgBlock b = elem.node; int nextChild = elem.nextChild; CfgBlock[] normalNodes = cfg.NormalSucc(b); CfgBlock[] exnNodes = cfg.ExcpSucc(b); int normalNodesCount = normalNodes.Length; int exnNodesCount = exnNodes.Length; // Is there another child to process? if (nextChild < normalNodesCount + exnNodesCount) { // Figure out the actual block. CfgBlock child; if (nextChild < normalNodesCount) { child = normalNodes[nextChild]; } else { child = exnNodes[nextChild-normalNodesCount]; } elem.nextChild = nextChild+1; // push the child block on to the stack. if (!markBit[child.Index]) { markBit[child.Index]=true; stack.Push(new StackElem(child)); } } else { // After all children are processed, place the block // on the result. stack.Pop(); b.priority = ++DFTime; result = FList.Cons(b, result); } } return result; }
public FinallyBlockDuplicator ( ControlFlowGraph cfg, Method method, IList/*<Block>*/ new_blocks, Hashtable/*<Block,Block>*/ block2next, NormalFlowBlockNavigator nfbnav, IList/*<ExceptionHandler>*/ all_ehs ) { this.dupVisitor = new DupVisitor(method.DeclaringType.DeclaringModule, method.DeclaringType); this.cfg = cfg; this.method = method; this.new_blocks = new_blocks; this.block2next = block2next; this.bnav = new UnionGraphNavigator(nfbnav, new ControlFlowGraph.ExcpFlowBlockNavigator(cfg)); this.allExceptionHandlers = all_ehs; // init the block -> index map this.b2index = new Hashtable(); StatementList blocks = method.Body.Statements; for(int i = 0; i < blocks.Count; i++) { b2index[(Block) blocks[i]] = i; } // init the exception handler -> last block map this.lastHandledBlock = new Hashtable(); foreach (ExceptionHandler eh in this.allExceptionHandlers) { if (eh.HandlerType != NodeType.Finally && eh.HandlerType != NodeType.FaultHandler) { continue; } this.lastHandledBlock[eh] = LastBlockInsideHandler(eh); } // 2. deal with the "leave" instructions TreatLeaveInstructions (); // 3. The original finally / fault handlers should be turned into catch handlers ConvertFinallyHandlerIntoCatchHandler(); }
internal void AssignIndex(ControlFlowGraph cfg, int index) { this.cfg = cfg; this.index = index; }
public static ControlFlowGraph Cast(ControlFlowGraph cfg) { return cfg; }
/// <summary> /// Get the CFG for a method. Results are cached, so getting the CFG for the same /// method twice will return the same CFG object. /// </summary> /// <param name="method">Method whose CFG we want to get.</param> /// <returns>CFG for <c>method</c>; cached.</returns> public virtual ControlFlowGraph ComputeControlFlowGraph (Method method) { ControlFlowGraph cfg = (ControlFlowGraph) method2cfg[method]; if (cfg == null) { cfg = new ControlFlowGraph(method); method2cfg.Add(method, cfg); } return cfg; }
public NormalFlowBlockNavigator(ControlFlowGraph parent, Hashtable/*<Block,Block>*/ block2next) { this.parent = parent; this.block2next = block2next; }
public ExcpFlowBlockNavigator(ControlFlowGraph parent) { this.parent = parent; }