/// <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); }