예제 #1
0
        public override CBAProgram runCBAPass(CBAProgram program)
        {
            // Add blanks
            blanksInfo = AddBlanks(program);

            // Remove unreachable procedures
            BoogieUtil.pruneProcs(program, program.mainProcName);

            if (!Options.TraceSlicing)
            {
                // Remove source line annotations
                sourceInfo = cba.PrintSdvPath.DeleteSourceInfo(program);
            }
            else
            {
                sourceInfo = null;
            }

            // Remove print info
            //printInfo = cba.PrintSdvPath.DeletePrintCmds(program);

            // Compress
            compressBlocks.VisitProgram(program);

            // name Ebasic
            NameEnvironmentConstraints(program);

            // Instrument assertions
            int tokenId = 0;

            origMainName = program.mainProcName;

            CBAProgram ret = null;

            if (!Options.DeepAsserts)
            {
                // Do error-bit instrumentation
                var impls = BoogieUtil.nameImplMapping(program);
                var pwa   = cba.SequentialInstrumentation.procsWithAsserts(program);

                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    var instrumented = new List <Block>();
                    foreach (var blk in impl.Blocks)
                    {
                        var currCmds  = new List <Cmd>();
                        var currLabel = blk.Label;

                        assertInstrInfo.addTrans(impl.Name, blk.Label, blk.Label);
                        var incnt = -1;
                        foreach (Cmd cmd in blk.Cmds)
                        {
                            incnt++;

                            // instrument assert
                            if (cmd is AssertCmd && !BoogieUtil.isAssertTrue(cmd))
                            {
                                currCmds.Add(BoogieAstFactory.MkVarEqExpr(assertsPassed, (cmd as AssertCmd).Expr));

                                var token = new AssertToken(tokenId);
                                originalAssertions.Add(token, cmd as AssertCmd);
                                tokenLocation.Add(token, Tuple.Create(impl.Name, currLabel));
                                procToTokens.InitAndAdd(impl.Name, token);

                                addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);

                                currLabel = addInstr(instrumented, currCmds, currLabel, tokenId);
                                tokenId++;
                                currCmds = new List <Cmd>();

                                continue;
                            }

                            // procedure call
                            if (cmd is CallCmd && pwa.Contains((cmd as CallCmd).callee))
                            {
                                currCmds.Add(cmd);
                                addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);
                                currLabel = addInstr(instrumented, currCmds, currLabel, -1);
                                currCmds  = new List <Cmd>();
                                continue;
                            }

                            currCmds.Add(cmd);
                            addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);
                        }

                        instrumented.Add(new Block(Token.NoToken, currLabel, currCmds, blk.TransferCmd));
                    }

                    impl.Blocks = instrumented;
                }

                program.AddTopLevelDeclaration(assertsPassed);
                var newMain = addMain(program);

                BoogieUtil.DoModSetAnalysis(program);

                // Set inline attribute
                // free requires assertsPassed == true;
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    impl.Proc.Requires.Add(new Requires(true, Expr.Ident(assertsPassed)));
                }

                // convert free ensures e to:
                //  free ensures assertsPassed == false || e
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()
                         .Where(impl => pwa.Contains(impl.Name)))
                {
                    foreach (Ensures ens in impl.Proc.Ensures)
                    {
                        ens.Condition = Expr.Or(Expr.Not(Expr.Ident(assertsPassed)), ens.Condition);
                    }
                }

                currProg = program;
                ret      = new CBAProgram(program, newMain, 0);
            }
            else
            {
                // Use Deep-assert instrumentation
                da = new cba.DeepAssertRewrite();

                // First, tag assertions with tokens
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    foreach (var blk in impl.Blocks)
                    {
                        foreach (var cmd in blk.Cmds.OfType <AssertCmd>())
                        {
                            if (BoogieUtil.isAssertTrue(cmd))
                            {
                                continue;
                            }

                            var token = new AssertToken(tokenId);
                            cmd.Attributes = new QKeyValue(Token.NoToken, "avn", new List <object> {
                                Expr.Literal(tokenId)
                            },
                                                           cmd.Attributes);
                            originalAssertions.Add(token, cmd);
                            tokenLocation.Add(token, Tuple.Create(impl.Name, blk.Label));
                            procToTokens.InitAndAdd(impl.Name, token);
                            tokenId++;
                        }
                    }
                }

                // Second, do the rewrite
                var t1     = new PersistentProgram(program, program.mainProcName, program.contextBound);
                var t2     = da.run(t1);
                var daprog = t2.getCBAProgram();

                // Third, revisit the assertions and remember their location
                // in the output program. This is a bit of a hack. The "tokenLocation"
                // of a token is the pair (p1,b1) where p1 is the procedure the assertion
                // originally came from and b1 is the block in the new main that contains
                // that assertion.
                var main = BoogieUtil.findProcedureImpl(daprog.TopLevelDeclarations, daprog.mainProcName);
                foreach (var block in main.Blocks)
                {
                    foreach (var cmd in block.Cmds.OfType <AssertCmd>())
                    {
                        var tok = QKeyValue.FindIntAttribute(cmd.Attributes, "avn", -1);
                        if (tok < 0)
                        {
                            continue;
                        }
                        var token = new AssertToken(tok);

                        Debug.Assert(tokenLocation.ContainsKey(token));
                        var oldloc = tokenLocation[token];
                        tokenLocation[token] = Tuple.Create(oldloc.Item1, block.Label);
                    }
                }

                currProg = daprog;
                ret      = daprog;
            }

            return(ret);
        }
