public static bool Emit(this RuntimeContractEmitFlags have, RuntimeContractEmitFlags want) { return ((have & RuntimeContractEmitFlags.NoChecking) == 0) && (have & want) != 0; }
private RuntimeContractEmitFlags AdaptRuntimeOptionsBasedOnAttributes(AttributeList attributeList) { var oldflags = this.contractEmitFlags; if (attributeList != null) { for (int i = 0; i < attributeList.Count; i++) { string category, setting; bool toggle; if (!HelperMethods.IsContractOptionAttribute(attributeList[i], out category, out setting, out toggle)) continue; if (string.Compare(category, "Contract", true) == 0) { if (string.Compare(setting, "Inheritance", true) == 0) { if (toggle) { this.contractEmitFlags |= RuntimeContractEmitFlags.InheritContracts; } else { this.contractEmitFlags &= ~(RuntimeContractEmitFlags.InheritContracts); } } } if (string.Compare(category, "Runtime", true) == 0) { if (string.Compare(setting, "Checking", true) == 0) { if (toggle) { this.contractEmitFlags &= ~(RuntimeContractEmitFlags.NoChecking); } else { this.contractEmitFlags |= RuntimeContractEmitFlags.NoChecking; } } } } } return oldflags; }
public RewriteAssertAssumeAndCallSiteRequires(Dictionary<Method, bool> replacementMethods, RuntimeContractMethods runtimeContracts, RuntimeContractEmitFlags emitFlags, Rewriter parent, Method containingMethod) { this.methodTable = replacementMethods; this.runtimeContracts = runtimeContracts; this.emitFlags = emitFlags; this.parent = parent; this.containingMethod = containingMethod; }
// Requires: // method.Body != null ==> // ForAll{Statement s in method.Body.Statements; // "BasicBlock"(s)}; public override void VisitMethod(Method method) { if (method == null) return; var savedEmitFlags = AdaptRuntimeOptionsBasedOnAttributes(method.Attributes); try { VisitMethodInternal(method); } finally { this.contractEmitFlags = savedEmitFlags; } }
private bool Emit(RuntimeContractEmitFlags want) { return this.contractEmitFlags.Emit(want); }
public override void VisitTypeNode(TypeNode typeNode) { if (typeNode == null) return; if (HelperMethods.IsContractTypeForSomeOtherType(typeNode, this.rewriterNodes) != null) { return; } Method savedInvariantMethod = this.InvariantMethod; Field savedReentrancyFlag = this.ReentrancyFlag; this.InvariantMethod = null; this.ReentrancyFlag = null; var savedState = this.currentState; this.currentState = new CurrentState(typeNode); var savedEmitFlags = this.AdaptRuntimeOptionsBasedOnAttributes(typeNode.Attributes); try { if (this.Emit(RuntimeContractEmitFlags.Invariants) && rewriterNodes.InvariantMethod != null) { InvariantList userWrittenInvariants = typeNode.Contract == null ? null : typeNode.Contract.Invariants; Class asClass = typeNode as Class; Field baseReentrancyFlag; Method baseInvariantMethod = FindAndInstantiateBaseClassInvariantMethod(asClass, out baseReentrancyFlag); if ((userWrittenInvariants != null && 0 < userWrittenInvariants.Count) || baseInvariantMethod != null) { Field reEntrancyFlag = null; var isStructWithExplicitLayout = IsStructWithExplicitLayout(typeNode as Struct); if (isStructWithExplicitLayout) { this.HandleError(new Warning(1044, String.Format("Struct '{0}' has explicit layout and an invariant. Invariant recursion guards will not be emitted and evaluation of invariants may occur too eagerly.", typeNode.FullName), new SourceContext())); } else { #region Find or create re-entrancy flag to the class if (baseReentrancyFlag != null) { // grab base reEntrancyFlag reEntrancyFlag = baseReentrancyFlag; } else { FieldFlags reentrancyFlagProtection; if (typeNode.IsSealed) { reentrancyFlagProtection = FieldFlags.Private | FieldFlags.CompilerControlled; } else if (this.InheritInvariantsAcrossAssemblies) { reentrancyFlagProtection = FieldFlags.Family | FieldFlags.CompilerControlled; } else { reentrancyFlagProtection = FieldFlags.FamANDAssem | FieldFlags.CompilerControlled; } reEntrancyFlag = new Field(typeNode, null, reentrancyFlagProtection, Identifier.For("$evaluatingInvariant$"), SystemTypes.Boolean, null); RewriteHelper.TryAddCompilerGeneratedAttribute(reEntrancyFlag); RewriteHelper.TryAddDebuggerBrowsableNeverAttribute(reEntrancyFlag); typeNode.Members.Add(reEntrancyFlag); } #endregion Add re-entrancy flag to the class } Block newBody = new Block(new StatementList(3)); // newBody ::= // if (this.$evaluatingInvariant$){ // return (true); // don't really return true since this is a void method, but it means the invariant is assumed to hold // this.$evaluatingInvariant$ := true; // try{ // <evaluate invariants and call base invariant method> // } finally { // this.$evaluatingInvariant$ := false; // } Method invariantMethod = new Method( typeNode, new AttributeList(), Identifier.For("$InvariantMethod$"), null, SystemTypes.Void, newBody); RewriteHelper.TryAddCompilerGeneratedAttribute(invariantMethod); invariantMethod.CallingConvention = CallingConventionFlags.HasThis; if (this.InheritInvariantsAcrossAssemblies) invariantMethod.Flags = MethodFlags.Family | MethodFlags.Virtual; else invariantMethod.Flags = MethodFlags.FamANDAssem | MethodFlags.Virtual; invariantMethod.Attributes.Add(new AttributeNode(new MemberBinding(null, this.runtimeContracts.ContractNodes.InvariantMethodAttribute.GetConstructor()), null)); #region call base class invariant if (baseInvariantMethod != null) { newBody.Statements.Add( new ExpressionStatement( new MethodCall( new MemberBinding(invariantMethod.ThisParameter, baseInvariantMethod), null, NodeType.Call, SystemTypes.Void))); } #endregion #region Add re-entrancy test to the method Block invariantExit = new Block(); if (reEntrancyFlag != null) { Block reEntrancyTest = new Block(new StatementList()); reEntrancyTest.Statements.Add( new Branch(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), invariantExit)); reEntrancyTest.Statements.Add( new AssignmentStatement(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), Literal.True) ); newBody.Statements.Add(reEntrancyTest); } #endregion Add re-entrancy test to the method Block invariantChecks = new Block(new StatementList()); if (userWrittenInvariants != null) { #region Filter out invariants that aren't runtime checkable var filteredInvariants = new InvariantList(); foreach (var i in userWrittenInvariants) { if (!EmitInvariant(i, this.skipQuantifiers)) continue; filteredInvariants.Add(i); } #endregion Filter out invariants that aren't runtime checkable #region Duplicate the invariants // need to duplicate the invariants so they aren't shared Duplicator d = new Duplicator(typeNode.DeclaringModule, typeNode); InvariantList duplicatedInvariants = d.VisitInvariantList(filteredInvariants); // F: seems to have the invariant duplictedInvariants != null Contract.Assume(duplicatedInvariants != null); #endregion Duplicate the invariants #region Rewrite the body of the invariant method // then we need to replace calls to Contract.Invariant with calls to Contract.RewriterInvariant // in the body of the invariant method RewriteInvariant rc = new RewriteInvariant(this.runtimeContracts); rc.VisitInvariantList(duplicatedInvariants); #endregion Rewrite the body of the invariant method for (int i = 0, n = duplicatedInvariants.Count; i < n; i++) { Expression e = duplicatedInvariants[i].Condition; var blockExpr = e as BlockExpression; if (blockExpr != null) { invariantChecks.Statements.Add(blockExpr.Block); } else { invariantChecks.Statements.Add(new ExpressionStatement(e)); } } } Block finallyB = new Block(new StatementList(1)); if (reEntrancyFlag != null) { finallyB.Statements.Add( new AssignmentStatement(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), Literal.False) ); } this.cleanUpCodeCoverage.VisitBlock(invariantChecks); Block b = RewriteHelper.CreateTryFinallyBlock(invariantMethod, invariantChecks, finallyB); newBody.Statements.Add(b); newBody.Statements.Add(invariantExit); newBody.Statements.Add(new Return()); // set the field "this.InvariantMethod" to this one so it is used in calls within each method // but don't add it yet to the class so it doesn't get visited! this.InvariantMethod = invariantMethod; this.ReentrancyFlag = reEntrancyFlag; } } base.VisitTypeNode(typeNode); // Now add invariant method to the class if (this.InvariantMethod != null) { typeNode.Members.Add(this.InvariantMethod); } return; } finally { this.InvariantMethod = savedInvariantMethod; this.ReentrancyFlag = savedReentrancyFlag; this.currentState = savedState; this.contractEmitFlags = savedEmitFlags; } }
/// <summary> /// For level, see TranslateLevel /// </summary> /// <param name="assemblyBeingRewritten"></param> /// <param name="rewriterNodes"></param> /// <param name="level"></param> public Rewriter(AssemblyNode assemblyBeingRewritten, RuntimeContractMethods runtimeContracts, Action<System.CodeDom.Compiler.CompilerError> handleError, bool inheritInvariantsAcrossAssemblies, bool skipQuantifiers) { Contract.Requires(handleError != null); // F: Contract.Requires(runtimeContracts != null); #region Find IDisposable.Dispose method TypeNode iDisposable = SystemTypes.IDisposable; if (iDisposable != null) { IDisposeMethod = iDisposable.GetMethod(Identifier.For("Dispose")); } #endregion this.runtimeContracts = runtimeContracts; this.assemblyBeingRewritten = assemblyBeingRewritten; this.rewriterNodes = runtimeContracts.ContractNodes; this.contractEmitFlags = TranslateLevel(this.runtimeContracts.RewriteLevel); this.contractEmitFlags |= RuntimeContractEmitFlags.InheritContracts; // default if (runtimeContracts.ThrowOnFailure) { this.contractEmitFlags |= RuntimeContractEmitFlags.ThrowOnFailure; } if (!runtimeContracts.UseExplicitValidation) { this.contractEmitFlags |= RuntimeContractEmitFlags.StandardMode; } this.m_handleError = handleError; this.InheritInvariantsAcrossAssemblies = inheritInvariantsAcrossAssemblies; this.skipQuantifiers = skipQuantifiers; }
public static bool Emit(this RuntimeContractEmitFlags have, RuntimeContractEmitFlags want) { return(((have & RuntimeContractEmitFlags.NoChecking) == 0) && (have & want) != 0); }