Пример #1
0
        protected override ProgTransformation.PersistentProgram recordOutput(Program p)
        {
            CBAProgram ap = p as CBAProgram;

            Debug.Assert(ap != null);

            return(ap.getPersistentVersion());
        }
Пример #2
0
        public override CBAProgram runCBAPass(CBAProgram inp)
        {
            if (cp == null)
            {
                return(null);
            }

            cp.setInput(input);
            return(cp.runCBAPass(inp));
        }
Пример #3
0
        protected override Program runPass(Program inp)
        {
            CBAProgram ap = inp as CBAProgram;

            Debug.Assert(ap != null);

            CBAProgram ret = runCBAPass(ap);

            return(ret as Program);
        }
Пример #4
0
        // Remove all procs in "procsToRemove" from the program, and replace calls to these procedures by
        // assume false
        public static PersistentCBAProgram prune(PersistentCBAProgram pprogram, HashSet <string> procsToRemove)
        {
            if (procsToRemove.Count == 0)
            {
                return(pprogram);
            }

            // Go through all Commands and remove calls
            CBAProgram program = pprogram.getCBAProgram();

            foreach (var decl in program.TopLevelDeclarations)
            {
                if (!(decl is Implementation))
                {
                    continue;
                }
                var impl = decl as Implementation;
                foreach (Block blk in impl.Blocks)
                {
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        if (isCall(blk.Cmds[i], procsToRemove))
                        {
                            blk.Cmds[i] = new AssumeCmd(Token.NoToken, Expr.False);
                        }
                    }
                }
            }

            // Remove declarations and implementations
            var newDecls = new List <Declaration>();

            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Implementation)
                {
                    if (procsToRemove.Contains((decl as Implementation).Name))
                    {
                        continue;
                    }
                }
                else if (decl is Procedure)
                {
                    if (procsToRemove.Contains((decl as Procedure).Name))
                    {
                        continue;
                    }
                }
                newDecls.Add(decl);
            }

            program.TopLevelDeclarations = newDecls;
            return(new PersistentCBAProgram(program, program.mainProcName, program.contextBound));
        }
Пример #5
0
        private void doInlining(CBAProgram p)
        {
            inlineInput = new PersistentCBAProgram(p, p.mainProcName, p.contextBound);

            // Temporary fix for Boogie's bug while inlining calls
            // that have don't care expressions. This does not change the control
            // structure nor the number of commands per block -- hence, this transformation
            // need not be recorded.
            RewriteCallDontCares rdc = new RewriteCallDontCares();

            rdc.VisitProgram(p);

            // Copy of OnlyBoogie.EliminateDeadVariablesAndInline

            var  TopLevelDeclarations = p.TopLevelDeclarations;
            bool inline = false;

            foreach (Declaration d in TopLevelDeclarations)
            {
                if ((d is Procedure || d is Implementation) && d.FindExprAttribute("inline") != null)
                {
                    inline = true;
                }
            }
            if (inline)
            {
                foreach (Declaration d in TopLevelDeclarations)
                {
                    Implementation impl = d as Implementation;
                    if (impl != null)
                    {
                        impl.OriginalBlocks  = impl.Blocks;
                        impl.OriginalLocVars = impl.LocVars;
                    }
                }
                foreach (Declaration d in TopLevelDeclarations)
                {
                    Implementation impl = d as Implementation;
                    if (impl != null && !impl.SkipVerification)
                    {
                        Inliner.ProcessImplementation(p as Program, impl);
                    }
                }
                foreach (Declaration d in TopLevelDeclarations)
                {
                    Implementation impl = d as Implementation;
                    if (impl != null)
                    {
                        impl.OriginalBlocks  = null;
                        impl.OriginalLocVars = null;
                    }
                }
            }
        }
Пример #6
0
        public override CBAProgram runCBAPass(CBAProgram inp)
        {
            if (unrollNum < 0)
            {
                return(null);
            }
            else
            {
                inp.UnrollLoops(unrollNum, false);
            }

            return(inp);
        }
