Microsoft.Cci.ILToCodeModel.PopReplacer.Rewrite C# (CSharp) Method

Rewrite() public method

Do not replace pops in lambdas: they must not be confused with pops that are not within them.
public Rewrite ( IAnonymousDelegate anonymousDelegate ) : IExpression
anonymousDelegate IAnonymousDelegate
return IExpression
    public override IExpression Rewrite(IAnonymousDelegate anonymousDelegate) {
      return anonymousDelegate;
    }

Same methods

PopReplacer::Rewrite ( IExpression expression ) : IExpression

Usage Example

示例#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;
    }