Beispiel #1
0
        // Always safe to return Top
        public static Value Evaluate(Expr expr, Dictionary <string, Value> subst)
        {
            var vused = new VarsUsed();

            vused.Visit(expr);

            // Make sure we have values of all variables except in-formals
            var informals = vused.Vars.Where(v => !subst.ContainsKey(v.Name));

            if (informals.All(v => (v is Formal) && ((v as Formal).InComing)))
            {
            }
            else
            {
                return(Value.GetTop());
            }

            if (vused.Vars.Any(v => subst.ContainsKey(v.Name) && subst[v.Name].ToSingletonVar() == null))
            {
                return(GetTop());
            }

            var vsubst = new Dictionary <string, Variable>();

            subst.Keys.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar()));

            var dup = new FixedDuplicator();
            var ne  = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(expr));

            return(Value.GetSingleton(ne));
        }
Beispiel #2
0
        public Value Subst(Dictionary <string, Value> subst)
        {
            if (isTrue)
            {
                return(this);
            }
            var newc = new HashSet <int>(constants);
            var newv = new HashSet <Variable>();
            var newe = new HashSet <Expr>();

            foreach (var v in vars)
            {
                Debug.Assert(subst.ContainsKey(v.Name));
                if (subst[v.Name].isTrue)
                {
                    return(GetTop());
                }
                newc.UnionWith(subst[v.Name].constants);
                newv.UnionWith(subst[v.Name].vars);
                newe.UnionWith(subst[v.Name].constExprs);
            }

            foreach (var e in constExprs)
            {
                var vused = new VarsUsed();
                vused.VisitExpr(e);

                Debug.Assert(vused.varsUsed.All(v => subst.ContainsKey(v)));

                if (vused.varsUsed.Any(v => subst[v].ToSingletonVar() == null))
                {
                    return(GetTop());
                }

                var vsubst = new Dictionary <string, Variable>();
                vused.varsUsed.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar()));

                var dup = new FixedDuplicator();
                var ne  = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(e));
                newe.Add(ne);
            }

            newe = removeDuplicates(newe);
            if (newe.Count > maxExprsToTrack)
            {
                return(GetTop());
            }

            var ret = new Value();

            ret.vars       = newv;
            ret.constants  = newc;
            ret.constExprs = newe;
            ret.isTrue     = false;

            return(ret);
        }
Beispiel #3
0
        // Return a new copy of the program
        public override Program getProgram()
        {
            var     startTime = DateTime.Now;
            Program ret;

            if (unresolved_program != null)
            {
                FixedDuplicator dup = new FixedDuplicator();
                ret = dup.VisitProgram(unresolved_program);
            }
            else
            {
                var progStr = "";
                if (programStream is FileStream || programStream is MemoryStream)
                {
                    var stream = programStream as Stream;
                    stream.Seek(0, SeekOrigin.Begin);
                    progStr = ParserHelper.Fill(stream, new List <string>());
                }
                else
                {
                    Debug.Assert(programStream is string);
                    progStr = (string)programStream;
                }

                var v = Parser.Parse(progStr, "PersistentProgram", out ret);

                if (v != 0)
                {
                    writeToFile("error.bpl");
                    throw new InternalError("Illegal program given to PersistentProgram");
                }

                if (PersistentProgram.clearTokens)
                {
                    PersistentProgram.ClearTokens(ret);
                }

                // TODO: use this always (sometimes .NET-2-Boogie programs crash)
                if (useDuplicator)
                {
                    FixedDuplicator dup = new FixedDuplicator();
                    unresolved_program = dup.VisitProgram(ret);
                }
            }

            if (ret.Resolve() != 0)
            {
                writeToFile("error.bpl");
                throw new InternalError("Illegal program given to PersistentProgram");
            }

            persistenceCost += (DateTime.Now - startTime);
            return(ret);
        }
        // Adds a new main:
        //   assertsPassed := true;
        //   call main();
        //   assert assertsPassed;
        string addMain(CBAProgram program)
        {
            var dup      = new FixedDuplicator();
            var origMain = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, program.mainProcName);
            var newMain  = dup.VisitImplementation(origMain);
            var newProc  = dup.VisitProcedure(origMain.Proc);

            newMain.Name += "_SeqInstr";
            newProc.Name += "_SeqInstr";
            newMain.Proc  = newProc;

            var mainIns = new List <Expr>();

            foreach (Variable v in newMain.InParams)
            {
                mainIns.Add(Expr.Ident(v));
            }
            var mainOuts = new List <IdentifierExpr>();

            foreach (Variable v in newMain.OutParams)
            {
                mainOuts.Add(Expr.Ident(v));
            }

            var callMain = new CallCmd(Token.NoToken, program.mainProcName, mainIns, mainOuts);

            callMain.Proc = origMain.Proc;

            var cmds = new List <Cmd>();

            cmds.Add(BoogieAstFactory.MkVarEqConst(assertsPassed, true));
            cmds.Add(callMain);
            cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(assertsPassed)));

            var blk = new Block(Token.NoToken, "start", cmds, new ReturnCmd(Token.NoToken));

            newMain.Blocks = new List <Block>();
            newMain.Blocks.Add(blk);

            program.AddTopLevelDeclaration(newProc);
            program.AddTopLevelDeclaration(newMain);

            program.mainProcName = newMain.Name;

            // Set entrypoint
            origMain.Attributes      = BoogieUtil.removeAttr("entrypoint", origMain.Attributes);
            origMain.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", origMain.Proc.Attributes);

            newMain.AddAttribute("entrypoint");

            return(newMain.Name);
        }
