コード例 #1
0
        /// <summary>
        ///
        /// </summary>
        public override void TraverseChildren(IMethodDefinition method)
        {
            if (TranslationHelper.HasAttribute(method, "BCTOmitAttribute"))
            {
                return;
            }

            if (method.IsStaticConstructor)
            {
                this.sawCctor = true;
            }

            bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));

            if (isEventAddOrRemove)
            {
                return;
            }


            Sink.ProcedureInfo procInfo;
            IMethodDefinition  stubMethod = null;

            if (IsStubMethod(method, out stubMethod))
            {
                procInfo = this.sink.FindOrCreateProcedure(stubMethod);
            }
            else
            {
                procInfo = this.sink.FindOrCreateProcedure(method);
            }

            if (method.IsAbstract || method.IsExternal || TranslationHelper.HasAttribute(method, "BCTOmitImplementationAttribute")
                // CCI is currently hacked to skip decompiling all method bodies in
                // compiler-generated classes.  This is nontrivial to test for here, so
                // just omit implementation of all methods whose bodies haven't been
                // decompiled, at risk of silently hiding other problems.
                || !(method.Body is ISourceMethodBody))
            {
                // we're done, just define the procedure
                return;
            }

            this.sink.BeginMethod(method);
            var decl      = procInfo.Decl;
            var proc      = decl as Bpl.Procedure;
            var formalMap = procInfo.FormalMap;

            if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey)
            {
                decl.AddAttribute("entrypoint");
            }

            try {
                StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

                // Manually set the beginning of the method as the source location for
                // BCT synthetic code until we traverse the first real statement, which
                // will automatically pick up its source location.  Needed for record
                // calls to show up in the trace.
                stmtTraverser.EmitSourceContext(method);

                if (!method.IsStatic)
                {
                    stmtTraverser.AddRecordCall("this",
                                                sink.CciTypeToBoogie(method.ContainingType),
                                                new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.ThisVariable));
                }

                #region Add assignments from In-Params to local-Params

                foreach (MethodParameter mparam in formalMap)
                {
                    if (mparam.inParameterCopy != null)
                    {
                        Bpl.IToken tok = method.Token();
                        Bpl.Expr   rhs = new Bpl.IdentifierExpr(tok, mparam.inParameterCopy);
                        stmtTraverser.AddRecordCall(mparam.underlyingParameter.Name.Value,
                                                    mparam.inParameterCopy.TypedIdent.Type, rhs);
                        stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
                                                                           new Bpl.IdentifierExpr(tok, mparam.outParameterCopy), rhs));
                    }
                }

                #endregion

                #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
                var inits = InitializeFieldsInConstructor(method);
                if (0 < inits.Count)
                {
                    foreach (var s in inits)
                    {
                        stmtTraverser.Traverse(s);
                    }
                }
                #endregion

                #region Translate method attributes
                // Don't need an expression translator because there is a limited set of things
                // that can appear as arguments to custom attributes
                // TODO: decode enum values
                try {
                    foreach (var a in method.Attributes)
                    {
                        var attrName = TypeHelper.GetTypeName(a.Type);
                        if (attrName.EndsWith("Attribute"))
                        {
                            attrName = attrName.Substring(0, attrName.Length - 9);
                        }
                        var args = new List <object>();
                        foreach (var c in a.Arguments)
                        {
                            var mdc = c as IMetadataConstant;
                            if (mdc != null)
                            {
                                object o;
                                if (mdc.Type.IsEnum)
                                {
                                    var lit = Bpl.Expr.Literal((int)mdc.Value);
                                    lit.Type = Bpl.Type.Int;
                                    o        = lit;
                                }
                                else
                                {
                                    switch (mdc.Type.TypeCode)
                                    {
                                    case PrimitiveTypeCode.Boolean:
                                        o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                                        break;

                                    case PrimitiveTypeCode.Int32:
                                        var lit = Bpl.Expr.Literal((int)mdc.Value);
                                        lit.Type = Bpl.Type.Int;
                                        o        = lit;
                                        break;

                                    case PrimitiveTypeCode.String:
                                        o = mdc.Value;
                                        break;

                                    default:
                                        throw new InvalidCastException("Invalid metadata constant type");
                                    }
                                }
                                args.Add(o);
                            }
                        }
                        decl.AddAttribute(attrName, args.ToArray());
                    }
                } catch (InvalidCastException) {
                    Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
                                      MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                    Console.WriteLine("    >>Skipping attributes, continuing with method translation");
                }
                #endregion

                #region Translate body
                var helperTypes = stmtTraverser.TranslateMethod(method);
                if (helperTypes != null)
                {
                    this.privateTypes.AddRange(helperTypes);
                }
                #endregion

                #region Create Local Vars For Implementation
                List <Bpl.Variable> vars = new List <Bpl.Variable>();
                foreach (MethodParameter mparam in formalMap)
                {
                    if (!mparam.underlyingParameter.IsByReference)
                    {
                        vars.Add(mparam.outParameterCopy);
                    }
                }
                foreach (Bpl.Variable v in this.sink.LocalVarMap.Values)
                {
                    vars.Add(v);
                }
                // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
                if (0 < this.sink.Options.modelExceptions)
                {
                    vars.Add(procInfo.LocalExcVariable);
                }
                vars.Add(procInfo.LabelVariable);
                List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray());
                #endregion

                var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

                #region Add implementation to Boogie program
                if (proc != null)
                {
                    Bpl.Implementation impl =
                        new Bpl.Implementation(method.Token(),
                                               decl.Name,
                                               new List <Bpl.TypeVariable>(),
                                               decl.InParams,
                                               decl.OutParams,
                                               vseq,
                                               translatedBody);

                    impl.Proc = proc;
                    this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
                }
                else // method is translated as a function
                //var func = decl as Bpl.Function;
                //Contract.Assume(func != null);
                //var blocks = new List<Bpl.Block>();
                //var counter = 0;
                //var returnValue = decl.OutParams[0];
                //foreach (var bb in translatedBody.BigBlocks) {
                //  var label = bb.LabelName ?? "L" + counter++.ToString();
                //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
                //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
                //    : bb.tc;
                //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
                //  blocks.Add(b);
                //}
                //var localVars = new List<Bpl.Variable>();
                //localVars.Add(returnValue);
                //func.Body = new Bpl.CodeExpr(localVars, blocks);
                {
                }
                #endregion
            } catch (TranslationException te) {
                Console.WriteLine("Translation error in body of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t" + te.Message + "\n" + te.StackTrace);
            } catch (Exception e) {
                Console.WriteLine("Error encountered during translation of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t>>" + e.Message + "\n" + e.StackTrace);
            } finally {
            }
        }
