//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);
        }
Exemple #2
0
        public override Statement VisitReturn(Return Return)
        {
            if (Return == null) return null;

            WriteStart("return");

            if (Return.Expression != null)
            {
                Write(" ");
                this.VisitExpression(Return.Expression);
            }
            WriteFinish(";");
            return Return;
        }
Exemple #3
0
        //
        // Custom code generation for misc standard statements
        //
        public override Statement VisitReturn(Return Return)
        {
            if (Return == null) return null;
            if (Return.Expression == null) return null;

            Return.Expression = this.VisitExpression(Return.Expression);
            Statement zingReturn = Templates.GetStatementTemplate("SetReturnValue");
            Replacer.Replace(zingReturn, "_rval", Return.Expression);
            return zingReturn;
        }
 public virtual Statement VisitReturn(Return Return)
 {
     if (Return == null) return null;
     Return.Expression = this.VisitExpression(Return.Expression);
     return Return;
 }
 public override void VisitReturn(Return Return)
 {
     this.ReturnStatement = Return;
     base.VisitReturn(Return);
 }
Exemple #6
0
        public void AddAsyncPost(List<Ensures> asyncPostconditions)
        {
            var origBody = new Block(this.checkBody);
            origBody.HasLocals = true;

            var newBodyBlock = new Block(new StatementList());
            newBodyBlock.HasLocals = true;

            var methodBody = new StatementList();
            var methodBodyBlock = new Block(methodBody);
            methodBodyBlock.HasLocals = true;
            checkMethod.Body = methodBodyBlock;

            methodBody.Add(newBodyBlock);
            Block newExitBlock = new Block();
            methodBody.Add(newExitBlock);

            #region Map closure locals to fields and initialize closure fields

            foreach (Ensures e in asyncPostconditions)
            {
                if (e == null) continue;
                this.Visit(e);
                if (this.forwarder != null) { this.forwarder.Visit(e); }
                ReplaceResult repResult = new ReplaceResult(this.checkMethod, this.originalResultLocal, this.parent.assemblyBeingRewritten);
                repResult.Visit(e);
                // now need to initialize closure result fields
                foreach (var target in repResult.NecessaryResultInitializationAsync(this.closureLocals))
                {
                    // note: target here 
                    methodBody.Add(new AssignmentStatement(target, this.originalResultLocal));
                }
            }

            #endregion

            #region Emit normal postconditions

            SourceContext lastEnsuresSourceContext = default(SourceContext);
            bool hasLastEnsuresContext = false;
            bool containsExceptionalPostconditions = false;
            var ensuresChecks = new StatementList();
            foreach (Ensures e in asyncPostconditions)
            {
                // Exceptional postconditions are handled separately.
                if (e is EnsuresExceptional)
                {
                    containsExceptionalPostconditions = true;
                    continue;
                }

                if (IsVoidTask()) break; // something is wrong in the original contract

                lastEnsuresSourceContext = e.SourceContext;
                hasLastEnsuresContext = true;
                // call Contract.RewriterEnsures
                Method ensMethod = this.parent.runtimeContracts.EnsuresMethod;
                ExpressionList args = new ExpressionList();
                args.Add(e.PostCondition);
                if (e.UserMessage != null)
                    args.Add(e.UserMessage);
                else
                    args.Add(Literal.Null);
                if (e.SourceConditionText != null)
                {
                    args.Add(e.SourceConditionText);
                }
                else
                {
                    args.Add(Literal.Null);
                }
                ensuresChecks.Add(new ExpressionStatement(
                  new MethodCall(new MemberBinding(null, ensMethod),
                  args, NodeType.Call, SystemTypes.Void), e.SourceContext));
            }
            this.parent.cleanUpCodeCoverage.VisitStatementList(ensuresChecks);
            this.parent.EmitRecursionGuardAroundChecks(this.checkMethod, methodBodyBlock, ensuresChecks);
            #endregion Normal postconditions

            #region Exceptional postconditions
            if (containsExceptionalPostconditions)
            {
                // Because async tasks wrap exceptions into Aggregate exceptions, we have to catch AggregateException
                // and iterate over the internal exceptions of the Aggregate.

                // We thus emit the following handler:
                //
                //  catch(AggregateException ae) {
                //    ae.Handle(this.CheckException);
                //    rethrow;
                //  }
                //
                //  alternatively, if the Task has no Result, we emit
                //
                //    var ae = t.Exception as AggregateException;
                //    if (ae != null) {
                //      ae.Handle(this.CheckException);
                //      throw ae;
                //    }

                var aggregateType = AggregateExceptionType.Value;

                var exnParameter = new Parameter(Identifier.For("e"), SystemTypes.Exception);
                this.checkExceptionMethod = new Method(this.closureClass, null, this.checkExceptionMethodId, new ParameterList(exnParameter), SystemTypes.Boolean, new Block(new StatementList()));
                this.checkExceptionMethod.Body.HasLocals = true;
                checkExceptionMethod.CallingConvention = CallingConventionFlags.HasThis;
                checkExceptionMethod.Flags |= MethodFlags.Public;

                this.closureClass.Members.Add(checkExceptionMethod);

                if (this.IsVoidTask())
                {
                    var blockAfterTest = new Block();
                    methodBody.Add(origBody);
                    methodBody.Add(new Branch(new UnaryExpression(this.newResultLocal, NodeType.LogicalNot), blockAfterTest));
                    var funcType = Func2Type.Value;
                    funcType = funcType.GetTemplateInstance(this.parent.assemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);
                    var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                    var funcLocal = new Local(funcType);
                    var ldftn = new UnaryExpression(new MemberBinding(null, this.checkExceptionMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
                    methodBody.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)), new ExpressionList(this.checkMethod.ThisParameter, ldftn))));
                    methodBody.Add(new ExpressionStatement(new MethodCall(new MemberBinding(this.newResultLocal, handleMethod), new ExpressionList(funcLocal))));
                    methodBody.Add(new Throw(this.newResultLocal));
                    methodBody.Add(blockAfterTest);
                }
                else
                {
                    // The tryCatch holds the try block, the catch blocks, and an empty block that is the
                    // target of an unconditional branch for normal execution to go from the try block
                    // around the catch blocks.
                    if (this.checkMethod.ExceptionHandlers == null) this.checkMethod.ExceptionHandlers = new ExceptionHandlerList();

                    Block afterCatches = new Block(new StatementList());

                    Block tryCatch = newBodyBlock;
                    Block tryBlock = new Block(new StatementList());
                    tryBlock.Statements.Add(origBody);
                    tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
                    // the EH needs to have a pointer to this block so the writer can
                    // calculate the length of the try block. So it should be the *last*
                    // thing in the try body.
                    Block blockAfterTryBody = new Block(null);
                    tryBlock.Statements.Add(blockAfterTryBody);
                    tryCatch.Statements.Add(tryBlock);
                    // The catchBlock contains the catchBody, and then
                    // an empty block that is used in the EH.

                    Block catchBlock = new Block(new StatementList());
                    Local l = new Local(aggregateType);
                    Throw rethrow = new Throw();
                    rethrow.NodeType = NodeType.Rethrow;

                    catchBlock.Statements.Add(new AssignmentStatement(l, new Expression(NodeType.Pop)));

                    var funcType = Func2Type.Value;
                    funcType = funcType.GetTemplateInstance(this.parent.assemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);
                    var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                    var funcLocal = new Local(funcType);
                    var ldftn = new UnaryExpression(new MemberBinding(null, this.checkExceptionMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
                    catchBlock.Statements.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)), new ExpressionList(this.checkMethod.ThisParameter, ldftn))));
                    catchBlock.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(l, handleMethod), new ExpressionList(funcLocal))));
                    // Handle method should return if all passes
                    catchBlock.Statements.Add(rethrow);
                    // The last thing in each catch block is an empty block that is the target of
                    // BlockAfterHandlerEnd in each exception handler.
                    // It is used in the writer to determine the length of each catch block
                    // so it should be the last thing added to each catch block.
                    Block blockAfterHandlerEnd = new Block(new StatementList());
                    catchBlock.Statements.Add(blockAfterHandlerEnd);
                    tryCatch.Statements.Add(catchBlock);

                    // add information to the ExceptionHandlers of this method
                    ExceptionHandler exHandler = new ExceptionHandler();
                    exHandler.TryStartBlock = origBody;
                    exHandler.BlockAfterTryEnd = blockAfterTryBody;
                    exHandler.HandlerStartBlock = catchBlock;
                    exHandler.BlockAfterHandlerEnd = blockAfterHandlerEnd;
                    exHandler.FilterType = l.Type;
                    exHandler.HandlerType = NodeType.Catch;
                    this.checkMethod.ExceptionHandlers.Add(exHandler);

                    tryCatch.Statements.Add(afterCatches);
                }
                EmitCheckExceptionBody(asyncPostconditions);
            }
            else // no exceptional post conditions
            {
                newBodyBlock.Statements.Add(origBody);
            }
            #endregion Exceptional and finally postconditions


            #region Create a block for the return statement and insert it
            // this is the block that contains the return statements
            // it is (supposed to be) the single exit from the method
            // that way, anything that must always be done can be done
            // in this block
            Statement returnStatement;
            if (this.IsVoidTask())
            {
                returnStatement = new Return();
            }
            else
            {
                returnStatement = new Return(this.newResultLocal);
            }
            if (hasLastEnsuresContext)
            {
                returnStatement.SourceContext = lastEnsuresSourceContext;
            }
            Block returnBlock = new Block(new StatementList(1));
            returnBlock.Statements.Add(returnStatement);
            methodBody.Add(returnBlock);
            #endregion
        }
