/// <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); }
/// <summary> /// Examines a CFG and removes the stack manipulating instructions by introducing /// some explicit variables for stack locations. After this transformation, no more /// Pop, Dup etc. /// </summary> /// <param name="cfg">Control Flow Graph that is modified by the transformation. /// This argument WILL be mutated.</param> /// <returns>A map that assigns to each block from <c>cfg</c> the stack depth at its /// beginning. Useful as a pseudo-liveness information.</returns> public static int[] Process(ControlFlowGraph cfg) { StackRemovalTransformation sd = new StackRemovalTransformation(cfg); StackRemovalVisitor srv = new StackRemovalVisitor(); // should be in order. foreach (CfgBlock block in cfg.PreOrder) { int depth = sd.InitialDepthOfBlock(block, cfg); if (depth < 0) { continue; } // set block starting depth srv.depth = depth; StatementList stats = block.Statements; for(int i = 0, n = stats.Count; i < n; i++) { stats[i] = (Statement) srv.Visit(stats[i]); if (cfg.GenericsUse == null) { cfg.GenericsUse = srv.GenericsUse; } if (cfg.PointerUse == null) { cfg.PointerUse = srv.PointerUse; } if (srv.SawMissingInfo) { cfg.HasMissingInfo = true; } } // push final depth onto successors. foreach (CfgBlock succ in cfg.NormalSucc(block)) { sd.PushDepth(succ, srv.depth); } } // finalize stack depth info on each block foreach (CfgBlock block in cfg.Blocks()) { int depth = sd.block2depth[block.Index]; // cache depth on block block.stackDepth = depth; if (depth < 0) { // unreachable // set statementlist to null in case some backward analysis or other code gets to it if (block.Statements.Count > 0) { block.Statements = new StatementList(0); } } } return sd.block2depth; }
/// <summary> /// Examines a CFG and removes the stack manipulating instructions by introducing /// some explicit variables for stack locations. After this transformation, no more /// Pop, Dup etc. /// </summary> /// <param name="cfg">Control Flow Graph that is modified by the transformation. /// This argument WILL be mutated.</param> /// <returns>A map that assigns to each block from <c>cfg</c> the stack depth at its /// beginning. Useful as a pseudo-liveness information.</returns> public static int[] Process(ControlFlowGraph cfg) { StackRemovalTransformation sd = new StackRemovalTransformation(cfg); StackRemovalVisitor srv = new StackRemovalVisitor(); // should be in order. foreach (CfgBlock block in cfg.PreOrder) { int depth = sd.InitialDepthOfBlock(block, cfg); if (depth < 0) { continue; } // set block starting depth srv.depth = depth; StatementList stats = block.Statements; for (int i = 0, n = stats.Count; i < n; i++) { stats[i] = (Statement)srv.Visit(stats[i]); if (cfg.GenericsUse == null) { cfg.GenericsUse = srv.GenericsUse; } if (cfg.PointerUse == null) { cfg.PointerUse = srv.PointerUse; } if (srv.SawMissingInfo) { cfg.HasMissingInfo = true; } } // push final depth onto successors. foreach (CfgBlock succ in cfg.NormalSucc(block)) { sd.PushDepth(succ, srv.depth); } } // finalize stack depth info on each block foreach (CfgBlock block in cfg.Blocks()) { int depth = sd.block2depth[block.Index]; // cache depth on block block.stackDepth = depth; if (depth < 0) { // unreachable // set statementlist to null in case some backward analysis or other code gets to it if (block.Statements.Count > 0) { block.Statements = new StatementList(0); } } } return(sd.block2depth); }