コード例 #2
0
        /// <summary>
        ///
        /// </summary>
        public override void TraverseChildren(IMethodDefinition method)
        {
            if (method.IsStaticConstructor)
            {
                this.sawCctor = true;
            }

            bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));

            if (isEventAddOrRemove)
            {
                return;
            }


            Sink.ProcedureInfo procInfo;
            IMethodDefinition  stubMethod = null;

            if (IsStubMethod(method, out stubMethod))
            {
                procInfo = this.sink.FindOrCreateProcedure(stubMethod);
            }
            else
            {
                procInfo = this.sink.FindOrCreateProcedure(method);
            }

            if (method.IsAbstract || method.IsExternal) // we're done, just define the procedure
            {
                return;
            }

            this.sink.BeginMethod(method);
            var decl      = procInfo.Decl;
            var proc      = decl as Bpl.Procedure;
            var formalMap = procInfo.FormalMap;

            if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey)
            {
                decl.AddAttribute("entrypoint");
            }

            // FEEDBACK inline handler methods to avoid more false alarms
            if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) &&
                !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method))
            {
                proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE));
                PhoneCodeHelper.instance().trackCallableMethod(proc);
            }

            try {
                StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

                // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null
                // FEEDBACK for modular analysis we need it to be non-null at the start
                // FEEDBACK also, callee is obviously non null
                IMethodDefinition translatedMethod = sink.getMethodBeingTranslated();
                if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& translatedMethod != null &&
                    PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod))
                {
                    // assign null to exception
                    List <Bpl.AssignLhs> assignee          = new List <Bpl.AssignLhs>();
                    Bpl.AssignLhs        exceptionAssignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable));
                    assignee.Add(exceptionAssignee);
                    List <Bpl.Expr> value = new List <Bpl.Expr>();
                    value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef));
                    Bpl.Cmd exceptionAssign = new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value);
                    stmtTraverser.StmtBuilder.Add(exceptionAssign);
                }

                #region Add assignments from In-Params to local-Params

                foreach (MethodParameter mparam in formalMap)
                {
                    if (mparam.inParameterCopy != null)
                    {
                        Bpl.IToken tok = method.Token();
                        stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
                                                                           new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
                                                                           new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
                    }
                }

                #endregion

                #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
                var inits = InitializeFieldsInConstructor(method);
                if (0 < inits.Count)
                {
                    foreach (var s in inits)
                    {
                        stmtTraverser.Traverse(s);
                    }
                }
                #endregion

                #region Translate method attributes
                // Don't need an expression translator because there is a limited set of things
                // that can appear as arguments to custom attributes
                // TODO: decode enum values
                try {
                    foreach (var a in method.Attributes)
                    {
                        var attrName = TypeHelper.GetTypeName(a.Type);
                        if (attrName.EndsWith("Attribute"))
                        {
                            attrName = attrName.Substring(0, attrName.Length - 9);
                        }
                        var args = new List <object>();
                        foreach (var c in a.Arguments)
                        {
                            var mdc = c as IMetadataConstant;
                            if (mdc != null)
                            {
                                object o;
                                if (mdc.Type.IsEnum)
                                {
                                    var lit = Bpl.Expr.Literal((int)mdc.Value);
                                    lit.Type = Bpl.Type.Int;
                                    o        = lit;
                                }
                                else
                                {
                                    switch (mdc.Type.TypeCode)
                                    {
                                    case PrimitiveTypeCode.Boolean:
                                        o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                                        break;

                                    case PrimitiveTypeCode.Int32:
                                        var lit = Bpl.Expr.Literal((int)mdc.Value);
                                        lit.Type = Bpl.Type.Int;
                                        o        = lit;
                                        break;

                                    case PrimitiveTypeCode.String:
                                        o = mdc.Value;
                                        break;

                                    default:
                                        throw new InvalidCastException("Invalid metadata constant type");
                                    }
                                }
                                args.Add(o);
                            }
                        }
                        decl.AddAttribute(attrName, args.ToArray());
                    }
                } catch (InvalidCastException) {
                    Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
                                      MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                    Console.WriteLine("    >>Skipping attributes, continuing with method translation");
                }
                #endregion

                #region Translate body
                var helperTypes = stmtTraverser.TranslateMethod(method);
                if (helperTypes != null)
                {
                    this.privateTypes.AddRange(helperTypes);
                }
                #endregion

                #region Create Local Vars For Implementation
                List <Bpl.Variable> vars = new List <Bpl.Variable>();
                foreach (MethodParameter mparam in formalMap)
                {
                    if (!mparam.underlyingParameter.IsByReference)
                    {
                        vars.Add(mparam.outParameterCopy);
                    }
                }
                foreach (Bpl.Variable v in this.sink.LocalVarMap.Values)
                {
                    vars.Add(v);
                }
                // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
                if (0 < this.sink.Options.modelExceptions)
                {
                    vars.Add(procInfo.LocalExcVariable);
                }
                vars.Add(procInfo.LabelVariable);
                List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray());
                #endregion

                var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

                #region Add implementation to Boogie program
                if (proc != null)
                {
                    Bpl.Implementation impl =
                        new Bpl.Implementation(method.Token(),
                                               decl.Name,
                                               new List <Bpl.TypeVariable>(),
                                               decl.InParams,
                                               decl.OutParams,
                                               vseq,
                                               translatedBody);

                    impl.Proc = proc;
                    this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
                }
                else // method is translated as a function
                //var func = decl as Bpl.Function;
                //Contract.Assume(func != null);
                //var blocks = new List<Bpl.Block>();
                //var counter = 0;
                //var returnValue = decl.OutParams[0];
                //foreach (var bb in translatedBody.BigBlocks) {
                //  var label = bb.LabelName ?? "L" + counter++.ToString();
                //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
                //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
                //    : bb.tc;
                //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
                //  blocks.Add(b);
                //}
                //var localVars = new List<Bpl.Variable>();
                //localVars.Add(returnValue);
                //func.Body = new Bpl.CodeExpr(localVars, blocks);
                {
                }
                #endregion
            } catch (TranslationException te) {
                Console.WriteLine("Translation error in body of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t" + te.Message);
            } catch (Exception e) {
                Console.WriteLine("Error encountered during translation of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t>>" + e.Message);
            } finally {
            }
        }
