예제 #1
0
        public override Statement VisitBranch(Branch branch)
        {
            if(branch == null)
                return null;

            if(branch.Target == null)
                return null;

            branch.Condition = this.VisitExpression(branch.Condition);

            int n = this.localsStack.top + 1;
            LocalsStack targetStack = (LocalsStack)this.StackLocalsAtEntry[branch.Target.UniqueKey];

            if(targetStack == null)
            {
                this.StackLocalsAtEntry[branch.Target.UniqueKey] = this.localsStack.Clone();
                return branch;
            }

            // Target block has an entry stack that is different from the current stack.  Need to copy stack
            // before branching.
            if(n <= 0)
                return branch; //Empty stack, no need to copy

            StatementList statements = new StatementList();

            this.localsStack.Transfer(targetStack, statements);
            statements.Add(branch);

            return new Block(statements);
        }
        public override void VisitBranch(Branch branch)
        {
            if (branch == null || branch.Target == null) return;

            if (branch.Target == branchTargetToReplace)
            {
                branch.Target = this.newBranchTarget;
                return;
            }

            base.VisitBranch(branch);
        }
예제 #3
0
        //public override Block VisitBlock(Block block) {
        //  if(block.Statements != null && block.Statements.Count == 1) {
        //    Return r = block.Statements[0] as Return;
        //    if(r != null) {
        //      Statement s = this.VisitReturn(r);
        //      Block retBlock = s as Block;
        //      if(retBlock != null) {
        //        block.Statements = retBlock.Statements;
        //        return block;
        //      } else {
        //        return base.VisitBlock(block);
        //      }
        //    } else {
        //      return base.VisitBlock(block);
        //    }
        //  } else {
        //    return base.VisitBlock(block);
        //  }
        //}

        public override Statement VisitReturn(Return Return)
        {
            if (Return == null)
            {
                return null;
            }

            returnCount++;
            this.lastReturnSourceContext = Return.SourceContext;

            StatementList stmts = new StatementList();

            Return.Expression = this.VisitExpression(Return.Expression);

            if (Return.Expression != null)
            {
                MethodCall mc = Return.Expression as MethodCall;
                if (mc != null && mc.IsTailCall)
                {
                    mc.IsTailCall = false;
                }

                var assgnmt = new AssignmentStatement(result, Return.Expression);

                assgnmt.SourceContext = Return.SourceContext;
                stmts.Add(assgnmt);
            }

            // the branch is a "leave" out of the try block that the body will be
            // in.
            var branch = new Branch(null, newExit, false, false, this.leaveExceptionBody);
            branch.SourceContext = Return.SourceContext;

            stmts.Add(branch);

            return new Block(stmts);
        }
예제 #4
0
    private static Statement WrapTryCatch(Method method, Statement statement)
    {
      Block afterCatches = new Block(new StatementList());
      Block tryBlock = new Block(new StatementList());
      Block blockAfterTryBody = new Block(null);
      tryBlock.Statements.Add(statement);
      tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
      tryBlock.Statements.Add(blockAfterTryBody);
      Block catchBlock = new Block(new StatementList());
      // emit code that pops the exception and fools fxcop
      Block branchTargetToFoolFxCop = new Block(null);
      var branch = new Branch(new Expression(NodeType.Pop), branchTargetToFoolFxCop);
      SourceContext hiddenContext = new SourceContext(HiddenDocument.Document);
      branch.SourceContext = hiddenContext;
      catchBlock.Statements.Add(branch);
      var rethrowStatement = new Throw();
      rethrowStatement.SourceContext = hiddenContext;
      rethrowStatement.NodeType = NodeType.Rethrow;
      catchBlock.Statements.Add(rethrowStatement);
      catchBlock.Statements.Add(branchTargetToFoolFxCop);
      var leave = new Branch(null, afterCatches, false, true, true);
      leave.SourceContext = hiddenContext;
      catchBlock.Statements.Add(leave);
      Block tryCatch = new Block(new StatementList());
      tryCatch.Statements.Add(tryBlock);
      tryCatch.Statements.Add(catchBlock);
      tryCatch.Statements.Add(afterCatches);

      if (method.ExceptionHandlers == null) method.ExceptionHandlers = new ExceptionHandlerList();

      ExceptionHandler exHandler = new ExceptionHandler();
      exHandler.TryStartBlock = tryBlock;
      exHandler.BlockAfterTryEnd = blockAfterTryBody;
      exHandler.HandlerStartBlock = catchBlock;
      exHandler.BlockAfterHandlerEnd = afterCatches;
      exHandler.FilterType = SystemTypes.Exception;
      exHandler.HandlerType = NodeType.Catch;
      method.ExceptionHandlers.Add(exHandler);

      return tryCatch;
    }
