/// <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;
    }
Ejemplo n.º 2
0
        /// <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);
        }