예제 #1
0
    /// <summary>
    /// Flattens the code of the method <c>method</c>.  Leaves the CCI representation of <c>method</c> intact.
    /// 
    /// Returns a mutated copy.
    /// 
    /// Important! don't forget to adjust handler block boundaries as well
    /// </summary>
    /// <param name="expandAllocations">When true, then Construct expressions are expanded into a separate allocation and separate
    /// constructor call.</param>
    /// <param name="constantFoldEvenInContracts">When <c>true</c>, use constant folding 
    /// to prune infeasible branches.</param>
    public static Method MakeFlat(Method method, bool expandAllocations, bool constantFold, out CodeMap codeMap)
    {
      /*
      Console.Out.WriteLine("+++++++++++++++++++++++++++");
      CodePrinter.PrintMethod(Console.Out, method);
      */

      #region Compensate for a bug involving re-initializing a method body
      {
        // We're going to muck with the method's Body. But then at one point the ExceptionHandlers
        // are evaluated and since that is null, it causes the Body to be re-initialized from the IL.
        // So just force some evaluations which fill in the backing stores to an empty list
        // (at least) instead of "null".
        // Do this for Body, Instructions, and ExceptionHandlers (the three things that cause
        // the ProvideBody delegate to execute).
        Block dummyBody = method.Body;
        InstructionList dummyInstructions = method.Instructions;
        ExceptionHandlerList dummyExceptions = method.ExceptionHandlers;
      }
      #endregion Compensate for a bug involving re-initializing a method body

      method = (Method)method.Clone();
      Block body = method.Body;

      if ((method == null) || (body == null)) {
        codeMap = null;
        return method;
      }

      // Add test case by inserting BlockExpressions and nested blocks
      // body = new FlattenerTest().VisitBlock(body);

      if(body.Statements == null) {
        codeMap = null;
        return method;
      }

      body = (Block)body.Clone();
      method.Body = body;

      CodeFlattener flatener = new CodeFlattener(method, expandAllocations, constantFold);

      flatener.FlattenBlock(body);

      flatener.AdjustBranches();

      flatener.AdjustHandlers(method);

      // now store the bodyList in the method body block

      body.Statements = flatener.new_blocks;

      /*
      Console.Out.WriteLine("---------------------------");
      CodePrinter.PrintMethod(Console.Out, method);
      Console.Out.WriteLine();
      */

      /*
      Console.WriteLine("----CodeFlattener on {0}", method.FullName);
      Console.WriteLine("orig blocks: {0}", flatener.orig2newBlocks.Count);
      Console.WriteLine("branches: {0}", flatener.branchInstructions.Length);
      */
      codeMap = new CodeMap(flatener.orig2Copy);
      return method;
    }
예제 #2
0
 /// <summary>
 /// Flattens the code of the method <c>method</c>.  Leaves the CCI representation of <c>method</c> intact.
 /// 
 /// Returns a mutated copy.
 /// 
 /// Important! don't forget to adjust handler block boundaries as well
 /// </summary>
 /// <param name="expandAllocations">When true, then Construct expressions are expanded
 /// into a separate allocation and separate constructor call.</param>
 public static Method MakeFlat(Method method, bool expandAllocations, out CodeMap codeMap) {
   return MakeFlat(method, expandAllocations, true, out codeMap);
 }