예제 #5
0
    private void EmitRecursionGuardAroundChecks(Method method, Block newBody, StatementList checks)
    {
      StatementList stmts = new StatementList();
      Block preconditionsStart = new Block(stmts);
      Block finallyStart = null;
      Block finallyEnd = new Block(); // branch target for skipping the checks

      // test if we are an auto property and need to disable the check if we are in construction
      if (this.ReentrancyFlag != null && (method.IsPropertyGetter || method.IsPropertySetter) && HelperMethods.IsAutoPropertyMember(method) && !method.IsStatic) {
        newBody.Statements.Add(new Branch(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), finallyEnd));
      }

      // don't add try finally if there are no precondition or if the method is a constructor (peverify issue)
      if (NeedsRecursionGuard(method, checks))
      {
        // emit recursion check
        finallyStart = new Block(new StatementList());

        // if (insideContractEvaluation > $recursionGuard$) goto finallyEnd
        // try {
        //   insideContractEvaluation++;
        //   checks;
        //   leave;
        // } finally {
        //   insideContractEvaluation--;
        // }
        //
        // SPECIAL CASE for auto properties where we made invariants into pre/post, we need to avoid the check if we are 
        // evaluating the invariant.
        //
        // if (this.$evaluatingInvariant || insideContractEvaluation > $recursionGuard$) goto finallyEnd
        // 

        newBody.Statements.Add(new Branch(new BinaryExpression(new MemberBinding(null, this.runtimeContracts.InContractEvaluationField), new Literal(this.runtimeContracts.RecursionGuardCountFor(method), SystemTypes.Int32), NodeType.Gt), finallyEnd));

        stmts.Add(new AssignmentStatement(new MemberBinding(null, this.runtimeContracts.InContractEvaluationField),
                                          new BinaryExpression(new MemberBinding(null, this.runtimeContracts.InContractEvaluationField), Literal.Int32One, NodeType.Add)));
        stmts.Add(new Block(checks));
        var leave = new Branch();
        leave.Target = finallyEnd;
        leave.LeavesExceptionBlock = true;
        stmts.Add(leave);
        
        finallyStart.Statements.Add(new AssignmentStatement(new MemberBinding(null, this.runtimeContracts.InContractEvaluationField),
                                    new BinaryExpression(new MemberBinding(null, this.runtimeContracts.InContractEvaluationField), Literal.Int32One, NodeType.Sub)));

        finallyStart.Statements.Add(new EndFinally());
      }
      else
      {
        stmts.Add(new Block(checks));
      }

      newBody.Statements.Add(preconditionsStart);
      if (finallyStart != null)
      {
        newBody.Statements.Add(finallyStart);
        var finallyHandler = new ExceptionHandler();
        finallyHandler.TryStartBlock = preconditionsStart;
        finallyHandler.BlockAfterTryEnd = finallyStart;
        finallyHandler.HandlerStartBlock = finallyStart;
        finallyHandler.BlockAfterHandlerEnd = finallyEnd;
        finallyHandler.HandlerType = NodeType.Finally;

        method.ExceptionHandlers.Add(finallyHandler);
      }
      // branch target for skipping the checks
      newBody.Statements.Add(finallyEnd);
    }
예제 #6
0
 public override void VisitBranch(Branch branch) {
   branch.ShortOffset = false;
 }
예제 #7
0
 public override Statement VisitBranch(Branch branch)
 {
     if (branch == null) return null;
     branch = (Branch)base.VisitBranch((Branch)branch.Clone());
     if (branch == null) return null;
     branch.Target = this.VisitBlock(branch.Target);
     return branch;
 }
예제 #8
0
 public override Statement VisitBranch(Branch branch)
 {
     throw new NotImplementedException("Node type not yet supported");
 }
예제 #9
0
		public override Statement  VisitBranch(Branch branch)
		{
      branch = (Branch)branch.Clone();

			// remember this statement on the list to adjust branches
			this.branchInstructions.Add(branch);

			if (branch.Condition == null) return branch;

      if (this.performConstantFoldingOnBranchConditions) {
        Literal l = AsConstant(branch.Condition);
        if (l != null) {
          if (Equals(l.Value, true) || Equals(l.Value, 1)) {
            branch.Condition = null;
            return branch;
          }
          if (Equals(l.Value, false) || Equals(l.Value, 0)) {
            return null;
          }
        }
      }
			branch.Condition = simplify(branch.Condition);
			return branch;
		}
예제 #10
0
 public SpecialBranch (Branch oldBranch, Block target) : base(null, target) {
   this.LeavesExceptionBlock = oldBranch.LeavesExceptionBlock;
   this.SourceContext = oldBranch.SourceContext;
 }