Пример #7
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            foreach (var decl in p.TopLevelDeclarations)
            {
                var impl = decl as Implementation;
                if (impl == null)
                {
                    continue;
                }
                compile(impl);
            }

            return(p);
        }
Пример #8
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            // Type information is needed in some cases. For instance, the Command
            // Mem[x] := untracked-expr is converted to havoc temp; Mem[x] := temp. Here
            // we need the type of "untracked-expr" or of "Mem[x]"
            if (p.Typecheck() != 0)
            {
                p.Emit(new TokenTextWriter("error.bpl"));
                throw new InternalError("Type errors");
            }
            vslice.VisitProgram(p as Program);
            BoogieUtil.DoModSetAnalysis(p);

            return(p);
        }
Пример #9
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            // Set the input for the first pass, just in case
            passes[0].setInput(input);

            CBAProgram curr = p;
            CBAProgram next = null;

            for (int i = 0; i < passes.Count; i++)
            {
                next = passes[i].runCBAPass(curr);
                curr = (next == null) ? curr : next;
            }

            return(next);
        }
Пример #10
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            // Eliminate dead variables
            UnusedVarEliminator.Eliminate(p as Program);

            // Add the inlining bound
            addInlineAttribute(p);

            // Inline
            doInlining(p);

            // Remove the inlined procedures & implementations
            removeInlinedProcs(p);

            // Remove annotations that won't parse because of dropped variables
            RemoveVarsFromAttributes.Prune(p);

            return(p);
        }
Пример #11
0
        private void addInlineAttribute(CBAProgram p)
        {
            foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>())
            {
                if (QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))
                {
                    continue;
                }

                var proc    = impl.Proc;
                var newattr = BoogieUtil.removeAttr("inline", proc.Attributes);

                Expr num = Expr.Literal(bound);
                var  val = new List <object>();
                val.Add(num);

                proc.Attributes = new QKeyValue(Token.NoToken, "inline", val, newattr);
            }
        }
Пример #12
0
        private void removeInlinedProcs(CBAProgram program)
        {
            HashSet <string> procsToRemove = new HashSet <string>();

            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Procedure)
                {
                    if (decl.FindExprAttribute("inline") != null)
                    {
                        procsToRemove.Add((decl as Procedure).Name);
                    }
                }
            }

            // Make sure we're not removing main
            procsToRemove.Remove(program.mainProcName);

            // Remove procs and Impls
            var newDecls = new List <Declaration>();

            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Procedure)
                {
                    if (procsToRemove.Contains((decl as Procedure).Name))
                    {
                        continue;
                    }
                }
                else if (decl is Implementation)
                {
                    if (procsToRemove.Contains((decl as Implementation).Name))
                    {
                        continue;
                    }
                }

                newDecls.Add(decl);
            }

            program.TopLevelDeclarations = newDecls;
        }
Пример #13
0
        // Returns all backedges of the call graph (i.e., a cutset in terms of edges)
        private HashSet <Tuple <string, string> > findRecursiveProcs(CBAProgram p)
        {
            var ret = new HashSet <Tuple <string, string> >();

            Graph <string> callGraph = new Graph <string>();

            callGraph.AddSource(p.mainProcName);
            foreach (var decl in p.TopLevelDeclarations)
            {
                var impl = decl as Implementation;
                if (impl == null)
                {
                    continue;
                }
                foreach (var blk in impl.Blocks)
                {
                    foreach (Cmd cmd in blk.Cmds)
                    {
                        var ccmd = cmd as CallCmd;
                        if (ccmd == null)
                        {
                            continue;
                        }
                        callGraph.AddEdge(impl.Name, ccmd.callee);
                    }
                }
            }

            // Do DFS to find a cutset

            // 0: white, 1: gray, 2: black
            var color = new Dictionary <string, int>();

            foreach (var n in callGraph.Nodes)
            {
                color.Add(n, 0);
            }

            dfs(callGraph, p.mainProcName, color, ret);
            return(ret);
        }
