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); }
// 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); }
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); }