Beispiel #5
0
        // Return a new copy of the program
        public override Program getProgram()
        {
            var startTime = DateTime.Now;

            FixedDuplicator dup = new FixedDuplicator();
            Program         ret = dup.VisitProgram(program);

            if (ret.Resolve() != 0 || ret.Typecheck() != 0)
            {
                BoogieUtil.PrintProgram(ret, "error.bpl");
                throw new InternalError("Illegal program given to PersistentProgram");
            }

            persistenceCost += (DateTime.Now - startTime);
            return(ret);
        }
Beispiel #6
0
        private void readInProgram(Program p)
        {
            var startTime = DateTime.Now;

            // Make a copy of p into the persistent storage
            FixedDuplicator dup = new FixedDuplicator();

            program = dup.VisitProgram(p);

            // Unresolve the program to break any pointer links
            var unresolver = new UnResolver();

            unresolver.VisitProgram(program);

            persistenceCost += (DateTime.Now - startTime);
        }
Beispiel #7
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            p.Typecheck();

            p.TopLevelDeclarations.OfType <Procedure>().Iter(proc => procsWithoutBody.Add(proc.Name));
            p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => procsWithoutBody.Remove(impl.Name));

            // remove malloc
            //procsWithoutBody.RemoveWhere(str => str.Contains("malloc"));

            // Make sure that procs without a body don't modify globals
            foreach (var proc in p.TopLevelDeclarations.OfType <Procedure>().Where(proc => procsWithoutBody.Contains(proc.Name)))
            {
                if (proc.Modifies.Count > 0 && !BoogieUtil.checkAttrExists("allocator", proc.Attributes))
                {
                    throw new InvalidInput("Produce Bug Witness: Procedure " + proc.Name + " modifies globals");
                }
            }

            // Add the boogie_si_record_int procedure
            var inpVarInt  = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Int), true);
            var inpVarBool = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Bool), true);

            var reProcInt = new Procedure(Token.NoToken, recordProcNameInt, new List <TypeVariable>(), new List <Variable> {
                inpVarInt
            }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());
            var reProcBool = new Procedure(Token.NoToken, recordProcNameBool, new List <TypeVariable>(), new List <Variable> {
                inpVarBool
            }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());

            // Add procedures for initialization of local variables
            foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>())
            {
                var ncmds = new List <Cmd>();
                foreach (var loc in (impl.LocVars.Concat(impl.OutParams)))
                {
                    var cc = new CallCmd(Token.NoToken, GetInitLocalsProc(loc.TypedIdent.Type).Name, new List <Expr>(), new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(loc) }));
                    cc.Attributes = new QKeyValue(Token.NoToken, RestrictToTrace.ConcretizeConstantNameAttr, new List <object> {
                        LocalVarInitValueAttr
                    }, cc.Attributes);
                    cc.Proc = GetInitLocalsProc(loc.TypedIdent.Type);
                    ncmds.Add(cc);
                }
                ncmds.AddRange(impl.Blocks[0].Cmds);
                impl.Blocks[0].Cmds = ncmds;
            }
            typeToInitLocalsProc.Values.Iter(pr => procsWithoutBody.Add(pr.Name));
            typeToInitLocalsProc.Values.Iter(pr => p.AddTopLevelDeclaration(pr));

            // save the current program
            var fd         = new FixedDuplicator(true);
            var modInpProg = fd.VisitProgram(p);

            // Instrument to record stuff
            p.TopLevelDeclarations.OfType <Implementation>().Iter(impl =>
                                                                  impl.Blocks.Iter(b => instrument(b)));

            // Name clash if this assert fails
            Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameInt) == null);
            Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameBool) == null);
            foreach (var rp in typeToRecordProc.Values)
            {
                Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, rp.Name) == null);
            }

            p.AddTopLevelDeclaration(reProcInt);
            p.AddTopLevelDeclaration(reProcBool);
            p.AddTopLevelDeclarations(typeToRecordProc.Values);

            var tmainimpl = BoogieUtil.findProcedureImpl(p.TopLevelDeclarations, p.mainProcName);

            if (!QKeyValue.FindBoolAttribute(tmainimpl.Attributes, "entrypoint"))
            {
                tmainimpl.AddAttribute("entrypoint");
            }

            var program = new PersistentCBAProgram(p, p.mainProcName, 0);
            //program.writeToFile("beforeverify.bpl");
            var vp = new VerificationPass(true);

            vp.run(program);

            success = vp.success;
            if (success)
            {
                return(null);
            }

            var trace = mapBackTraceRecord(vp.trace);

            RestrictToTrace.addConcretization            = true;
            RestrictToTrace.addConcretizationAsConstants = true;
            var tinfo = new InsertionTrans();
            var rt    = new RestrictToTrace(modInpProg, tinfo);

            rt.addTrace(trace);
            RestrictToTrace.addConcretization            = false;
            RestrictToTrace.addConcretizationAsConstants = false;

            var rtprog = rt.getProgram();

            // Build a map of where the alloc constants are from
            allocConstants = rt.concretizeConstantToCall;

            // Add symbolic constants for angelic map havocs
            var newDecls = new List <Constant>();

            rtprog.TopLevelDeclarations.OfType <Implementation>().Iter(impl =>
                                                                       impl.Blocks.Iter(b => instrumentMapHavocs(b, allocConstants, newDecls)));
            rtprog.AddTopLevelDeclarations(newDecls);

            /*
             * foreach (var impl in rtprog.TopLevelDeclarations.OfType<Implementation>())
             * {
             *  // strip _trace from the impl name
             *  var implName = impl.Name;
             *  var c = implName.LastIndexOf("_trace");
             *  while (c != -1)
             *  {
             *      implName = implName.Substring(0, c);
             *      c = implName.LastIndexOf("_trace");
             *  }
             *
             *  var vu = new VarsUsed();
             *  vu.VisitImplementation(impl);
             *  vu.varsUsed.Where(s => s.StartsWith("alloc_"))
             *      .Iter(s => allocConstants[s] = implName);
             * }
             */
            BoogieUtil.findProcedureImpl(rtprog.TopLevelDeclarations, rt.getFirstNameInstance(p.mainProcName))
            .AddAttribute("entrypoint");

            program = new PersistentCBAProgram(rtprog, rt.getFirstNameInstance(p.mainProcName), p.contextBound);

            // Lets inline it all
            var inlp = new InliningPass(1);

            program = inlp.run(program);

            var compress = new CompressBlocks();
            var ret      = program.getProgram();

            compress.VisitProgram(ret);


            return(new CBAProgram(ret, program.mainProcName, 0));
        }