Пример #14
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            if (p.mode == ConcurrencyMode.FixedContext)
            {
                InstrumentationConfig.addRaiseException = false;
            }

            // Step1: Gather program information
            pinfo = new ProgramInfo(p.mainProcName, p, LanguageSemantics.assertNotReachableName());

            TidArithmetic.reset();
            if (pinfo.threadIdType.IsBv)
            {
                TidArithmetic.useIntArithmetic = false;
                p.AddTopLevelDeclaration(TidArithmetic.getBvAdd());
                p.AddTopLevelDeclaration(TidArithmetic.getBvGt());
            }
            else
            {
                TidArithmetic.useIntArithmetic = true;
            }

            // Step2: Set up a variable manager
            vmgr = new VariableManager(pinfo);

            // Step3: Set up the instrumentation policy

            // The globals not to instrument are:
            //   -- ones not modified by any procedure
            //   -- ones not shared
            //   -- ones to treat as thread-local
            HashSet <string> globalsToInstrument = new HashSet <string>();

            foreach (var g in pinfo.declaredGlobals)
            {
                string name = g.Key;
                if (!pinfo.modifiedGlobals.ContainsKey(name))
                {
                    continue;
                }
                if (!LanguageSemantics.isShared(name))
                {
                    continue;
                }
                if (pinfo.threadLocalGlobals.ContainsKey(name))
                {
                    continue;
                }
                globalsToInstrument.Add(name);
            }

            var rprocs = findRecursiveProcs(p);

            //foreach (var be in rprocs) Console.WriteLine("{0} -> {1}", be.Item1, be.Item2);

            policy =
                new InstrumentationPolicy(p.contextBound, globalsToInstrument, pinfo.procsWithImplementation, pinfo.asyncProcs, rprocs, p.mode);

            //policy.print(Log.getWriter(Log.Debug));

            // Step4: Split program declarations based on the instrumentation policy

            // skipping this step (not needed for basic CBA reduction)

            // Step5: Carry out the K-split instrumentation
            inst = new Instrumenter(policy, vmgr, pinfo, tinfo_instrument);
            List <Declaration> newDecls = inst.instrument(p.TopLevelDeclarations.ToList());

            foreach (var trp in inst.blocksWithFixedK)
            {
                blockExecutionContextMap.Add(trp.fst + "::" + trp.snd, trp.trd);
            }

            // Step6: Instrument main with initialization and the Checker
            Implementation mainProcImpl = BoogieUtil.findProcedureImpl(newDecls, p.mainProcName);

            inst.instrumentGivenMainImpl(mainProcImpl);

            // Step7: Instrument Async calls
            bool instrumentedAsync     = false;
            InstrumentAsyncCalls ainst = new InstrumentAsyncCalls(vmgr, pinfo, tinfo_async);

            foreach (var decl in newDecls)
            {
                if (decl is Implementation)
                {
                    ainst.VisitImplementation(decl as Implementation);
                    instrumentedAsync = instrumentedAsync || ainst.hasAsync;
                }
            }

            if (!instrumentedAsync)
            {
                Log.WriteLine(Log.Debug, "Warning: Did not find any async call");
            }

            // Step8: Set entrypoint
            mainProcImpl.AddAttribute("entrypoint");

            // Step9: Add new variable declarations
            newDecls.AddRange(vmgr.getNewDeclarations(policy.executionContextBound));
            newDecls.AddRange(BoogieAstFactory.newDecls);
            BoogieAstFactory.newDecls.Clear();

            // Thats it.

            Program ret = new Program();

            ret.TopLevelDeclarations = newDecls;

            if (InstrumentationConfig.printInstrumented)
            {
                // Re-resolve ret
                ProgTransformation.PersistentProgram tprog = new ProgTransformation.PersistentProgram(ret);
                var instrumented = tprog.getProgram();

                // Re-do the modsets -- make them as concise as possible.
                BoogieUtil.DoModSetAnalysis(instrumented);

                // Temporary fix for Boogie's bug while inlining calls
                // that have don't care expressions.
                RewriteCallDontCares rdc = new RewriteCallDontCares();
                rdc.VisitProgram(instrumented);

                BoogieUtil.PrintProgram(instrumented, InstrumentationConfig.instrumentedFile);

                throw new NormalExit("Printed " + InstrumentationConfig.instrumentedFile);
            }

            // Resolve the program (Do not typecheck because that does inlining).
            //BoogieUtil.PrintProgram(ret, "instrumented.bpl");
            //ret = BoogieUtil.ReadAndOnlyResolve("instrumented.bpl");
            if (p.mode == ConcurrencyMode.FixedContext)
            {
                InstrumentationConfig.addRaiseException = true;
            }

            p = new CBAProgram(ret, p.mainProcName, p.contextBound);

            return(p);
        }