Exemple #7
0
    //[ContractVerification(true)]
    private void VisitMethodInternal(Method method) {
      if (method.IsAbstract || IsRewriterGenerated(method)) {
        return;
      }
      Block origBody = method.Body;
      if (origBody == null || origBody.Statements == null || origBody.Statements.Count == 0) return;

#if DEBUG
      if (!RewriteHelper.PostNormalizedFormat(method))
        throw new RewriteException("The method body for '" + method.FullName + "' is not structured correctly");
#endif


      #region Rewrite all Assert and Assume methods
      // Happens in-place so any modifications made are persisted even if nothing else is done to method

      RewriteAssertAssumeAndCallSiteRequires raa = new RewriteAssertAssumeAndCallSiteRequires(this.AssertAssumeRewriteMethodTable, this.runtimeContracts, this.contractEmitFlags, this, method);
      method.Body = raa.VisitBlock(method.Body);

      #endregion Rewrite all Assert and Assume methods (if user specified)

      #region Bail out early if publicSurfaceOnly and method is not visible (but not for contract validators!) or contract abbreviator
      if (this.runtimeContracts.PublicSurfaceOnly && !IsCallableFromOutsideAssembly(method) && !ContractNodes.IsValidatorMethod(method)
          || ContractNodes.IsAbbreviatorMethod(method)) return;
      #endregion

      int oldLocalUniqueNameCounter = 0;
      List<Block> contractInitializationBlocks = new List<Block>();
      Block postPreambleBlock = null;
      Dictionary<TypeNode, Local> closureLocals = new Dictionary<TypeNode, Local>();
      Block oldExpressionPreStateValues = new Block(new StatementList());
      #region Gather pre- and postconditions from supertypes and from method contract
      // Create lists of unique preconditions and postconditions.
      List<Requires> preconditions = new List<Requires>();
      List<Ensures> postconditions = new List<Ensures>();
      List<Ensures> asyncPostconditions = new List<Ensures>();
      RequiresList validations = null;
      // For postconditions, wrap all parameters within an old expression (if they are not already within one)
      var wrap = new WrapParametersInOldExpressions();
      EmitAsyncClosure asyncBuilder = null;

      #region Copy the method's contracts.
      if (method.Contract != null && (method.Contract.RequiresCount > 0 || method.Contract.EnsuresCount > 0 || 
                                      method.Contract.ValidationsCount > 0 || method.Contract.AsyncEnsuresCount > 0))
      {
        // Use duplicate of contract because it is going to get modified from processing Old(...) and
        // Result(). Can't have the modified contract get inherited (or else the Old(...) processing
        // will not work properly.)
        // Can't use MethodContract.CopyFrom or HelperMethods.DuplicateMethodBodyAndContract
        // because they assume the new contract is in a different method. Plus the latter duplicates
        // any closure classes needed for anonymous delegates in the contract.
        MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, method, this.runtimeContracts.ContractNodes, true);
        validations = mc.Validations;


        if (mc != null) {
          contractInitializationBlocks.Add(mc.ContractInitializer);
          postPreambleBlock = mc.PostPreamble;

          RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);

        }
      }
      #endregion Copy the method's contracts.
      #region Search the class hierarchy for overridden methods to propagate their contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.OverridesBaseClassMember && method.DeclaringType != null && method.OverriddenMethod != null) {
        for (TypeNode super = method.DeclaringType.BaseType; super != null; super = HelperMethods.DoesInheritContracts(super)?super.BaseType:null) {
          var baseMethod = super.GetImplementingMethod(method.OverriddenMethod, false);
          Method baseContractMethod = HelperMethods.GetContractMethod(baseMethod);
          if (baseContractMethod != null) {
            MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, baseContractMethod, this.runtimeContracts.ContractNodes, false);
            RewriteHelper.ReplacePrivateFieldsThatHavePublicProperties(method.DeclaringType, super, mc, this.rewriterNodes);
            if (mc != null) {
              contractInitializationBlocks.Add(mc.ContractInitializer);
              // can't have post preambles in overridden methods, since they cannot be constructors.

              // only add requires if baseMethod is the root method
              if (mc.Requires != null && baseMethod.OverriddenMethod == null)
              {
                foreach (RequiresPlain requires in mc.Requires) {
                  if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                  // Debug.Assert(!preconditions.Contains(requires));
                  preconditions.Add(requires);
                }
              }
              RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
            }
          }

          // bail out if this base type does not inherit contracts
          if (!HelperMethods.DoesInheritContracts(super)) break;
        }
      }
      #endregion Search the class hierarchy for overridden methods to propagate their contracts.
      #region Propagate explicit interface method contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.ImplementedInterfaceMethods != null) {
        foreach (Method interfaceMethod in method.ImplementedInterfaceMethods) {
          if (interfaceMethod != null)
          {
            Method contractMethod = HelperMethods.GetContractMethod(interfaceMethod);

            if (contractMethod != null)
            { // if null, then no contract for this interface method

              // Maybe it would be easier to just duplicate the entire method and then pull the
              // initialization code from the duplicate?
              MethodContract mc=HelperMethods.DuplicateContractAndClosureParts(method, contractMethod, this.runtimeContracts.ContractNodes, false);
              if (mc != null)
              {
                contractInitializationBlocks.Add(mc.ContractInitializer);
                // can't have post preambles in interface methods (not constructors)
                if (mc.Requires != null)
                {
                  foreach (RequiresPlain requires in mc.Requires)
                  {
                    if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                    // Debug.Assert(!preconditions.Contains(requires));
                    preconditions.Add(requires);
                  }
                }
                RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
              }
            }
          }
        }
      }
      #endregion Propagate explicit interface method contracts.
      #region Propagate implicit interface method contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.ImplicitlyImplementedInterfaceMethods != null) {
        foreach (Method interfaceMethod in method.ImplicitlyImplementedInterfaceMethods) {
          if (interfaceMethod != null) {
            Method contractMethod = HelperMethods.GetContractMethod(interfaceMethod);
            if (contractMethod != null)
            { // if null, then no contract for this method


              // Maybe it would be easier to just duplicate the entire method and then pull the
              // initialization code from the duplicate?
              MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, contractMethod, this.runtimeContracts.ContractNodes, false);
              if (mc != null)
              {
                contractInitializationBlocks.Add(mc.ContractInitializer);
                // can't have post preambles in implicit interface method implementations, as they are not constructors.
                if (mc.Requires != null)
                {
                  foreach (RequiresPlain requires in mc.Requires)
                  {
                    if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                    // Debug.Assert(!preconditions.Contains(requires));
                    preconditions.Add(requires);
                  }
                }
                RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
              }
            }
          }
        }
      }
      #endregion Propagate implicit interface method contracts.
      #endregion Gather pre- and postconditions from supertypes and from method contract


      #region Return if there is nothing to do
      if (preconditions.Count < 1 && postconditions.Count < 1 && asyncPostconditions.Count < 1 && (validations == null || validations.Count == 0) && this.InvariantMethod == null)
        return;
      #endregion Return if there is nothing to do

      #region Change all short branches to long because code modifications can add code
      {
        // REVIEW: This does *not* remove any short branches in the contracts.
        // I think that is okay, but we should think about it.
        RemoveShortBranches rsb = new RemoveShortBranches();
        rsb.VisitBlock(method.Body);
      }
      #endregion Change all short branches to long because code modifications can add code
      #region Modify method body to change all returns into assignments and branch to unified exit
      // now modify the method body to change all return statements
      // into assignments to the local "result" and a branch to a
      // block at the end that can check the post-condition using
      // "result" and then finally return it.
      // [MAF] we do it later once we know if the branches are leaves or just branch.
      Local result = null;
      if (!HelperMethods.IsVoidType(method.ReturnType)) {
        // don't write huge names. The debugger chokes on them and shows no locals at all.
        //   result = new Local(Identifier.For("Contract.Result<" + typeName + ">()"), method.ReturnType);
        result = new Local(Identifier.For("Contract.Result()"), method.ReturnType);
        if (method.LocalList == null) {
          method.LocalList = new LocalList();
        }
        method.LocalList.Add(result);
      }
      Block newExit = new Block(new StatementList());
      #endregion Modify method body to change all returns into assignments and branch to unified exit

      #region Create the new method's body
      Block newBody = new Block(new StatementList());
      newBody.HasLocals = true;

      #endregion Create the new method's body
      #region If there had been any closure initialization code, put it first in the new body
      if (0 < contractInitializationBlocks.Count) {
        foreach (Block b in contractInitializationBlocks) {
          newBody.Statements.Add(b);
        }
      }
      #endregion

      EmitInterleavedValidationsAndRequires(method, preconditions, validations, newBody);

      #region Turn off invariant checking until the end
      Local oldReEntrancyFlagLocal = null;
      if (MethodShouldHaveInvariantChecked(method) && this.ReentrancyFlag != null && BodyHasCalls(method.Body))
      {
        oldReEntrancyFlagLocal = new Local(SystemTypes.Boolean);
        newBody.Statements.Add(new Block(new StatementList(
          new AssignmentStatement(oldReEntrancyFlagLocal, new MemberBinding(method.ThisParameter, this.ReentrancyFlag)),
          new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), Literal.True))));
      }
      #endregion

      #region Put all of the collected initializations from "old" expressions into the method
      if (oldExpressionPreStateValues.Statements.Count > 0) {
        newBody.Statements.Add(oldExpressionPreStateValues);
      }
      #endregion

      // if there are preamble blocks we need to move them from the origBody in case we will wrap a try-catch
      var preambleIndex = 0;
      while (origBody.Statements.Count > preambleIndex && origBody.Statements[preambleIndex] is PreambleBlock) {
        newBody.Statements.Add(origBody.Statements[preambleIndex]);
        origBody.Statements[preambleIndex] = null;
        preambleIndex++;
      }
      Block newBodyBlock = new Block(new StatementList());
      newBody.Statements.Add(newBodyBlock); // placeholder for eventual body
      newBody.Statements.Add(newExit);

      #region Replace "result" in postconditions (both for method return and out parameters)
      if (result != null)
      {
        foreach (Ensures e in postconditions)
        {
          if (e == null) continue;
          ReplaceResult repResult = new ReplaceResult(method, result, this.assemblyBeingRewritten);
          repResult.Visit(e);
          // now need to initialize closure result fields
          foreach (var target in repResult.NecessaryResultInitialization(closureLocals))
          {
            newBody.Statements.Add(new AssignmentStatement(target, result));
          }
        }
      }
      #endregion

      #region Emit potential post preamble block (from contract duplicate) in constructors
      if (postPreambleBlock != null)
      {
        newBody.Statements.Add(postPreambleBlock);
      }
      #endregion

      #region Emit normal postconditions

      SourceContext lastEnsuresSourceContext = default(SourceContext);
      bool hasLastEnsuresContext = false;
      bool containsExceptionalPostconditions = false;
      var ensuresChecks = new StatementList();
      foreach (Ensures e in postconditions) {
        // Exceptional postconditions are handled separately.
        if (e is EnsuresExceptional) {
          containsExceptionalPostconditions = true;
          continue;
        }

        lastEnsuresSourceContext = e.SourceContext;
        hasLastEnsuresContext = true;
        // call Contract.RewriterEnsures
        Method ensMethod = this.runtimeContracts.EnsuresMethod;
        ExpressionList args = new ExpressionList();
        args.Add(e.PostCondition);
        if (e.UserMessage != null)
          args.Add(e.UserMessage);
        else
          args.Add(Literal.Null);
        if (e.SourceConditionText != null) {
          args.Add(e.SourceConditionText);
        } else {
          args.Add(Literal.Null);
        }
        ensuresChecks.Add(new ExpressionStatement(
          new MethodCall(new MemberBinding(null, ensMethod),
          args, NodeType.Call, SystemTypes.Void), e.SourceContext));
      }
      this.cleanUpCodeCoverage.VisitStatementList(ensuresChecks);
      EmitRecursionGuardAroundChecks(method, newBody, ensuresChecks);
      #endregion Normal postconditions

      #region Emit object invariant
      if (MethodShouldHaveInvariantChecked(method)) {
        // Now turn checking on by restoring old reentrancy flag
        if (this.ReentrancyFlag != null && oldReEntrancyFlagLocal != null) 
        {
          newBody.Statements.Add(new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), oldReEntrancyFlagLocal));
        }
        var callType = (method is InstanceInitializer) || this.InvariantMethod.DeclaringType.IsValueType ? NodeType.Call : NodeType.Callvirt;

        // just add a call to the already existing invariant method, "this.InvariantMethod();"
        // all of the processing needed is done as part of VisitClass
        newBody.Statements.Add(
          new ExpressionStatement(
          new MethodCall(
          new MemberBinding(method.ThisParameter, this.InvariantMethod), null, callType, SystemTypes.Void)));
      }
      #endregion Object invariant

      #region Emit exceptional postconditions

      ReplaceReturns rr;
      if (containsExceptionalPostconditions)
      {
        // -- The following code comes from System.Compiler.Normalizer.CreateTryCatchBlock --

        // The tryCatch holds the try block, the catch blocks, and an empty block that is the
        // target of an unconditional branch for normal execution to go from the try block
        // around the catch blocks.
        if (method.ExceptionHandlers == null) method.ExceptionHandlers = new ExceptionHandlerList();

        Block afterCatches = new Block(new StatementList());

        Block tryCatch = newBodyBlock;
        Block tryBlock = new Block(new StatementList());
        tryBlock.Statements.Add(origBody);
        rr = new ReplaceReturns(result, newExit, leaveExceptionBody:true);
        rr.Visit(origBody);

        tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
        // the EH needs to have a pointer to this block so the writer can
        // calculate the length of the try block. So it should be the *last*
        // thing in the try body.
        Block blockAfterTryBody = new Block(null);
        tryBlock.Statements.Add(blockAfterTryBody);
        tryCatch.Statements.Add(tryBlock);
        for (int i = 0, n = postconditions.Count; i < n; i++)
        {
          // Normal postconditions are handled separately.
          EnsuresExceptional e = postconditions[i] as EnsuresExceptional;
          if (e == null)
            continue;

          // The catchBlock contains the catchBody, and then
          // an empty block that is used in the EH.
          Block catchBlock = new Block(new StatementList());
          Local l = new Local(e.Type);
          Throw rethrow = new Throw();
          rethrow.NodeType = NodeType.Rethrow;

          // call Contract.RewriterEnsures
          ExpressionList args = new ExpressionList();
          args.Add(e.PostCondition);
          if (e.UserMessage != null)
            args.Add(e.UserMessage);
          else
            args.Add(Literal.Null);
          if (e.SourceConditionText != null)
          {
            args.Add(e.SourceConditionText);
          }
          else
          {
            args.Add(Literal.Null);
          }
          args.Add(l);
          var checks = new StatementList();
          checks.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(null, this.runtimeContracts.EnsuresOnThrowMethod),
            args, NodeType.Call, SystemTypes.Void), e.SourceContext));

          catchBlock.Statements.Add(new AssignmentStatement(l, new Expression(NodeType.Pop), e.SourceContext));
          this.cleanUpCodeCoverage.VisitStatementList(checks);
          EmitRecursionGuardAroundChecks(method, catchBlock, checks);

          #region Emit object invariant on EnsuresOnThrow check
          if (MethodShouldHaveInvariantChecked(method, inExceptionCase: true))
          {
            // Now turn checking on by restoring old reentrancy flag
            if (this.ReentrancyFlag != null && oldReEntrancyFlagLocal != null)
            {
              catchBlock.Statements.Add(new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), oldReEntrancyFlagLocal));
            }
            // just add a call to the already existing invariant method, "this.InvariantMethod();"
            // all of the processing needed is done as part of VisitClass
            catchBlock.Statements.Add(
              new ExpressionStatement(
              new MethodCall(
              new MemberBinding(method.ThisParameter, this.InvariantMethod), null, NodeType.Call, SystemTypes.Void)));
          }
          #endregion Object invariant

          catchBlock.Statements.Add(rethrow);
          // The last thing in each catch block is an empty block that is the target of
          // BlockAfterHandlerEnd in each exception handler.
          // It is used in the writer to determine the length of each catch block
          // so it should be the last thing added to each catch block.
          Block blockAfterHandlerEnd = new Block(new StatementList());
          catchBlock.Statements.Add(blockAfterHandlerEnd);
          tryCatch.Statements.Add(catchBlock);

          // add information to the ExceptionHandlers of this method
          ExceptionHandler exHandler = new ExceptionHandler();
          exHandler.TryStartBlock = origBody;
          exHandler.BlockAfterTryEnd = blockAfterTryBody;
          exHandler.HandlerStartBlock = catchBlock;
          exHandler.BlockAfterHandlerEnd = blockAfterHandlerEnd;
          exHandler.FilterType = l.Type;
          exHandler.HandlerType = NodeType.Catch;
          method.ExceptionHandlers.Add(exHandler);
        }
        tryCatch.Statements.Add(afterCatches);
      }
      else // no exceptional post conditions
      {
        newBodyBlock.Statements.Add(origBody);
        rr = new ReplaceReturns(result, newExit, leaveExceptionBody: false);
        rr.Visit(origBody);
      }
      #endregion Exceptional and finally postconditions

      #region Create a block for the return statement and insert it
      // this is the block that contains the return statements
      // it is (supposed to be) the single exit from the method
      // that way, anything that must always be done can be done
      // in this block
      Block returnBlock = new Block(new StatementList(1));

      if (asyncPostconditions != null && asyncPostconditions.Count > 0)
      {
          asyncBuilder.AddAsyncPost(asyncPostconditions);
          var funcLocal = new Local(asyncBuilder.FuncCtor.DeclaringType);
          var ldftn = new UnaryExpression(new MemberBinding(null, asyncBuilder.CheckMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
          returnBlock.Statements.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, asyncBuilder.FuncCtor), new ExpressionList(asyncBuilder.ClosureLocal, ldftn))));
          returnBlock.Statements.Add(new AssignmentStatement(result, new MethodCall(new MemberBinding(result, asyncBuilder.ContinueWithMethod), new ExpressionList(funcLocal))));
      }
      Statement returnStatement;
      if (!HelperMethods.IsVoidType(method.ReturnType)) {
        returnStatement = new Return(result);
      }
      else
      {
        returnStatement = new Return();
      }
      if (hasLastEnsuresContext)
      {
        returnStatement.SourceContext = lastEnsuresSourceContext;
      }
      else
      {
        returnStatement.SourceContext = rr.LastReturnSourceContext;
      }
      returnBlock.Statements.Add(returnStatement);
      newBody.Statements.Add(returnBlock);
      #endregion

      method.Body = newBody;

      #region Make sure InitLocals is marked for this method
      // 15 April 2003
      // Since each method has locals added to it, need to make sure this flag is
      // on. Otherwise, the generated code cannot pass peverify.
      if (!method.InitLocals) {
        method.InitLocals = true;
        //WriteToLog("Setting InitLocals for method: {0}", method.FullName);
      }
      #endregion
    }
