상속: Microsoft.Cci.MutableCodeModel.CodeRewriter
예제 #1
0
    internal static bool ReplacePushPopPattern(BlockStatement b, IMetadataHost host) {
      Contract.Requires(b != null);
      Contract.Requires(host != null);

      bool replacedPattern = false;
      var statements = b.Statements;
      for (int i = 0; i < statements.Count-1; i++) {
        //First identify count consecutive push statements
        int count = 0;
        while (i+count < statements.Count-1 && statements[i+count] is PushStatement) count++;
        if (count == 0) continue;
        Contract.Assert(i+count < statements.Count);
        Contract.Assert(count < statements.Count);
        for (int j = 0; j < count; j++) {
          Contract.Assume(statements[i+j] is PushStatement);
          if (((PushStatement)statements[i+j]).ValueToPush is DupValue) goto nextIteration;
        }
        Contract.Assert(i >= 0);
        Contract.Assert(i < statements.Count-1);
        //If any of the push statements (other than the first one) contains pop expressions, replace them with the corresponding push values and remove the pushes.
        int pushcount = 1; //the number of push statements that are eligble for removal at this point.
        for (int j = i + 1; j < i + count; j++) {
          Contract.Assume(j < statements.Count); //because i+count < statements.Count for the initial value of count and count just decreases
          Contract.Assume(j >= 0); //because i >= 0 and j never decreases to less than i
          Contract.Assume(statements[j] is PushStatement); //because i < j < i+count and i..i+count-1 are all push statements
          PushStatement st = (PushStatement)statements[j];
          PopCounter pcc = new PopCounter();
          pcc.Traverse(st.ValueToPush);
          int numberOfPushesToRemove = pushcount;
          if (pcc.count > 0) {
            if (pcc.count < numberOfPushesToRemove) numberOfPushesToRemove = pcc.count;
            int firstPushToRemove = j - numberOfPushesToRemove;
            PopReplacer prr = new PopReplacer(host, statements, firstPushToRemove, pcc.count-numberOfPushesToRemove);
            st.ValueToPush = prr.Rewrite(st.ValueToPush);
            statements.RemoveRange(firstPushToRemove, numberOfPushesToRemove);
            if (pcc.count > numberOfPushesToRemove) return true; //We've consumed all of the pushes and we're done.
            count -= numberOfPushesToRemove; //Fewer pushes now remain
            pushcount -= numberOfPushesToRemove; //Likewise fewer eligible pushes remain
            //Start over again at firstPushToRemove, which now indexes the first statement not yet considered.
            j = firstPushToRemove-1;
            continue;
          }
          pushcount++;
        }
        Contract.Assume(count >= 0);
        Contract.Assume(i+count < statements.Count);
        var nextStatement = statements[i + count];
        Contract.Assume(nextStatement != null);
        if (!(nextStatement is IExpressionStatement || nextStatement is IPushStatement || nextStatement is IReturnStatement || nextStatement is IThrowStatement)) continue;
        PopCounter pc = new PopCounter();
        pc.Traverse(nextStatement);
        if (pc.count == 0) continue;
        if (pc.count < count) {
          i += count-pc.count; //adjust i to point to the first push statement to remove because of subsequent pops.
          count = pc.count;
        }
        Contract.Assume(i < statements.Count);
        PopReplacer pr = new PopReplacer(host, statements, i, pc.count-count);
        pr.Rewrite(nextStatement);
        var s = nextStatement as Statement;
        if (s != null)
          s.Locations.AddRange(statements[i].Locations);
        Contract.Assume(count >= 0);
        Contract.Assert(i+count < statements.Count);
        statements.RemoveRange(i, count);
        replacedPattern = true;
      nextIteration: ;
      }
      return replacedPattern;
    }