Пример #15
0
        public override CBAProgram runCBAPass(CBAProgram program)
        {
            var nameImplMap = BoogieUtil.nameImplMapping(program);

            // Construct call graph, compute SCCs
            var graph = new Graph <string>();

            foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
            {
                impl.Blocks.Iter(block =>
                                 block.Cmds.OfType <CallCmd>().Iter(cmd =>
                                                                    graph.AddEdge(impl.Name, cmd.callee)));
            }
            graph.AddSource(program.mainProcName);
            var preds = new Adjacency <string>(st => graph.Predecessors(st));
            var succs = new Adjacency <string>(st => graph.Successors(st));
            var sccs  = new StronglyConnectedComponents <string>(graph.Nodes, preds, succs);

            sccs.Compute();

            //var dotFileCnt = 1;

            // For each SCC, compute backedges
            foreach (var scc in sccs)
            {
                if (scc.Count == 1)
                {
                    var onlyProc = scc.First();
                    if (nameImplMap.ContainsKey(onlyProc) && QKeyValue.FindBoolAttribute(nameImplMap[onlyProc].Attributes, "LoopProcedure"))
                    {
                        continue;
                    }

                    if (graph.Successors(onlyProc).All(callee => callee != onlyProc))
                    {
                        continue;
                    }
                }

                Console.Write("Considering SCC: ");
                scc.Iter(s => Console.Write("{0} ", s));
                Console.WriteLine();

                foundRecursion = true;

                // pick source
                var sccProcs = new HashSet <string>(scc);
                var src      = scc.FirstOrDefault(proc => graph.Predecessors(proc).Any(pred => !sccProcs.Contains(pred)));
                if (src == null)
                {
                    src = scc.First();
                }

                var grey  = new HashSet <string>();
                var black = new HashSet <string>();
                grey.Add(src);

                backedges     = new HashSet <Tuple <string, string> >();
                dfsTreeParent = new Dictionary <string, string>();
                someCycles    = new List <HashSet <string> >();

                dfs(graph, src, sccProcs, grey, black);

                InferWhatToCut(graph, scc);

                // create copies
                var procCopies = new Dictionary <Tuple <string, int>, Procedure>();
                var implCopies = new Dictionary <Tuple <string, int>, Implementation>();
                foreach (var name in scc)
                {
                    var impl = nameImplMap[name];
                    program.RemoveTopLevelDeclaration(impl);
                    program.RemoveTopLevelDeclaration(impl.Proc);

                    for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++)
                    {
                        var dup   = new FixedDuplicator(true);
                        var nimpl = dup.VisitImplementation(impl);
                        var nproc = dup.VisitProcedure(impl.Proc);

                        nimpl.Name += string.Format("#{0}", i);
                        nproc.Name += string.Format("#{0}", i);
                        nimpl.Proc  = nproc;

                        program.AddTopLevelDeclaration(nimpl);
                        program.AddTopLevelDeclaration(nproc);

                        procCopies.Add(Tuple.Create(impl.Name, i), nproc);
                        implCopies.Add(Tuple.Create(impl.Name, i), nimpl);
                    }
                }

                // redirect calls
                foreach (var name in scc)
                {
                    foreach (var pred in graph.Predecessors(name))
                    {
                        if (sccProcs.Contains(pred))
                        {
                            continue;
                        }
                        var pimpl = nameImplMap[pred];
                        foreach (var blk in pimpl.Blocks)
                        {
                            var newcmds = new List <Cmd>();
                            foreach (var cmd in blk.Cmds)
                            {
                                var ccmd = cmd as CallCmd;
                                if (ccmd == null || !sccProcs.Contains(ccmd.callee))
                                {
                                    newcmds.Add(cmd);
                                    continue;
                                }
                                newcmds.Add(
                                    new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", CommandLineOptions.Clo.RecursionBound - 1),
                                                ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync));
                            }
                            blk.Cmds = newcmds;
                        }
                    }

                    for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++)
                    {
                        var impl = implCopies[Tuple.Create(name, i)];
                        foreach (var blk in impl.Blocks)
                        {
                            var newcmds = new List <Cmd>();
                            foreach (var cmd in blk.Cmds)
                            {
                                var ccmd = cmd as CallCmd;
                                if (ccmd == null || !sccProcs.Contains(ccmd.callee))
                                {
                                    newcmds.Add(cmd);
                                    continue;
                                }
                                var cnt = i;
                                if (CutEdge(name, ccmd.callee))
                                {
                                    cnt--;
                                }

                                if (cnt < 0)
                                {
                                    newcmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
                                }
                                else
                                {
                                    newcmds.Add(new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", cnt),
                                                            ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync));
                                }
                            }
                            blk.Cmds = newcmds;
                        }
                    }
                }
            }

            return(program);
        }