Exemple #8
0
 public override Statement VisitReturn(Return Return)
 {
     if (Return == null) return null;
     return base.VisitReturn((Return)Return.Clone());
 }
Exemple #9
0
 private Return ParseReturn(TokenSet followers){
   this.sawReturnOrYield = true;
   Return Return = new Return();
   Return.SourceContext = this.scanner.CurrentSourceContext;
   Debug.Assert(this.currentToken == Token.Return);
   this.GetNextToken();
   if (this.currentToken != Token.Semicolon){
     Expression expr = Return.Expression = this.ParseExpression(followers|Token.Semicolon);
     if (expr != null)
       Return.SourceContext.EndPos = expr.SourceContext.EndPos;
   }
   this.SkipSemiColon(followers);
   return Return;
 }
Exemple #10
0
 public override Statement VisitReturn(Return ret)
 {
     this.lastBranchWasUnconditional = true;
     return ret;
 }
        private static Block CreateReturnBlock(Parameter checkPostTaskParameter, SourceContext? lastEnsuresSourceContext)
        {
            Statement returnStatement = new Return(checkPostTaskParameter);
            if (lastEnsuresSourceContext != null)
            {
                returnStatement.SourceContext = lastEnsuresSourceContext.Value;
            }

            Block returnBlock = new Block(new StatementList(1));
            returnBlock.Statements.Add(returnStatement);

            return returnBlock;
        }