コード例 #3
0
    /// <summary>
    /// 
    /// </summary>
    public override void Visit(IMethodDefinition method) {

      Dictionary<IParameterDefinition, MethodParameter> formalMap = new Dictionary<IParameterDefinition, MethodParameter>();
      this.sink.BeginMethod();

      try {
        #region Create in- and out-parameters

        int in_count = 0;
        int out_count = 0;
        MethodParameter mp;
        foreach (IParameterDefinition formal in method.ResolvedMethod.Parameters) {

          mp = new MethodParameter(formal);
          if (mp.inParameterCopy != null) in_count++;
          if (mp.outParameterCopy != null && (formal.IsByReference || formal.IsOut))
            out_count++;
          formalMap.Add(formal, mp);
        }
        this.sink.FormalMap = formalMap;

        #region Look for Returnvalue

        // This is just a hack, should be replaced with something more robust
        if (method.Type.TypeCode != PrimitiveTypeCode.Void) {
          Bpl.Type rettype = Bpl.Type.Int;
          out_count++;
          this.sink.RetVariable = new Bpl.Formal(method.Token(),
              new Bpl.TypedIdent(method.Type.Token(),
                  "$result", rettype), false);
        } else {
          this.sink.RetVariable = null;
        }

        #endregion

        #region Create 'this' parameter
        in_count++;
        Bpl.Type selftype = Bpl.Type.Int;
        Bpl.Formal self = new Bpl.Formal(method.Token(),
            new Bpl.TypedIdent(method.Type.Token(),
                "this", selftype), true);

        #endregion

        Bpl.Variable[] invars = new Bpl.Formal[in_count];
        Bpl.Variable[] outvars = new Bpl.Formal[out_count];

        int i = 0;
        int j = 0;

        #region Add 'this' parameter as first in parameter
        invars[i++] = self;
        #endregion

        foreach (MethodParameter mparam in formalMap.Values) {
          if (mparam.inParameterCopy != null) {
            invars[i++] = mparam.inParameterCopy;
          }
          if (mparam.outParameterCopy != null) {
            if (mparam.underlyingParameter.IsByReference || mparam.underlyingParameter.IsOut)
              outvars[j++] = mparam.outParameterCopy;
          }
        }

        #region add the returnvalue to out if there is one
        if (this.sink.RetVariable != null) outvars[j] = this.sink.RetVariable;
        #endregion

        #endregion

        #region Check The Method Contracts
        Bpl.RequiresSeq boogiePrecondition = new Bpl.RequiresSeq();
        Bpl.EnsuresSeq boogiePostcondition = new Bpl.EnsuresSeq();
        Bpl.IdentifierExprSeq boogieModifies = new Bpl.IdentifierExprSeq();

        IMethodContract contract = ContractProvider.GetMethodContractFor(method);

        if (contract != null) {
          try {
            foreach (IPrecondition pre in contract.Preconditions) {
              ExpressionTraverser exptravers = this.factory.MakeExpressionTraverser(this.sink, null);
              exptravers.Visit(pre.Condition); // TODO
              // Todo: Deal with Descriptions


              Bpl.Requires req
                  = new Bpl.Requires(pre.Token(),
                      true, exptravers.TranslatedExpressions.Pop(), "");
              boogiePrecondition.Add(req);
            }

            foreach (IPostcondition post in contract.Postconditions) {
              ExpressionTraverser exptravers = this.factory.MakeExpressionTraverser(this.sink, null);

              exptravers.Visit(post.Condition);
              // Todo: Deal with Descriptions

              Bpl.Ensures ens =
                  new Bpl.Ensures(post.Token(),
                      true, exptravers.TranslatedExpressions.Pop(), "");
              boogiePostcondition.Add(ens);
            }

            foreach (IAddressableExpression mod in contract.ModifiedVariables) {
              ExpressionTraverser exptravers = this.factory.MakeExpressionTraverser(this.sink, null);
              exptravers.Visit(mod);

              Bpl.IdentifierExpr idexp = exptravers.TranslatedExpressions.Pop() as Bpl.IdentifierExpr;

              if (idexp == null) {
                throw new TranslationException(String.Format("Cannot create IdentifierExpr for Modifyed Variable {0}", mod.ToString()));
              }
              boogieModifies.Add(idexp);
            }
          } catch (TranslationException te) {
            throw new NotImplementedException("Cannot Handle Errors in Method Contract: " + te.ToString());
          } catch {
            throw;
          }
        }

        #endregion

        string MethodName = TranslationHelper.CreateUniqueMethodName(method);

        Bpl.Procedure proc = new Bpl.Procedure(method.Token(),
            MethodName, // make it unique!
            new Bpl.TypeVariableSeq(),
            new Bpl.VariableSeq(invars), // in
            new Bpl.VariableSeq(outvars), // out
            boogiePrecondition,
            boogieModifies,
            boogiePostcondition);

        this.sink.TranslatedProgram.TopLevelDeclarations.Add(proc);

        if (method.IsAbstract) {
          throw new NotImplementedException("abstract methods are not yet implemented");
        }

        StatementTraverser stmtTraverser = this.factory.MakeStatementTraverser(this.sink);

        #region Add assignements from In-Params to local-Params

        foreach (MethodParameter mparam in formalMap.Values) {
          if (mparam.inParameterCopy != null) {
            Bpl.IToken tok = method.Token();
            stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
              new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
              new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
          }
        }

        #endregion

        try {
          method.ResolvedMethod.Body.Dispatch(stmtTraverser);
        } catch (TranslationException te) {
          throw new NotImplementedException("No Errorhandling in Methodvisitor / " + te.ToString());
        } catch {
          throw;
        }

        #region Create Local Vars For Implementation
        List<Bpl.Variable> vars = new List<Bpl.Variable>();
        foreach (MethodParameter mparam in formalMap.Values) {
          if (!(mparam.underlyingParameter.IsByReference || mparam.underlyingParameter.IsOut))
            vars.Add(mparam.outParameterCopy);
        }
        foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) {
          vars.Add(v);
        }

        Bpl.VariableSeq vseq = new Bpl.VariableSeq(vars.ToArray());
        #endregion

        Bpl.Implementation impl =
            new Bpl.Implementation(method.Token(),
                MethodName, // make unique
                new Microsoft.Boogie.TypeVariableSeq(),
                new Microsoft.Boogie.VariableSeq(invars),
                new Microsoft.Boogie.VariableSeq(outvars),
                vseq,
                stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken));

        impl.Proc = proc;
        this.sink.TranslatedProgram.TopLevelDeclarations.Add(impl);
      } catch (TranslationException te) {
        throw new NotImplementedException(te.ToString());
      } catch {
        throw;
      } finally {
        // Maybe this is a good place to add the procedure to the toplevel declarations
      }
    }
