//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); }
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; }
// // 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); }
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 }
//[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 }
public override Statement VisitReturn(Return Return) { if (Return == null) return null; return base.VisitReturn((Return)Return.Clone()); }
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; }
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; }
/// <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; } } } }
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); }