public static bool Emit(this RuntimeContractEmitFlags have, RuntimeContractEmitFlags want)
 {
     return ((have & RuntimeContractEmitFlags.NoChecking) == 0) && (have & want) != 0;
 }
예제 #2
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;
    }
예제 #3
0
 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;
 }
예제 #4
0
 // 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;
   }
 }
예제 #5
0
 private bool Emit(RuntimeContractEmitFlags want)
 {
   return this.contractEmitFlags.Emit(want);
 }
예제 #6
0
    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;
      }
    }
예제 #7
0
    /// <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);
 }