예제 #2
0
        private void ReplacePushPopPattern(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 2)
            {
                return;
            }
            //First identify count consecutive push statements
            int count = 0;

            while (i + count < statements.Count - 1 && statements[i + count] is PushStatement)
            {
                count++;
            }
            while (i > 1 && statements[i - 1] is PushStatement)
            {
                i--; count++;
            }
            if (count == 0)
            {
                return;
            }
            for (int j = 0; j < count; j++)
            {
                if (((PushStatement)statements[j + i]).ValueToPush is Dup)
                {
                    return;
                }
            }
            //If any of the push statements (other than the first one) contains pop expressions, replace them with the corresponding push values and remove the pushes.
            int pushcount = 1; //the number of push statements that are eligble for removal at this point.

            for (int j = i + 1; j < i + count; j++)
            {
                PushStatement st  = (PushStatement)statements[j];
                PopCounter    pcc = new PopCounter();
                new CodeTraverser()
                {
                    PreorderVisitor = pcc
                }.Traverse(st.ValueToPush);
                int numberOfPushesToRemove = pushcount;
                if (pcc.count > 0)
                {
                    if (pcc.count < numberOfPushesToRemove)
                    {
                        numberOfPushesToRemove = pcc.count;
                    }
                    int         firstPushToRemove = j - numberOfPushesToRemove;
                    PopReplacer prr = new PopReplacer(this.sourceMethodBody.host, statements, firstPushToRemove, pcc.count - numberOfPushesToRemove);
                    st.ValueToPush = prr.Visit(st.ValueToPush);
                    statements.RemoveRange(firstPushToRemove, numberOfPushesToRemove);
                    j         = j - pcc.count;
                    count     = count - pcc.count;
                    pushcount = pushcount - pcc.count;
                }
                pushcount++;
            }
            //If the next statement is an expression statement that pops some of the just pushed values, replace those pops with the pushed values and remove the pushes.
            ExpressionStatement /*?*/ expressionStatement = statements[i + count] as ExpressionStatement;

            if (expressionStatement == null)
            {
                return;
            }
            PopCounter pc = new PopCounter();

            new CodeTraverser()
            {
                PreorderVisitor = pc
            }.Traverse(expressionStatement.Expression);
            if (pc.count == 0)
            {
                return;
            }
            if (pc.count < count)
            {
                i    += count - pc.count; //adjust i to point to the first push statement to remove because of subsequent pops.
                count = pc.count;
            }
            PopReplacer pr = new PopReplacer(this.sourceMethodBody.host, statements, i, pc.count - count);

            expressionStatement.Expression = pr.Visit(expressionStatement.Expression);
            expressionStatement.Locations.AddRange(statements[i].Locations);
            statements.RemoveRange(i, count);
        }
예제 #3
0
 private void ReplacePushPopPattern(List<IStatement> statements, int i)
 {
     if (i > statements.Count - 2) return;
       //First identify count consecutive push statements
       int count = 0;
       while (i+count < statements.Count-1 && statements[i+count] is PushStatement) count++;
       while (i > 1 && statements[i-1] is PushStatement) { i--; count++; }
       if (count == 0) return;
       for (int j = 0; j < count; j++) {
     if (((PushStatement)statements[j+i]).ValueToPush is Dup) return;
       }
       //If any of the push statements (other than the first one) contains pop expressions, replace them with the corresponding push values and remove the pushes.
       int pushcount = 1; //the number of push statements that are eligble for removal at this point.
       for (int j = i + 1; j < i + count; j++) {
     PushStatement st = (PushStatement)statements[j];
     PopCounter pcc = new PopCounter();
     new CodeTraverser() { PreorderVisitor = pcc }.Traverse(st.ValueToPush);
     int numberOfPushesToRemove = pushcount;
     if (pcc.count > 0) {
       if (pcc.count < numberOfPushesToRemove) numberOfPushesToRemove = pcc.count;
       int firstPushToRemove = j - numberOfPushesToRemove;
       PopReplacer prr = new PopReplacer(this.sourceMethodBody.host, statements, firstPushToRemove, pcc.count-numberOfPushesToRemove);
       st.ValueToPush = prr.Visit(st.ValueToPush);
       statements.RemoveRange(firstPushToRemove, numberOfPushesToRemove);
       j = j - pcc.count;
       count = count - pcc.count;
       pushcount = pushcount - pcc.count;
     }
     pushcount++;
       }
       //If the next statement is an expression statement that pops some of the just pushed values, replace those pops with the pushed values and remove the pushes.
       ExpressionStatement/*?*/ expressionStatement = statements[i + count] as ExpressionStatement;
       if (expressionStatement == null) return;
       PopCounter pc = new PopCounter();
       new CodeTraverser() { PreorderVisitor = pc }.Traverse(expressionStatement.Expression);
       if (pc.count == 0) return;
       if (pc.count < count) {
     i += count-pc.count; //adjust i to point to the first push statement to remove because of subsequent pops.
     count = pc.count;
       }
       PopReplacer pr = new PopReplacer(this.sourceMethodBody.host, statements, i, pc.count-count);
       expressionStatement.Expression = pr.Visit(expressionStatement.Expression);
       statements.RemoveRange(i, count);
 }