コード例 #4
0
        private static void CreateDispatchMethod(Sink sink, ITypeDefinition type, HashSet <IMethodDefinition> delegates)
        {
            Contract.Assert(type.IsDelegate);
            IMethodDefinition invokeMethod = null;

            foreach (IMethodDefinition m in type.Methods)
            {
                if (m.Name.Value == "Invoke")
                {
                    invokeMethod = m;
                    break;
                }
            }

            try {
                IMethodDefinition  unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod;
                Sink.ProcedureInfo invokeProcedureInfo       = sink.FindOrCreateProcedure(unspecializedInvokeMethod);
                Bpl.Procedure      invokeProcedure           = (Bpl.Procedure)invokeProcedureInfo.Decl;
                invokeProcedure.AddAttribute("inline", Bpl.Expr.Literal(1));
                Bpl.Formal delegateVariable = invokeProcedureInfo.ThisVariable;
                Bpl.IToken token            = invokeMethod.Token();

                List <Bpl.Variable> dispatchProcInExprs = new List <Bpl.Variable>();
                for (int i = 1; i < invokeProcedure.InParams.Count; i++)
                {
                    Bpl.Variable v = invokeProcedure.InParams[i];
                    dispatchProcInExprs.Add(v);
                }
                List <Bpl.Variable> dispatchProcOutExprs = new List <Bpl.Variable>();
                foreach (Bpl.Variable v in invokeProcedure.OutParams)
                {
                    dispatchProcOutExprs.Add(v);
                }

                List <Bpl.Variable> localVariables = new List <Bpl.Variable>();
                Bpl.StmtListBuilder stmtBuilder    = new Bpl.StmtListBuilder();
                int localCounter = 0;
                foreach (IMethodDefinition defn in delegates)
                {
                    Bpl.Constant       c = sink.FindOrCreateDelegateMethodConstant(defn);
                    Sink.ProcedureInfo delegateProcedureInfo = sink.FindOrCreateProcedure(defn);
                    Bpl.Procedure      delegateProcedure     = (Bpl.Procedure)delegateProcedureInfo.Decl;
                    Bpl.Formal         thisVariable          = delegateProcedureInfo.ThisVariable;
                    int numArguments = defn.ParameterCount;

                    List <Bpl.Variable> tempInputs  = new List <Bpl.Variable>();
                    List <Bpl.Variable> tempOutputs = new List <Bpl.Variable>();

                    for (int i = 0; i < defn.ParameterCount; i++)
                    {
                        Bpl.Variable      v             = delegateProcedure.InParams[(thisVariable == null ? 0 : 1) + i];
                        Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken,
                                                                                new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type));
                        localVariables.Add(localVariable);
                        tempInputs.Add(localVariable);
                    }

                    for (int i = 0; i < delegateProcedure.OutParams.Count; i++)
                    {
                        Bpl.Variable      v             = delegateProcedure.OutParams[i];
                        Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken,
                                                                                new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type));
                        localVariables.Add(localVariable);
                        tempOutputs.Add(localVariable);
                    }

                    List <Bpl.Expr>           ins  = new List <Bpl.Expr>();
                    List <Bpl.IdentifierExpr> outs = new List <Bpl.IdentifierExpr>();
                    if (!defn.IsStatic)
                    {
                        ins.Add(sink.ReadReceiver(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)));
                    }
                    for (int i = 0; i < tempInputs.Count; i++)
                    {
                        ins.Add(Bpl.Expr.Ident(tempInputs[i]));
                    }
                    if (defn.IsGeneric)
                    {
                        for (int i = 0; i < defn.GenericParameterCount; i++)
                        {
                            ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken,
                                                     new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)),
                                                     new List <Bpl.Expr>(new Bpl.Expr[] { sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)) })));
                        }
                    }
                    if (defn.IsStatic)
                    {
                        int numTypeParameters = Sink.ConsolidatedGenericParameterCount(defn.ContainingType);
                        for (int i = 0; i < numTypeParameters; i++)
                        {
                            ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken,
                                                     new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)),
                                                     new List <Bpl.Expr>(new Bpl.Expr[] { sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)) })));
                        }
                    }
                    for (int i = 0; i < tempOutputs.Count; i++)
                    {
                        outs.Add(Bpl.Expr.Ident(tempOutputs[i]));
                    }

                    Bpl.Expr            bexpr         = sink.ReadMethod(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable));
                    Bpl.StmtListBuilder ifStmtBuilder = new Bpl.StmtListBuilder();
                    System.Diagnostics.Debug.Assert(tempInputs.Count == dispatchProcInExprs.Count);
                    if (tempInputs.Count > 0)
                    {
                        BuildAssignment(sink, ifStmtBuilder, tempInputs, dispatchProcInExprs);
                    }
                    ifStmtBuilder.Add(EmitDummySourceContext());
                    ifStmtBuilder.Add(new Bpl.CallCmd(token, delegateProcedure.Name, ins, outs));
                    System.Diagnostics.Debug.Assert(tempOutputs.Count == dispatchProcOutExprs.Count);
                    if (tempOutputs.Count > 0)
                    {
                        BuildAssignment(sink, ifStmtBuilder, dispatchProcOutExprs, tempOutputs);
                    }
                    stmtBuilder.Add(new Bpl.IfCmd(bexpr.tok, bexpr, ifStmtBuilder.Collect(bexpr.tok), null, null));
                }

                Bpl.Implementation dispatchImpl =
                    new Bpl.Implementation(token,
                                           invokeProcedure.Name,
                                           new List <Bpl.TypeVariable>(),
                                           invokeProcedure.InParams,
                                           invokeProcedure.OutParams,
                                           localVariables,
                                           stmtBuilder.Collect(token)
                                           );
                dispatchImpl.Proc = invokeProcedure;
                dispatchImpl.AddAttribute("inline", Bpl.Expr.Literal(1));
                sink.TranslatedProgram.AddTopLevelDeclaration(dispatchImpl);
            } catch (TranslationException te) {
                throw new NotImplementedException(te.ToString());
            } catch {
                throw;
            } finally {
                // Maybe this is a good place to add the procedure to the toplevel declarations
            }
        }
