// 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);
        }
예제 #2
0
        private PersistentCBAProgram instrument(PersistentCBAProgram pprogram, HashSet <string> candidates)
        {
            Debug.Assert(candidates.Count != 0);

            labelProcMap = new Dictionary <string, string>();
            var program     = pprogram.getProgram();
            var nameImplMap = BoogieUtil.nameImplMapping(program);

            // Each candidate gets its own variable
            var procVars = new Dictionary <string, Variable>();

            foreach (var str in candidates)
            {
                procVars.Add(str,
                             new GlobalVariable(Token.NoToken,
                                                new TypedIdent(Token.NoToken, "ep_var_" + str, Microsoft.Boogie.Type.Bool)));

                program.AddTopLevelDeclaration(procVars[str]);
            }

            // Add the new variables to each procedures' modifies clause
            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Implementation)
                {
                    var impl = decl as Implementation;
                    foreach (var str in candidates)
                    {
                        impl.Proc.Modifies.Add(new IdentifierExpr(Token.NoToken, procVars[str]));
                    }
                }
            }

            // Instrument program
            foreach (var str in candidates)
            {
                var impl  = nameImplMap[str];
                var ncmds = new List <Cmd>();
                ncmds.Add(BoogieAstFactory.MkVarEqConst(procVars[str], false));
                ncmds.AddRange(impl.Blocks[0].Cmds);

                impl.Blocks[0].Cmds = ncmds;
            }

            // Instrument main.
            // -- Assign true to the new variables
            // -- Change the assert
            //    (We assume that main only has one assert)

            var mainImpl = nameImplMap[pprogram.mainProcName];
            var newCmds  = new List <Cmd>();

            foreach (var str in candidates)
            {
                newCmds.Add(BoogieAstFactory.MkVarEqConst(procVars[str], true));
            }
            newCmds.AddRange(mainImpl.Blocks[0].Cmds);
            mainImpl.Blocks[0].Cmds = newCmds;

            // Find the assert
            Block     blkWithAssert = null;
            AssertCmd assertCmd     = null;
            bool      found         = false;

            foreach (var blk in mainImpl.Blocks)
            {
                found = false;
                foreach (var cmd in blk.Cmds)
                {
                    if (cmd is AssertCmd)
                    {
                        assertCmd = cmd as AssertCmd;
                        found     = true;
                        break;
                    }
                }

                if (found)
                {
                    blkWithAssert = blk;
                    break;
                }
            }

            Debug.Assert(blkWithAssert != null);

            // Construct the new blocks
            var newLabs = new Dictionary <string, string>();
            var restLab = getNewLabel();

            foreach (var str in candidates)
            {
                newLabs.Add(str, getNewLabel());
                var tcmds = new List <Cmd>();

                tcmds.Add(new AssertCmd(Token.NoToken, Expr.Or(Expr.Ident(procVars[str]), assertCmd.Expr)));

                mainImpl.Blocks.Add(new Block(Token.NoToken, newLabs[str], tcmds, BoogieAstFactory.MkGotoCmd(restLab)));
            }

            // change blkWithAssert to include only commands upto the assert
            // Add the rest of commands to a new block
            found   = false;
            newCmds = new List <Cmd>();
            var newBlk = new Block(Token.NoToken, restLab, new List <Cmd>(), blkWithAssert.TransferCmd);

            foreach (Cmd cmd in blkWithAssert.Cmds)
            {
                if (cmd is AssertCmd)
                {
                    found = true;
                    continue;
                }
                if (!found)
                {
                    newCmds.Add(cmd);
                }
                else
                {
                    newBlk.Cmds.Add(cmd);
                }
            }
            blkWithAssert.Cmds = newCmds;
            var targets = new List <String>(newLabs.Values.ToArray());

            blkWithAssert.TransferCmd = new GotoCmd(Token.NoToken, targets);

            mainImpl.Blocks.Add(newBlk);

            var ret = new PersistentCBAProgram(program, pprogram.mainProcName, pprogram.contextBound);

            //ret.writeToFile("ep_instrumented.bpl");

            return(ret);
        }