예제 #11
0
      // The "leave" instruction block.Statements[i] is replaced with a branch instruction
      // to a ChainBlocks of duplicated finally blocks (which are now normal blocks) that finally
      // arrives in the original branch target.
      private void ProcessLeave (Block block, int i, Branch leave) {
        Debug.Assert(block != null);
        Debug.Assert(block.Statements[i] is Branch && ((Branch)block.Statements[i]).LeavesExceptionBlock);
        //Console.Out.WriteLine("process leave from " + CodePrinter.b2s(block) + "," + i);

        Block originalLeaveTarget = ((Branch) block.Statements[i]).Target;
        // 1. find the list of all finally blocks "traversed" by the branch
        IEnumerable/*<ExceptionHandler>*/ list_finally = GetFinallyHandlersForLeave(block, i);

        // 2. duplicate and ChainBlocks them with jumps between them
        Block modBlock = block;
        int   modIndex = i; // the modIndex'th instruction of modBlock will be replaced with a "chaining" Branch
        bool isFirstHandler = true;
        Block firstBlockInFinally, lastBlockInFinally;

        foreach(ExceptionHandler eh in list_finally) {
          DuplicateFinallyBody(eh, block, out firstBlockInFinally, out lastBlockInFinally);

          Debug.Assert(firstBlockInFinally != null && lastBlockInFinally != null);

          ChainBlocks(modBlock, modIndex, firstBlockInFinally, isFirstHandler);

          isFirstHandler = false;
          modBlock = lastBlockInFinally;
        }
        ChainBlocks(modBlock, modIndex, originalLeaveTarget, isFirstHandler);

#if DEBUGxxx
        Console.WriteLine();
        Console.WriteLine("-------------------------------------------------------------");
        Console.WriteLine();
        SimpleDisplay(Console.Out, this.method); 
        Console.WriteLine("NEW:");
        foreach (Block b in new_blocks)
        {
          SimpleDisplay(Console.Out, b, null);
        }
#endif        
      }
예제 #12
0
 public override Statement VisitBranch(Branch branch) {
   if (branch == null) return null;
   return ((Branch)branch.Clone());
 }
예제 #13
0
 public override Statement VisitBranch(Branch branch) {
   // update the branch target for non-leave branches
   if ( ! branch.LeavesExceptionBlock || branch is SpecialBranch) {
     branch.Target = get_new_target(branch.Target);
   }
   return branch;
 }
예제 #14
0
        public override Statement VisitBranch(Branch branch)
        {
            if (branch == null) return null;
            if (branch.Condition != null)
                throw new InvalidOperationException("Unexpected branch condition in BBSplitter");

            // Check to see if a basic block has been created for this target yet
            BasicBlock bbTarget = (BasicBlock)branchTargets[branch.Target.UniqueKey];

            // If not, create one now and register it in branchTargets
            if (bbTarget == null)
            {
                bbTarget = new BasicBlock(null);
                AddBlock(bbTarget);
                bbTarget.SourceContext = branch.SourceContext;
                bbTarget.MiddleOfTransition = true;
                branchTargets[branch.Target.UniqueKey] = bbTarget;
            }

            #if false
            // Note: this optimization was overly aggressive because it assumes that branch targets
            // fall within the current atomic block. If not, then we need an extra "branch" block
            // which can be the end of the atomic block.

            if (this.insideAtomicBlock)
            {
                // We don't need a basic block for the branch itself. We just redirect the
                // CurrentContinuation to the target of the branch.

                CurrentContinuation = bbTarget;
            }
            else
            #endif
            {
                // If we aren't in an atomic block, we can't optimize away the block for the
                // goto itself.
                BasicBlock branchBlock = new BasicBlock(null, bbTarget);
                AddBlock(branchBlock);
                branchBlock.SourceContext = branch.SourceContext;
                CurrentContinuation = branchBlock;

                // Remember this branch if it happens to be inside an atomic block. If the
                // target is *not* within the atomic block, then we'll need to do some
                // fixup work later.
                if (this.insideAtomicBlock)
                    atomicBranches.Add(branchBlock);
            }

            return branch;
        }
예제 #15
0
 public virtual Statement VisitBranch(Branch branch)
 {
     if (branch == null) return null;
     branch.Condition = this.VisitExpression(branch.Condition);
     return branch;
 }
예제 #16
0
 public override Statement VisitBranch(Branch branch)
 {
     if (branch == null) return null;
     if (branch.Target == null) return null;
     this.VisitBlock(branch.Target);
     this.lastBranchWasUnconditional = branch.Condition == null;
     return branch;
 }
예제 #17
0
 public override Statement VisitBranch(Branch branch)
 {
     Debug.Assert(false, "Unexpected Branch node in Normalizer");
     return null;
 }
예제 #18
0
 public EventingVisitor(Action<Branch> visitBranch) { VisitedBranch += visitBranch; } public event Action<Branch> VisitedBranch; public override Statement VisitBranch(Branch branch) { if (VisitedBranch != null) VisitedBranch(branch); return base.VisitBranch(branch); }