コード例 #5
0
    /// <summary>
    /// 
    /// </summary>
    public override void TraverseChildren(IMethodDefinition method) {

      if (method.IsStaticConstructor) this.sawCctor = true;

      bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));
      if (isEventAddOrRemove)
        return;


      Sink.ProcedureInfo procInfo;
      IMethodDefinition stubMethod = null;
      if (IsStubMethod(method, out stubMethod)) {
        procInfo = this.sink.FindOrCreateProcedure(stubMethod);
      } else {
        procInfo = this.sink.FindOrCreateProcedure(method);
      }

      if (method.IsAbstract || method.IsExternal) { // we're done, just define the procedure
        return;
      }

      this.sink.BeginMethod(method);
      var decl = procInfo.Decl;
      var proc = decl as Bpl.Procedure;
      var formalMap = procInfo.FormalMap;

      if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey) {
        decl.AddAttribute("entrypoint");
      }

      // FEEDBACK inline handler methods to avoid more false alarms
      if (PhoneCodeHelper.instance().PhoneFeedbackToggled && PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) &&
          !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method)) {
            proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE));
            PhoneCodeHelper.instance().trackCallableMethod(proc);
      }

      try {
        StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

        // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null
        // FEEDBACK for modular analysis we need it to be non-null at the start
        // FEEDBACK also, callee is obviously non null
        IMethodDefinition translatedMethod= sink.getMethodBeingTranslated();
        if (PhoneCodeHelper.instance().PhoneFeedbackToggled && translatedMethod != null &&
            PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod)) {
          // assign null to exception
          List<Bpl.AssignLhs> assignee= new List<Bpl.AssignLhs>();
          Bpl.AssignLhs exceptionAssignee= new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable));
          assignee.Add(exceptionAssignee);
          List<Bpl.Expr> value= new List<Bpl.Expr>();
          value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef));
          Bpl.Cmd exceptionAssign= new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value);
          stmtTraverser.StmtBuilder.Add(exceptionAssign);
        }

        #region Add assignments from In-Params to local-Params

        foreach (MethodParameter mparam in formalMap) {
          if (mparam.inParameterCopy != null) {
            Bpl.IToken tok = method.Token();
            stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
              new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
              new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
          }
        }

        #endregion

        #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
        var inits = InitializeFieldsInConstructor(method);
        if (0 < inits.Count) {
          foreach (var s in inits) {
            stmtTraverser.Traverse(s);
          }
        }
        #endregion

        #region Translate method attributes
        // Don't need an expression translator because there is a limited set of things
        // that can appear as arguments to custom attributes
        // TODO: decode enum values
        try {
          foreach (var a in method.Attributes) {
            var attrName = TypeHelper.GetTypeName(a.Type);
            if (attrName.EndsWith("Attribute"))
              attrName = attrName.Substring(0, attrName.Length - 9);
            var args = new List<object>();
            foreach (var c in a.Arguments) {
              var mdc = c as IMetadataConstant;
              if (mdc != null) {
                object o;
                if (mdc.Type.IsEnum) {
                  var lit = Bpl.Expr.Literal((int) mdc.Value);
                  lit.Type = Bpl.Type.Int;
                  o = lit;
                } else {
                  switch (mdc.Type.TypeCode) {
                    case PrimitiveTypeCode.Boolean:
                      o = (bool) mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                      break;
                    case PrimitiveTypeCode.Int32:
                      var lit = Bpl.Expr.Literal((int) mdc.Value);
                      lit.Type = Bpl.Type.Int;
                      o = lit;
                      break;
                    case PrimitiveTypeCode.String:
                      o = mdc.Value;
                      break;
                    default:
                      throw new InvalidCastException("Invalid metadata constant type");
                  }
                }
                args.Add(o);
              }
            }
            decl.AddAttribute(attrName, args.ToArray());
          }
        } catch (InvalidCastException) {
          Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
            MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
          Console.WriteLine("    >>Skipping attributes, continuing with method translation");
        }
        #endregion

        #region Translate body
        var helperTypes = stmtTraverser.TranslateMethod(method);
        if (helperTypes != null) {
          this.privateTypes.AddRange(helperTypes);
        }
        #endregion

        #region Create Local Vars For Implementation
        List<Bpl.Variable> vars = new List<Bpl.Variable>();
        foreach (MethodParameter mparam in formalMap) {
          if (!mparam.underlyingParameter.IsByReference)
            vars.Add(mparam.outParameterCopy);
        }
        foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) {
          vars.Add(v);
        }
        // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
        if (0 <this.sink.Options.modelExceptions)
          vars.Add(procInfo.LocalExcVariable);
        vars.Add(procInfo.LabelVariable);
        List<Bpl.Variable> vseq = new List<Bpl.Variable>(vars.ToArray());
        #endregion

        var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

        #region Add implementation to Boogie program
        if (proc != null) {
          Bpl.Implementation impl =
              new Bpl.Implementation(method.Token(),
                  decl.Name,
                  new List<Bpl.TypeVariable>(),
                  decl.InParams,
                  decl.OutParams,
                  vseq,
                  translatedBody);

          impl.Proc = proc;
          this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
        } else { // method is translated as a function
          //var func = decl as Bpl.Function;
          //Contract.Assume(func != null);
          //var blocks = new List<Bpl.Block>();
          //var counter = 0;
          //var returnValue = decl.OutParams[0];
          //foreach (var bb in translatedBody.BigBlocks) {
          //  var label = bb.LabelName ?? "L" + counter++.ToString();
          //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
          //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
          //    : bb.tc;
          //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
          //  blocks.Add(b);
          //}
          //var localVars = new List<Bpl.Variable>();
          //localVars.Add(returnValue);
          //func.Body = new Bpl.CodeExpr(localVars, blocks);
        }
        #endregion

      } catch (TranslationException te) {
        Console.WriteLine("Translation error in body of \n    '{0}':",
          MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
        Console.WriteLine("\t" + te.Message);
      } catch (Exception e) {
        Console.WriteLine("Error encountered during translation of \n    '{0}':",
          MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
        Console.WriteLine("\t>>" + e.Message);
      } finally {
      }
    }