예제 #3
0
        private string addTraceRec(ErrorTrace trace)
        {
            Debug.Assert(trace.Blocks.Count != 0);

            // First, construct the procedure declaration: only a name change required
            string    newName = getNewName(trace.procName);
            Procedure proc    = nameToProc[trace.procName];

            output.AddTopLevelDeclaration(
                new Procedure(Token.NoToken, newName, proc.TypeParameters, proc.InParams,
                              proc.OutParams, proc.Requires, proc.Modifies, proc.Ensures,
                              proc.Attributes));

            // Now to peice together the commands from the implementation. We keep around
            // multiple blocks to make sure that trace mapping works out.
            var traceBlocks = new List <Block>();

            Implementation impl = nameToImpl[trace.procName];

            var labelToBlock = BoogieUtil.labelBlockMapping(impl);

            // These two need not agree. This happens when impl.Block[0] has
            // no commands.
            // Debug.Assert(impl.Blocks[0].Label == trace.Blocks[0].blockName);
            Debug.Assert(reachableViaEmptyBlocks(impl.Blocks[0].Label, labelToBlock).Contains(trace.Blocks[0].blockName));

            for (int i = 0, n = trace.Blocks.Count; i < n; i++)
            {
                Block curr = labelToBlock[trace.Blocks[i].blockName];

                Block traceBlock = new Block();
                traceBlock.Cmds  = new List <Cmd>();
                traceBlock.Label = addIntToString(trace.Blocks[i].blockName, i); // (The "i" is to deal with loops)
                if (i != n - 1)
                {
                    traceBlock.TransferCmd = BoogieAstFactory.MkGotoCmd(addIntToString(trace.Blocks[i + 1].blockName, i + 1));
                }
                else
                {
                    traceBlock.TransferCmd = new ReturnCmd(Token.NoToken);
                }
                tinfo.addTrans(newName, trace.Blocks[i].blockName, traceBlock.Label);

                #region Check consistency
                Debug.Assert(curr.Cmds.Count >= trace.Blocks[i].Cmds.Count);
                if (trace.Blocks[i].Cmds.Count != curr.Cmds.Count)
                {
                    Debug.Assert((i == n - 1));
                }

                if (curr.TransferCmd is ReturnCmd)
                {
                    Debug.Assert(i == n - 1);
                }
                else if (curr.TransferCmd is GotoCmd)
                {
                    List <String> targets = (curr.TransferCmd as GotoCmd).labelNames;
                    // one of these targets should be the next label
                    if (i != n - 1)
                    {
                        Debug.Assert(reachableViaEmptyBlocks(targets, labelToBlock).Contains(trace.Blocks[i + 1].blockName));
                    }
                }
                else
                {
                    throw new InternalError("Unknown transfer command");
                }
                #endregion

                // Index into trace.Blocks[i].Cmds
                int instrCount = -1;

                foreach (Cmd c in curr.Cmds)
                {
                    instrCount++;
                    if (instrCount == trace.Blocks[i].Cmds.Count)
                    {
                        break;
                    }

                    ErrorTraceInstr curr_instr = trace.Blocks[i].Cmds[instrCount];
                    if (curr_instr.info.isValid)
                    {
                        traceBlock.Cmds.Add(InstrumentationConfig.getFixedContextProc(curr_instr.info.executionContext));
                        newFixedContextProcs.Add(curr_instr.info.executionContext);
                    }

                    // Don't keep "fix context value" procs from the input program
                    if (InstrumentationConfig.getFixedContextValue(c) != -1)
                    {
                        traceBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.True));
                        addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);
                        continue;
                    }

                    // Don't keep "fix raise exception" procs from the input program
                    if (InstrumentationConfig.isFixedRaiseExceptionProc(c))
                    {
                        traceBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.True));
                        addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);
                        continue;
                    }

                    if (addConcretization && c is HavocCmd && curr_instr.info != null && curr_instr.info.hasIntVar("si_arg") &&
                        (c as HavocCmd).Vars.Count > 0 && (c as HavocCmd).Vars[0].Decl.TypedIdent.Type.IsInt)
                    {
                        // concretize havoc-ed variable
                        var val = curr_instr.info.getIntVal("si_arg");
                        traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst((c as HavocCmd).Vars[0].Decl, val));
                        addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);
                        continue;
                    }

                    if (!(c is CallCmd))
                    {
                        if (convertNonFailingAssertsToAssumes && c is AssertCmd && !(curr_instr.info is AssertFailInstrInfo))
                        {
                            traceBlock.Cmds.Add(new AssumeCmd(c.tok, (c as AssertCmd).Expr, (c as AssertCmd).Attributes));
                        }
                        else
                        {
                            traceBlock.Cmds.Add(c);
                        }
                        Debug.Assert(!curr_instr.isCall());
                        addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);

                        continue;
                    }
                    Debug.Assert(curr_instr.isCall());

                    CallCmd   cc         = c as CallCmd;
                    CallInstr call_instr = curr_instr as CallInstr;

                    if (!nameToImpl.ContainsKey(cc.Proc.Name) || !call_instr.hasCalledTrace)
                    {
                        // This is a call to a procedure without implementation; skip;
                        calledProcsNoImpl.Add(cc.Proc.Name);
                        traceBlock.Cmds.Add(c);
                        Debug.Assert(!call_instr.hasCalledTrace);
                        if (addConcretization && cc.Outs.Count == 1 && call_instr.info.hasVar("si_arg"))
                        {
                            if (!addConcretizationAsConstants)
                            {
                                if (call_instr.info.hasBoolVar("si_arg"))
                                {
                                    traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst(cc.Outs[0].Decl, call_instr.info.getBoolVal("si_arg")));
                                }
                                else if (call_instr.info.hasIntVar("si_arg"))
                                {
                                    traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst(cc.Outs[0].Decl, call_instr.info.getIntVal("si_arg")));
                                }
                                else
                                {
                                    Debug.Assert(false);
                                }
                            }
                            else
                            {
                                // create a constant that is equal to this literal, then use the constant
                                // for concretization

                                // do we use a specific name for the constant?
                                var constantName = QKeyValue.FindStringAttribute(cc.Attributes, ConcretizeConstantNameAttr);
                                if (constantName == null)
                                {
                                    constantName = "";
                                }

                                var constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
                                                                                          string.Format("alloc_{0}__{1}", constantName, const_counter), cc.Outs[0].Decl.TypedIdent.Type), false);
                                const_counter++;

                                traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqVar(cc.Outs[0].Decl, constant));
                                output.AddTopLevelDeclaration(constant);

                                if (call_instr.info.hasIntVar("si_arg"))
                                {
                                    output.AddTopLevelDeclaration(new Axiom(Token.NoToken, Expr.Eq(Expr.Ident(constant), Expr.Literal(call_instr.info.getIntVal("si_arg")))));
                                }
                                else if (call_instr.info.hasVar("si_arg") && cc.Outs[0].Decl.TypedIdent.Type.IsCtor)
                                {
                                    uvalueToConstants.InitAndAdd(call_instr.info.getVal("si_arg").ToString(), constant);
                                }

                                var id = QKeyValue.FindIntAttribute(cc.Attributes, ConcretizeCallIdAttr, -1);
                                concretizeConstantToCall.Add(constant.Name, id);
                            }
                        }
                        addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);
                        continue;
                    }

                    Debug.Assert(call_instr.calleeTrace.procName == cc.Proc.Name);
                    var callee = addTraceRec(call_instr.calleeTrace);

                    var newcmd = new CallCmd(Token.NoToken, callee, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync);
                    traceBlock.Cmds.Add(newcmd);
                    addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds);
                }
                traceBlocks.Add(traceBlock);
            }

            Debug.Assert(traceBlocks.Count != 0);
            if (trace.raisesException)
            {
                var exitblk = traceBlocks.Last();
                exitblk.Cmds.Add(InstrumentationConfig.getFixedRaiseExceptionProc());
                addRaiseExceptionProcDecl = true;
            }

            // Add the implementation to output
            //var block = new Block(Token.NoToken, trace.Blocks[0].blockName, traceCmdSeq, new ReturnCmd(Token.NoToken));
            //List<Block> blocks = new List<Block>();
            //blocks.Add(block);

            //tinfo.addTrans(newName, trace.Blocks[0].blockName, trace.Blocks[0].blockName);
            tinfo.addProcNameTrans(trace.procName, newName);

            output.AddTopLevelDeclaration(
                new Implementation(Token.NoToken, newName, impl.TypeParameters,
                                   impl.InParams, impl.OutParams, impl.LocVars, traceBlocks,
                                   QKeyValue.FindStringAttribute(impl.Attributes, "origRTname") == null ?
                                   new QKeyValue(Token.NoToken, "origRTname", new List <object> {
                impl.Name
            }, impl.Attributes)
                    : impl.Attributes));

            return(newName);
        }
예제 #4
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);
        }