Пример #16
0
 public override CBAProgram runCBAPass(CBAProgram p)
 {
     rcc.VisitProgram(p as Program);
     return(p);
 }
Пример #17
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            if (!aggressive)
            {
                return(null);
            }

            var procsWithAsserts           = procsWithAssertions(p);
            HashSet <string> procsToDelete = new HashSet <string>();

            // Gather the set of procedures to delete
            foreach (Declaration d in p.TopLevelDeclarations)
            {
                if (d is Procedure)
                {
                    var proc = d as Procedure;

                    if (proc.Name.Equals(p.mainProcName))
                    {
                        continue;
                    }

                    if (procsWithAsserts.Contains(proc.Name))
                    {
                        continue;
                    }

                    if (proc.OutParams.Count > 0)
                    {
                        continue;
                    }

                    var modifiesShared = false;
                    foreach (IdentifierExpr ie in proc.Modifies)
                    {
                        if (LanguageSemantics.isShared(ie.Decl.Name))
                        {
                            modifiesShared = true;
                            break;
                        }
                    }

                    if (!modifiesShared)
                    {
                        procsToDelete.Add(proc.Name);
                    }
                }
            }

            // Delete the implementations
            CBAProgram ret = new CBAProgram(new Program(), p.mainProcName, p.contextBound);

            foreach (Declaration d in p.TopLevelDeclarations)
            {
                if (d is Implementation)
                {
                    Implementation impl = d as Implementation;
                    if (procsToDelete.Contains(impl.Name) && !BoogieUtil.hasAssert(impl))
                    {
                        Log.WriteLine(Log.Debug, "Deleting " + impl.Name);
                        continue;
                    }
                    ret.AddTopLevelDeclaration(d);
                }
                else
                {
                    ret.AddTopLevelDeclaration(d);
                }
            }

            Log.WriteLine(Log.Debug, "Empty Mod Sets: Deleted " + (p.TopLevelDeclarations.Count() - ret.TopLevelDeclarations.Count()).ToString() +
                          " implementations");
            return(ret);
        }
