public static PersistentProgram RunHoudiniPass(PersistentProgram prog) { Stats.resume("houdini"); HashSet <Variable> templateVars = new HashSet <Variable>(); List <Requires> reqs = new List <Requires>(); List <Ensures> enss = new List <Ensures>(); SimpleHoudini houdini = new SimpleHoudini(templateVars, reqs, enss, -1, -1); houdini.ExtractLoops = true; SimpleHoudini.fastRequiresInference = false; //SimpleHoudini.checkAsserts = true; houdini.printHoudiniQuery = null; // "candidates.bpl"; // turnning on several switches: InImpOutNonNull + InNonNull infer most assertions houdini.InImpOutNonNull = false; houdini.InImpOutNull = false; houdini.InNonNull = false; houdini.OutNonNull = false; houdini.addContracts = false; prog.writeToFile("beforeHoudini.bpl"); PersistentProgram newP = houdini.run(prog); newP.writeToFile("afterHoudini.bpl"); //BoogieUtil.PrintProgram(newP.getProgram(), "afterHoudini.bpl"); Utils.Print("End Houdini Pass ..."); Stats.stop("houdini"); return(newP); }
// Run Alias Analysis on a sequential Boogie program // and returned the pruned program public static PersistentProgram RunAliasAnalysis(PersistentProgram inp, bool pruneEP = true) { var newinp = inp; if (Options.unrollDepth > 0) { Stats.resume("unroll"); var unrp = new cba.LoopUnrollingPass(Options.unrollDepth); newinp = unrp.run(newinp); Stats.stop("unroll"); } var program = newinp.getProgram(); //AliasAnalysis.AliasAnalysis.dbg = true; //AliasAnalysis.AliasConstraintSolver.dbg = true; AliasAnalysis.AliasAnalysisResults res = null; if (Options.UseAliasAnalysisForAssertions) { // Do SSA program = SSA.Compute(program, PhiFunctionEncoding.Verifiable, new HashSet <string> { "int" }); if (Options.inlineDepth > 0) { Stats.resume("inlining"); Stats.resume("read.write"); program = BoogieUtil.ReResolveInMem(program); Stats.stop("read.write"); var op = CommandLineOptions.Clo.InlineDepth; CommandLineOptions.Clo.InlineDepth = Options.inlineDepth; cba.InliningPass.InlineToDepth(program); CommandLineOptions.Clo.InlineDepth = op; RemoveHavocs(program); Stats.stop("inlining"); } /* TODO: Is this needed? * Stats.resume("read.write"); * program = BoogieUtil.ReResolveInMem(program); * Stats.stop("read.write"); */ // Make sure that aliasing queries are on identifiers only var af = AliasAnalysis.SimplifyAliasingQueries.Simplify(program); Stats.resume("fixpoint"); res = AliasAnalysis.AliasAnalysis.DoAliasAnalysis(program); Stats.stop("fixpoint"); } else { // Make sure that aliasing queries are on identifiers only var af = AliasAnalysis.SimplifyAliasingQueries.Simplify(program); res = new AliasAnalysis.AliasAnalysisResults(); af.Iter(s => res.aliases.Add(s, true)); } var origProgram = inp.getProgram(); AliasAnalysis.PruneAliasingQueries.Prune(origProgram, res); if (pruneEP) { PruneRedundantEntryPoints(origProgram); } return(new PersistentProgram(origProgram, inp.mainProcName, inp.contextBound)); }
static void Main(string[] args) { System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.Batch; if (args.Length < 2 || !args[0].EndsWith(".bpl") || !args[1].EndsWith(".bpl")) { Console.WriteLine("Usage: AvHarnessInstrumentation infile.bpl outfile.bpl [options]"); return; } SetOptions(args); // Initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; BoogieUtil.InitializeBoogie(""); ProgTransformation.PersistentProgramIO.useDuplicator = true; var sw = new Stopwatch(); sw.Start(); if (Options.killAfter > 0) { var timer = new System.Timers.Timer(Options.killAfter * 1000); timer.Elapsed += (sender, e) => HandleTimer(sw); timer.Start(); } try { // Get the program, install the harness and do basic instrumentation var inprog = GetProgram(args[0]); Utils.Print(string.Format("#Procs : {0}", inprog.TopLevelDeclarations.OfType <Implementation>().Count()), Utils.PRINT_TAG.AV_STATS); Utils.Print(string.Format("#EntryPoints : {0}", harnessInstrumentation.entrypoints.Count), Utils.PRINT_TAG.AV_STATS); Utils.Print(string.Format("#AssertsBeforeAA : {0}", AssertCountVisitor.Count(inprog)), Utils.PRINT_TAG.AV_STATS); if (Options.delayAA) { PruneRedundantEntryPoints(inprog); BoogieUtil.PrintProgram(inprog, args[1]); } else { var program = new PersistentProgram(inprog, AvnAnnotations.CORRAL_MAIN_PROC, 0); // Run alias analysis Stats.resume("alias.analysis"); Console.WriteLine("Running alias analysis"); program = RunAliasAnalysis(program); Stats.stop("alias.analysis"); var assertCnt = AssertCountVisitor.Count(program.getProgram()); Utils.Print(string.Format("#AssertsAfterAA : {0}", assertCnt), Utils.PRINT_TAG.AV_STATS); // run Houdini pass if (Options.HoudiniPass) { Utils.Print("Running Houdini Pass"); program = RunHoudiniPass(program); assertCnt = AssertCountVisitor.Count(program.getProgram()); Utils.Print(string.Format("#Asserts : {0}", assertCnt), Utils.PRINT_TAG.AV_STATS); } if (assertCnt == 0) { // program has been proved correct // Write a trivial program System.IO.File.WriteAllLines(args[1], new string[] { "procedure {:entrypoint} {:NoVerificationNecessary} dummy() { }" }); } else { program.writeToFile(args[1]); } } } catch (Exception e) { //stacktrace containts source locations, confuses regressions that looks for AV_OUTPUT Utils.Print(String.Format("AngelicVerifier failed with: {0}", e.Message), Utils.PRINT_TAG.AV_OUTPUT); Utils.Print(String.Format("AngelicVerifier failed with: {0}", e.Message + e.StackTrace), Utils.PRINT_TAG.AV_DEBUG); } finally { Stats.printStats(); Utils.Print(string.Format("TotalTime(ms) : {0}", sw.ElapsedMilliseconds), Utils.PRINT_TAG.AV_STATS); } }
// Replace "assume x == NULL" with "assume x == NULL; assert false;" // provided x can indeed alias NULL // Also returns a map from allocation_site to possible branches affected by it public static Tuple <Program, Dictionary <int, HashSet <int> > > Run(Program program, string ep, bool useAA, bool injectAssert) { var ib = new InstrumentBranches(program, useAA, injectAssert); ib.instrument(ep); if (!useAA) { Console.WriteLine("For deadcode detection, we added {0} angelic assertions", ib.assertsAdded); return(Tuple.Create <Program, Dictionary <int, HashSet <int> > >(program, null)); } var inp = new PersistentProgram(program, ep, 1); //inp.writeToFile("progbefore.bpl"); // Make sure that aliasing queries are on identifiers only var af = AliasAnalysis.SimplifyAliasingQueries.Simplify(program); // Do SSA program = SSA.Compute(program, PhiFunctionEncoding.Verifiable, new HashSet <string> { "int" }); //BoogieUtil.PrintProgram(program, "b3.bpl"); // Run AA AliasAnalysis.AliasAnalysisResults res = AliasAnalysis.AliasAnalysis.DoAliasAnalysis(program); // allocation site of null var nil = res.allocationSites[ib.nullQuery.Name].FirstOrDefault(); Debug.Assert(nil != null); var deadcodeAssertId = 0; // add the assert false OR assume reach(true) var MkAssertFalse = new Func <int, PredicateCmd>(i => { var acmd = injectAssert ? BoogieAstFactory.MkAssert(Expr.False) as PredicateCmd : new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken, new FunctionCall(ib.reach), new List <Expr> { Expr.True })) as PredicateCmd; acmd.Attributes = new QKeyValue(Token.NoToken, "deadcode", new List <object> { Expr.Literal(i) }, null); return(acmd); }); // build a map from AA allocation sites to allocation_site id var as2id = new Dictionary <string, HashSet <int> >(); foreach (var tup in ib.allocationSite2Func) { var asites = res.allocationSites[tup.Value.Name]; asites.Where(s => !as2id.ContainsKey(s)).Iter(s => as2id.Add(s, new HashSet <int>())); asites.Iter(s => as2id[s].Add(tup.Key)); } if (AliasAnalysis.AliasConstraintSolver.environmentPointersUnroll != 0) { Console.WriteLine("AA Warning: EnvironmentPointersUnroll is non-zero, which means that the dependency information for deadcode branches is not sound."); Console.WriteLine("AA Warning: We currently rely on: forall unknown allocation sites that return a, ReachableAllocationSitesViaFields(a) = {a}."); } // map from allocation_site to possible branches affected by it var depInfo = new Dictionary <int, HashSet <int> >(); program = inp.getProgram(); var id = 0; var added = 0; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { blk.Cmds.RemoveAll(c => (c is AssumeCmd) && QKeyValue.FindBoolAttribute((c as AssumeCmd).Attributes, "ForDeadCodeDetection")); var ncmds = new List <Cmd>(); for (int i = 0; i < blk.Cmds.Count; i++) { ncmds.Add(blk.Cmds[i]); var acmd = blk.Cmds[i] as AssumeCmd; if (acmd == null) { continue; } id++; if (!ib.id2Func.ContainsKey(id)) { continue; } var asites = res.allocationSites[ib.id2Func[id].Name]; //if (!Options.disbleDeadcodeOpt || !asites.Contains(nil) && asites.Count != 0) { var assertid = deadcodeAssertId++; ncmds.Add(MkAssertFalse(assertid)); // compute dependent allocations for this branch var dep = new HashSet <int>(); asites.Where(a => as2id.ContainsKey(a)) .Iter(a => dep.UnionWith(as2id[a])); dep.Where(d => !depInfo.ContainsKey(d)) .Iter(d => depInfo.Add(d, new HashSet <int>())); dep.Iter(d => depInfo[d].Add(assertid)); added++; } //i++; } blk.Cmds = ncmds; } } //BoogieUtil.PrintProgram(program, "progafter.bpl"); Console.WriteLine("For deadcode detection, we added {0} angelic assertions", added); return(Tuple.Create(program, depInfo)); }
static void Main(string[] args) { System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.Batch; if (args.Length < 2 || !args[0].EndsWith(".bpl") || !args[1].EndsWith(".bpl")) { Console.WriteLine("Usage: AvHarnessInstrumentation infile.bpl outfile.bpl [options]"); return; } SetOptions(args); // Initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; BoogieUtil.InitializeBoogie(""); ProgTransformation.PersistentProgramIO.useDuplicator = true; var sw = new Stopwatch(); sw.Start(); try { // Get the program, install the harness and do basic instrumentation var inprog = GetProgram(args[0]); var program = new PersistentProgram(inprog, AvnAnnotations.CORRAL_MAIN_PROC, 0); Utils.Print(string.Format("#Procs : {0}", inprog.TopLevelDeclarations.OfType <Implementation>().Count()), Utils.PRINT_TAG.AV_STATS); Utils.Print(string.Format("#EntryPoints : {0}", harnessInstrumentation.entrypoints.Count), Utils.PRINT_TAG.AV_STATS); Utils.Print(string.Format("#AssertsBeforeAA : {0}", AssertCountVisitor.Count(inprog)), Utils.PRINT_TAG.AV_STATS); // Run alias analysis Stats.resume("alias.analysis"); Console.WriteLine("Running alias analysis"); program = RunAliasAnalysis(program); Stats.stop("alias.analysis"); Utils.Print(string.Format("#AssertsAfterAA : {0}", AssertCountVisitor.Count(program.getProgram())), Utils.PRINT_TAG.AV_STATS); // run Houdini pass if (Options.HoudiniPass) { Utils.Print("Running Houdini Pass"); program = RunHoudiniPass(program); Utils.Print(string.Format("#Asserts : {0}", AssertCountVisitor.Count(program.getProgram())), Utils.PRINT_TAG.AV_STATS); } program.writeToFile(args[1]); } catch (Exception e) { //stacktrace containts source locations, confuses regressions that looks for AV_OUTPUT Utils.Print(String.Format("AngelicVerifier failed with: {0}", e.Message), Utils.PRINT_TAG.AV_OUTPUT); Utils.Print(String.Format("AngelicVerifier failed with: {0}", e.Message + e.StackTrace), Utils.PRINT_TAG.AV_DEBUG); } finally { Stats.printStats(); Utils.Print(string.Format("TotalTime(ms) : {0}", sw.ElapsedMilliseconds), Utils.PRINT_TAG.AV_STATS); } }
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); }