Beispiel #8
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);
        }
Beispiel #9
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);
        }
        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);
        }
Beispiel #11
0
        // Split on the postconditions of procedure "proc"
        // 1. only retain its postconditions; make everything else as assumes
        // 2. drop the implementation of the procedure
        // 3. convert calls to itself to calls to a fake procedure with assumed postconditions
        static Program SplitOnProcedure(Program program, string proc)
        {
            var dup = new FixedDuplicator();

            program = dup.VisitProgram(program);
            program = BoogieUtil.ReResolveInMem(program, true);

            var            toremove = new HashSet <Implementation>();
            Implementation procimpl = null;

            foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
            {
                if (impl.Name == proc)
                {
                    procimpl = impl;
                    continue;
                }

                if (impl.Proc.Ensures.All(ens => ens.Free))
                {
                    continue;
                }

                var newens = new List <Ensures>();
                impl.Proc.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment)));
                impl.Proc.Ensures = newens;
                toremove.Add(impl);
            }

            program.RemoveTopLevelDeclarations(decl => decl is Implementation && toremove.Contains(decl));

            if (procimpl != null)
            {
                // create copy
                var proccopy = dup.VisitProcedure(procimpl.Proc);
                proccopy.Name += "_dup";

                // make assumes
                var newens = new List <Ensures>();
                proccopy.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment)));
                proccopy.Ensures = newens;

                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    foreach (var blk in impl.Blocks)
                    {
                        for (int i = 0; i < blk.Cmds.Count; i++)
                        {
                            var ccmd = blk.Cmds[i] as CallCmd;
                            if (ccmd == null || ccmd.callee != procimpl.Name)
                            {
                                continue;
                            }
                            blk.Cmds[i] = new CallCmd(ccmd.tok, proccopy.Name, ccmd.Ins, ccmd.Outs, ccmd.Attributes);
                        }
                    }
                }

                program.AddTopLevelDeclaration(proccopy);
            }

            return(program);
        }