Пример #18
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            if (unrollNum >= 0)
            {
                return(base.runCBAPass(p));
            }

            foreach (var impl in BoogieUtil.GetImplementations(p))
            {
                impl.PruneUnreachableBlocks();
            }

            // save RB
            var rb = CommandLineOptions.Clo.RecursionBound;

            if (BoogieVerify.irreducibleLoopUnroll >= 0)
            {
                CommandLineOptions.Clo.RecursionBound = BoogieVerify.irreducibleLoopUnroll;
            }

            var procsWithIrreducibleLoops = new HashSet <string>();
            var passInfo = p.ExtractLoops(out procsWithIrreducibleLoops);

            // restore RB
            CommandLineOptions.Clo.RecursionBound = rb;

            // no loops found, then this transformation is identity
            if (passInfo.Count == 0 && procsWithIrreducibleLoops.Count == 0)
            {
                return(null);
            }

            if (addUniqueCallLabels)
            {
                // annotate calls with a unique number
                var addIds = new AddUniqueCallIds();

                // Loop unrolling is done for procs with irreducible loops.
                // This simply copies Cmd objects. Duplicate them to remove
                // aliasing
                foreach (var impl in p.TopLevelDeclarations
                         .OfType <Implementation>()
                         .Where(impl => procsWithIrreducibleLoops.Contains(impl.Name)))
                {
                    var dup = new FixedDuplicator(true);
                    foreach (var blk in impl.Blocks)
                    {
                        blk.Cmds = dup.VisitCmdSeq(blk.Cmds);
                    }
                }

                // Add labels again to all procedures
                foreach (var impl in p.TopLevelDeclarations
                         .OfType <Implementation>())
                {
                    addIds.VisitImplementation(impl);
                }
            }

            info = new Dictionary <string, Dictionary <string, string> >();
            passInfo.Iter(kvp =>
            {
                info.Add(kvp.Key, new Dictionary <string, string>());
                kvp.Value.Iter(sb => info[kvp.Key].Add(sb.Key, sb.Value.Label));
            });

            // Construct the set of procs in the original program
            // and the loop procedures
            allProcs  = new HashSet <string>();
            loopProcs = new HashSet <string>();
            foreach (var decl in p.TopLevelDeclarations)
            {
                var impl = decl as Implementation;
                if (impl == null)
                {
                    continue;
                }
                allProcs.Add(impl.Name);
                if (impl.Proc is LoopProcedure)
                {
                    loopProcs.Add(impl.Name);
                    impl.Proc.AddAttribute("LoopProcedure");
                }
            }

            //foreach (var impl in BoogieUtil.GetImplementations(p))
            //{
            //removeAssumeFalseBlocks(impl);
            //}


            // Optimization: if no loop is found, then no need to print
            // out a new program
            if (loopProcs.Count == 0)
            {
                return(null);
            }

            // Remove vars from attributes that are not in scope anymore
            RemoveVarsFromAttributes.Prune(p);

            return(p);
        }
Пример #19
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            // Run verification, gather traces
            var verifier = getVerifier();

            verifier.run(input);

            // Set verification result
            success = verifier.success;
            traces  = verifier.traces;

            // Now compute coverage, provided error was not reached
            if (!verifier.success)
            {
                return(null);
            }

            // Gather procedure names
            var nameImplMap = BoogieUtil.nameImplMapping(p);

            var allProcs = new HashSet <string>();

            foreach (var tp in nameImplMap)
            {
                allProcs.Add(tp.Key);
            }

            procsNotCovered = new HashSet <string>();
            procsNotCovered.UnionWith(allProcs);
            procsNotCovered.Remove(p.mainProcName);

            // Iterate and gather procedures that can be reached
            int oldProverLimit = CommandLineOptions.Clo.ProverCCLimit;

            var done = false;

            do
            {
                // Set the number of traces returned by boogie in one shot
                CommandLineOptions.Clo.ProverCCLimit = procsNotCovered.Count();

                var covered = iterateComputation(input as PersistentCBAProgram, procsNotCovered);
                if (covered.Count == 0)
                {
                    done = true;
                }
                else
                {
                    procsNotCovered = HashSetExtras <string> .Difference(procsNotCovered, covered);

                    if (!procsNotCovered.Any())
                    {
                        done = true;
                    }
                }
            } while (!done);

            CommandLineOptions.Clo.ProverCCLimit = oldProverLimit;

            return(null);
        }
