Exemple #1
0
        /// <summary>
        /// The abstract transition relation.
        /// 'cmd' is allowed to be a StateCmd.
        /// </summary>
        static NativeLattice.Element Step(NativeLattice lattice, Cmd cmd, NativeLattice.Element elmt)
        {
            Contract.Requires(lattice != null);
            Contract.Requires(cmd != null);
            Contract.Requires(elmt != null);
            Contract.Ensures(Contract.Result <NativeLattice.Element>() != null);

            if (cmd is AssignCmd)
            {
                // parallel assignment
                var c = (AssignCmd)cmd;
                elmt = lattice.Update(elmt, c.AsSimpleAssignCmd);
            }
            else if (cmd is HavocCmd)
            {
                var c = (HavocCmd)cmd;
                foreach (IdentifierExpr id in c.Vars)
                {
                    Contract.Assert(id != null);
                    elmt = lattice.Eliminate(elmt, id.Decl);
                }
            }
            else if (cmd is PredicateCmd)
            {
                var c         = (PredicateCmd)cmd;
                var conjuncts = new List <Expr>();
                foreach (var ee in Conjuncts(c.Expr))
                {
                    Contract.Assert(ee != null);
                    elmt = lattice.Constrain(elmt, ee);
                }
            }
            else if (cmd is StateCmd)
            {
                var c = (StateCmd)cmd;
                // Iterate the abstract transition on all the commands in the desugaring of the call
                foreach (Cmd callDesug in c.Cmds)
                {
                    Contract.Assert(callDesug != null);
                    elmt = Step(lattice, callDesug, elmt);
                }

                // Project out the local variables of the StateCmd
                foreach (Variable local in c.Locals)
                {
                    Contract.Assert(local != null);
                    elmt = lattice.Eliminate(elmt, local);
                }
            }
            else if (cmd is SugaredCmd)
            {
                var c = (SugaredCmd)cmd;
                elmt = Step(lattice, c.Desugaring, elmt);
            }
            else if (cmd is CommentCmd)
            {
                // skip
            }
            else
            {
                Contract.Assert(false); // unknown command
            }

            return(elmt);
        }
        public static void Analyze(Implementation impl, NativeLattice lattice, NativeLattice.Element start)
        {
            // We need to keep track of some information for each(some) block(s).  To do that efficiently,
              // we number the implementation's blocks sequentially, and then we can use arrays to store
              // the additional information.
              var pre = new NativeLattice.Element[impl.Blocks.Count];  // set to null if we never compute a join/widen at this block
              var post = CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere ? new NativeLattice.Element[impl.Blocks.Count] : null;
              var iterations = new int[impl.Blocks.Count];
              var bottom = lattice.Bottom;
              int n = 0;
              foreach (var block in impl.Blocks) {
            block.aiId = n;
            // Note:  The forward analysis below will store lattice elements in pre[n] if pre[n] is non-null.
            // Thus, the assignment "pre[n] = bottom;" below must be done under the following condition:
            //    n == 0 || block.widenBlock
            // One possible strategy would be to do it only under that condition.  Alternatively,
            // one could do the assignment under the following condition:
            //    n == 0 || block.widenBlock || block.Predecessors.Length != 1
            // (which would require first setting the Predecessors field).  In any case, if
            //    CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere
            // then all pre[n] should be set.
            pre[n] = bottom;
            n++;
              }
              Contract.Assert(n == impl.Blocks.Count);

              var workItems = new Queue<Tuple<Block, NativeLattice.Element>>();
              workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(impl.Blocks[0], start));
              //ComputeBlockInvariantsNative(impl, );
              // compute a fixpoint here
              while (workItems.Count > 0) {
            var workItem = workItems.Dequeue();
            var b = workItem.Item1;
            var id = b.aiId;
            var e = workItem.Item2;
            if (pre[id] == null) {
              // no pre information stored here, so just go ahead through the block
            } else if (lattice.Below(e, pre[id])) {
              // no change
              continue;
            } else if (b.widenBlock && CommandLineOptions.Clo.StepsBeforeWidening <= iterations[id]) {
              e = lattice.Widen(pre[id], e);
              pre[id] = e;
              iterations[id]++;
            } else {
              e = lattice.Join(pre[id], e);
              pre[id] = e;
              iterations[id]++;
            }

            // propagate'e' through b.Cmds
            foreach (Cmd cmd in b.Cmds) {
              e = Step(lattice, cmd, e);
            }

            if (post != null && pre[id] != null) {
              post[id] = e;
            }

            var g = b.TransferCmd as GotoCmd;
            if (g != null) {  // if g==null, it's a pity we didn't pay attention to that earlier, because then we could have skipped analyzing the code in this block
              foreach (Block succ in g.labelTargets) {
            workItems.Enqueue(new Tuple<Block, NativeLattice.Element>(succ, e));
              }
            }
              }

              Instrument(impl, pre, post);
        }