Exemple #12
0
    /// <summary>
    /// 
    /// </summary>
    /// <param name="Return">Cloned</param>
    /// <returns></returns>
		public override Statement  VisitReturn(Return Return)
		{
			if (Return.Expression == null) return Return;

      Return = (Return)Return.Clone();
			Return.Expression = simplify(Return.Expression);
			return Return;
		}
            public override void VisitReturn(Return returnStatement)
            {
                Expression source = returnStatement.Expression;
                Construct sourceConstruct = source as Construct;

                if (sourceConstruct != null)
                {
                    if (sourceConstruct.Type != null && sourceConstruct.Type.Name.Name.StartsWith(this.closureTag))
                    {
                        if (sourceConstruct.Type.Template != null)
                        {
                            TypeNode template = sourceConstruct.Type.Template;
                            while (template.Template != null)
                            {
                                template = template.Template;
                            }

                            this.closureClass = (Class)template;
                        }
                        else
                        {
                            this.closureClass = (Class)sourceConstruct.Type;
                        }
                    }
                }
            }
Exemple #14
0
        public override Statement VisitReturn(Return Return)
        {
            if (Return == null) return null;

            if (insideAtomicBlock)
            {
                // If we're returning from inside an atomic block, we want to
                // have one block that leaves the atomic region (w/ atomic
                // level at zero), and a second block that performs the return.
                // The evaluation of the return expression must happen in the first block.
                // We use MiddleOfTransition to make sure this doesn't create
                // an additional state transition. The extra block is for the
                // benefit of the summarization code in the runtime.
                BasicBlock block = AddBlock(new BasicBlock(null));
                block.RelativeAtomicLevel = 0;

                BasicBlock extraBlock = AddBlock(new BasicBlock(Return, block));
                extraBlock.RelativeAtomicLevel = 0;
                extraBlock.MiddleOfTransition = true;
                CurrentContinuation = extraBlock;
            }
            else
            {
                BasicBlock block = AddBlock(new BasicBlock(Return));
                CurrentContinuation = block;
            }

            return Return;
        }
 public EventingVisitor(Action<Return> visitReturn) { VisitedReturn += visitReturn; } public event Action<Return> VisitedReturn; public override Statement VisitReturn(Return Return) { if (VisitedReturn != null) VisitedReturn(Return); return base.VisitReturn(Return); }