Пример #20
0
        // Short-circuit the chain of returns produced by raiseException
        public void optimizeRaiseExceptionInstrumentation(CBAProgram program)
        {
            var procMap  = BoogieUtil.nameImplMapping(program);
            var mainImpl = procMap[program.mainProcName];

            var labelBlockMap = BoogieUtil.labelBlockMapping(mainImpl);

            // For each block, check if the first statement is "assume raiseException"
            foreach (var blk in mainImpl.Blocks)
            {
                if (blk.Cmds.Count == 0)
                {
                    continue;
                }

                var cmd = blk.Cmds[0];

                if (!(cmd is AssumeCmd))
                {
                    continue;
                }

                var expr = (cmd as AssumeCmd).Expr;
                if (expr is IdentifierExpr)
                {
                    var v = (expr as IdentifierExpr).Decl;
                    if (v.Name != "raiseException")
                    {
                        continue;
                    }
                }
                else
                {
                    continue;
                }

                // Yup, its "assume raiseException" -- follow the chain of gotos through empty blocks
                var lab = getSingleSucc(blk.TransferCmd);
                if (lab == null)
                {
                    continue;
                }

                var b        = labelBlockMap[lab];
                var chainLen = 0;

                /* Heuristic, possibly unsound: some blocks have a single statement that contains
                 * an assignment for the return value. Note that once raiseException has been raised,
                 * no return value is needed.
                 */
                while (b.Cmds.Count <= 1)
                {
                    var next = getSingleSucc(b.TransferCmd);
                    if (next == null)
                    {
                        break;
                    }
                    lab = next;
                    b   = labelBlockMap[lab];
                    chainLen++;
                }

                blk.TransferCmd = BoogieAstFactory.MkGotoCmd(lab);

                if (chainLen != 0)
                {
                    Log.WriteLine(Log.Debug, "raiseException chain shortened by " + chainLen.ToString());
                }
            }
        }
Пример #21
0
 abstract public CBAProgram runCBAPass(CBAProgram p);
Пример #22
0
 public override CBAProgram runCBAPass(CBAProgram p)
 {
     compressBlocks.VisitProgram(p);
     return(p);
 }
Пример #23
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            procsOnEP = new HashSet <string>();
            var nameImplMap = BoogieUtil.nameImplMapping(p);

            // Set of all procedures (with an implementation)
            var allProcs = new HashSet <string>();

            foreach (var tp in nameImplMap)
            {
                allProcs.Add(tp.Key);
            }

            var verifier = getVerifier();

            // Run verification, gather traces
            verifier.run(input);

            // Set verification result
            success = verifier.success;
            traces  = verifier.traces;

            // Now, compute the error projection
            if (verifier.success)
            {
                ErrorProjection = allProcs;
                return(null);
            }

            // Look at all procedures that lie on the error trace
            foreach (var trace in verifier.traces)
            {
                procsOnEP.UnionWith(trace.getProcs());
            }

            Log.WriteLine(Log.Normal, string.Format("EP: Got {0} traces and {1} procs", verifier.traces.Count, procsOnEP.Count));

            // Just make sure that we inlcude main here (probably not necessary)
            procsOnEP.Add(p.mainProcName);

            // Have we already covered all of the program?
            if (procsOnEP.Equals(allProcs))
            {
                ErrorProjection = new HashSet <string>();
                return(null);
            }

            // Iterate and try to force the verifier to return paths in
            // different procedures
            var done = false;

            do
            {
                var moreProcs = iterateComputation(input as PersistentCBAProgram, HashSetExtras <string> .Difference(allProcs, procsOnEP));
                if (moreProcs.Count == 0)
                {
                    done = true;
                }
                else
                {
                    procsOnEP.UnionWith(moreProcs);
                    if (procsOnEP.Equals(allProcs))
                    {
                        done = true;
                    }
                }
            } while (!done);

            ErrorProjection = HashSetExtras <string> .Difference(allProcs, procsOnEP);

            return(null);
        }