예제 #2
0
        // Prune away EntryPoints that cannot reach an assertion
        static void PruneRedundantEntryPoints(Program program)
        {
            var procs = BoogieUtil.procsThatMaySatisfyPredicate(program, cmd => (cmd is AssertCmd && !BoogieUtil.isAssertTrue(cmd)));

            procs = harnessInstrumentation.entrypoints.Difference(procs);
            Console.WriteLine("Pruning away {0} entry points as they cannot reach an assert", procs.Count);
            harnessInstrumentation.PruneEntryPoints(program, procs);
        }
예제 #3
0
        private static Program PrepareQuery(IEnumerable <Implementation> loopImpls, Program program)
        {
            // Sometimes loops have multiple backedges, hence multiple recursive calls: merge them
            loopImpls.Iter(impl => mergeRecCalls(impl));

            var dup = new FixedDuplicator(true);
            // Make copies of loopImpl procs
            var loopProcsCopy = new Dictionary <string, Procedure>();

            loopImpls
            .Iter(impl => loopProcsCopy.Add(impl.Name, dup.VisitProcedure(impl.Proc)));

            loopProcsCopy.Values.Iter(proc => proc.Name += "_PassiveCopy");

            // Make copies of the caller implementations
            var loopCallerImplCopy = new Dictionary <string, Implementation>();
            var loopCallerProcCopy = new Dictionary <string, Procedure>();

            loopImpls
            .Iter(impl => loopCallerImplCopy.Add(impl.Name, dup.VisitImplementation(loopCaller[impl.Name])));

            loopImpls
            .Iter(impl => loopCallerProcCopy.Add(impl.Name, dup.VisitProcedure(loopCaller[impl.Name].Proc)));

            loopCallerImplCopy
            .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key);

            loopCallerProcCopy
            .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key);

            loopCallerImplCopy
            .Iter(kvp => kvp.Value.Proc = loopCallerProcCopy[kvp.Key]);

            // Instrument callers
            foreach (var kvp in loopCallerImplCopy)
            {
                var impl = kvp.Value;

                var av = BoogieAstFactory.MkLocal("LoopBound_AssertVar", Microsoft.Boogie.Type.Bool);
                impl.LocVars.Add(av);

                // av := true
                var init     = BoogieAstFactory.MkVarEqConst(av, true);
                var initCmds = new List <Cmd>();
                initCmds.Add(init);
                initCmds.AddRange(impl.Blocks[0].Cmds);
                impl.Blocks[0].Cmds = initCmds;

                // av := false
                foreach (var blk in impl.Blocks)
                {
                    var newCmds = new List <Cmd>();
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        // disable assertions
                        if (blk.Cmds[i] is AssertCmd && !BoogieUtil.isAssertTrue(blk.Cmds[i]))
                        {
                            newCmds.Add(new AssumeCmd(Token.NoToken, (blk.Cmds[i] as AssertCmd).Expr));
                            continue;
                        }
                        var cc = blk.Cmds[i] as CallCmd;
                        if (cc != null && cc.callee == kvp.Key)
                        {
                            newCmds.Add(blk.Cmds[i]);
                            newCmds.Add(BoogieAstFactory.MkVarEqConst(av, false));
                        }
                        else if (cc != null && loopProcsCopy.ContainsKey(cc.callee))
                        {
                            var ncc = new CallCmd(cc.tok, loopProcsCopy[cc.callee].Name, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync);
                            ncc.Proc = loopProcsCopy[cc.callee];
                            newCmds.Add(ncc);
                        }
                        else
                        {
                            newCmds.Add(blk.Cmds[i]);
                        }
                    }
                    blk.Cmds = newCmds;
                }

                // assert av
                impl.Blocks
                .Where(blk => blk.TransferCmd is ReturnCmd)
                .Iter(blk => blk.Cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(av))));
            }

            // Prepare program
            var ret = new Program();

            program.TopLevelDeclarations
            .Where(decl => !(decl is Implementation))
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopProcsCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopCallerImplCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopCallerProcCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopImpls
            .Iter(impl => ret.AddTopLevelDeclaration(impl));

            loopCallerImplCopy.Values
            .Iter(impl => impl.AddAttribute("entrypoint"));

            // Store mapping: entrypoint -> loop
            loopImpls
            .Select(loop => Tuple.Create(loop, loopCallerImplCopy[loop.Name]))
            .Iter(tup => tup.Item2.AddAttribute("LB_Mapping", tup.Item1.Name));

            ret = BoogieUtil.ReResolveInMem(ret);

            return(ret);
        }