Exemple #3
0
        public static void Analyze(Implementation impl, NativeLattice lattice, NativeLattice.Element start)
        {
            // We need to keep track of some information for each(some) block(s).  To do that efficiently,
            // we number the implementation's blocks sequentially, and then we can use arrays to store
            // the additional information.
            var pre = new NativeLattice.Element[impl.Blocks
                                                .Count]; // set to null if we never compute a join/widen at this block
            var post = CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere
        ? new NativeLattice.Element[impl.Blocks.Count]
        : null;
            var iterations = new int[impl.Blocks.Count];
            var bottom     = lattice.Bottom;
            int n          = 0;

            foreach (var block in impl.Blocks)
            {
                block.aiId = n;
                // Note:  The forward analysis below will store lattice elements in pre[n] if pre[n] is non-null.
                // Thus, the assignment "pre[n] = bottom;" below must be done under the following condition:
                //    n == 0 || block.widenBlock
                // One possible strategy would be to do it only under that condition.  Alternatively,
                // one could do the assignment under the following condition:
                //    n == 0 || block.widenBlock || block.Predecessors.Length != 1
                // (which would require first setting the Predecessors field).  In any case, if
                //    CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere
                // then all pre[n] should be set.
                pre[n] = bottom;
                n++;
            }

            Contract.Assert(n == impl.Blocks.Count);

            var workItems = new Queue <Tuple <Block, NativeLattice.Element> >();

            workItems.Enqueue(new Tuple <Block, NativeLattice.Element>(impl.Blocks[0], start));
            //ComputeBlockInvariantsNative(impl, );
            // compute a fixpoint here
            while (workItems.Count > 0)
            {
                var workItem = workItems.Dequeue();
                var b        = workItem.Item1;
                var id       = b.aiId;
                var e        = workItem.Item2;
                if (pre[id] == null)
                {
                    // no pre information stored here, so just go ahead through the block
                }
                else if (lattice.Below(e, pre[id]))
                {
                    // no change
                    continue;
                }
                else if (b.widenBlock && CommandLineOptions.Clo.Ai.StepsBeforeWidening <= iterations[id])
                {
                    e       = lattice.Widen(pre[id], e);
                    pre[id] = e;
                    iterations[id]++;
                }
                else
                {
                    e       = lattice.Join(pre[id], e);
                    pre[id] = e;
                    iterations[id]++;
                }

                // propagate'e' through b.Cmds
                foreach (Cmd cmd in b.Cmds)
                {
                    e = Step(lattice, cmd, e);
                }

                if (post != null && pre[id] != null)
                {
                    post[id] = e;
                }

                var g = b.TransferCmd as GotoCmd;
                if (g != null)
                {
                    // if g==null, it's a pity we didn't pay attention to that earlier, because then we could have skipped analyzing the code in this block
                    foreach (Block succ in g.labelTargets)
                    {
                        workItems.Enqueue(new Tuple <Block, NativeLattice.Element>(succ, e));
                    }
                }
            }

            Instrument(impl, pre, post);
        }