Пример #24
0
        public static Dictionary <string, int> Compute(CBAProgram program, int max, List <string> Annotations, BoogieVerifyOptions options)
        {
            var loopBounds = new Dictionary <string, int>();

            Initialize(Annotations);
            maxBound = max;
            var start = DateTime.Now;

            // remove non-free ensures and requires
            program.TopLevelDeclarations.OfType <Procedure>()
            .Iter(proc => proc.Ensures = proc.Ensures.Filter(en => en.Free));
            program.TopLevelDeclarations.OfType <Procedure>()
            .Iter(proc => proc.Requires = proc.Requires.Filter(en => en.Free));
            // remove assertions
            program.TopLevelDeclarations.OfType <Implementation>()
            .Iter(impl => impl.Blocks
                  .Iter(blk => blk.Cmds = blk.Cmds.Map(c =>
            {
                var ac = c as AssertCmd;
                if (ac == null)
                {
                    return(c);
                }
                return(new AssumeCmd(ac.tok, /*ac.Expr*/ Expr.True, ac.Attributes));
            })));
            // delete yield
            program.TopLevelDeclarations.OfType <Implementation>()
            .Iter(impl => impl.Blocks
                  .Iter(blk => blk.Cmds.RemoveAll(c => c is YieldCmd)));

            // Call graph
            ComputeCallGraph(program);

            // Gather the set of implementations with "loop" inside their name
            var allLoopImpls = new List <Implementation>();

            program.TopLevelDeclarations.OfType <Implementation>()
            .Iter(impl => { if (impl.Name.Contains("loop"))
                            {
                                allLoopImpls.Add(impl);
                            }
                  });

            // Prune to the right form
            var loopImpls = allLoopImpls.Filter(CheckImpl);

            #region Process user annotations

            // Include user anntations
            var allLoops = new HashSet <string>();
            loopImpls.Iter(impl => allLoops.Add(impl.Name));
            foreach (var sp in UserAnnotations
                     .Where(s => s.StartsWith("LB:"))
                     .Select(s => s.Split(':'))
                     .Where(sp => sp.Length == 3))
            {
                // grab bound
                var bound = 0;
                if (!Int32.TryParse(sp[2], out bound))
                {
                    continue;
                }

                // grab proc
                if (!allLoops.Contains(sp[1]))
                {
                    continue;
                }

                loopBounds[sp[1]] = bound;
                Console.WriteLine("LB: Loop {0} requires minimum {1} iterations (annotated)", sp[1], bound);
            }
            loopImpls = loopImpls.Filter(impl => !loopBounds.ContainsKey(impl.Name));
            #endregion

            if (loopImpls.Count == 0)
            {
                return(loopBounds);
            }

            // Prepare query
            var query = PrepareQuery(loopImpls, program);

            // Set general options
            BoogieVerify.options = options;

            // Set rec. bound
            var oldBound = CommandLineOptions.Clo.RecursionBound;
            CommandLineOptions.Clo.RecursionBound = maxBound;

            // Query
            var allErrors = new List <BoogieErrorTrace>();
            BoogieVerify.Verify(query, out allErrors);
            foreach (var trace in allErrors)
            {
                var loopName = QKeyValue.FindStringAttribute(trace.impl.Attributes, "LB_Mapping");
                var bound    = RecBound(loopName, trace.cex, trace.impl.Name);
                if (bound <= 1)
                {
                    continue;
                }
                loopBounds.Add(loopName, bound);
                Console.WriteLine("LB: Loop {0} requires minimum {1} iterations", loopName, bound);
            }

            CommandLineOptions.Clo.RecursionBound = oldBound;
            timeTaken = (DateTime.Now - start);

            return(loopBounds);
        }