// Prune away non-candidates, verify using the rest static BoogieVerify.ReturnStatus PruneAndRun(PersistentProgram inp, HashSet <string> candidates, out HashSet <string> assignment, ref int inlined) { var program = inp.getProgram(); program.Typecheck(); program = BoogieUtil.ReResolve(program); // Remove non-candidates CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, candidates, true); program.RemoveTopLevelDeclarations(decl => (decl is Constant) && QKeyValue.FindBoolAttribute(decl.Attributes, "existential") && !candidates.Contains((decl as Constant).Name)); //BoogieUtil.PrintProgram(program, "hi_query" + IterCnt + ".bpl"); // Run Houdini var ot = CommandLineOptions.Clo.ProverKillTime; CommandLineOptions.Clo.ProverKillTime = HoudiniTimeout; assignment = CoreLib.HoudiniInlining.RunHoudini(program, true); CommandLineOptions.Clo.ProverKillTime = ot; //Console.WriteLine(" >> Contracts: {0}", assignment.Count); // Read the program again, add contracts program = inp.getProgram(); program.Typecheck(); CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, assignment); //BoogieUtil.PrintProgram(program, "si_query" + IterCnt + ".bpl"); // Run SI var err = new List <BoogieErrorTrace>(); // Set bound BoogieVerify.options.maxInlinedBound = 0; if (inlined != 0) { BoogieVerify.options.maxInlinedBound = PerfMetric(inlined); } var rstatus = BoogieVerify.Verify(program, out err, true); //Console.WriteLine(string.Format(" >> Procedures Inlined: {0}", BoogieVerify.CallTreeSize)); //Console.WriteLine(string.Format("Boogie verification time: {0} s", BoogieVerify.verificationTime.TotalSeconds.ToString("F2"))); inlined = BoogieVerify.CallTreeSize + 1; BoogieVerify.options.CallTree = new HashSet <string>(); BoogieVerify.CallTreeSize = 0; BoogieVerify.verificationTime = TimeSpan.Zero; return(rstatus); }
public static void RunOnce(PersistentProgram inprog, bool printcontracts) { var program = inprog.getProgram(); program.Typecheck(); BoogieUtil.PrintProgram(program, "hi_query.bpl"); Console.WriteLine("Running HoudiniLite"); var assignment = CoreLib.HoudiniInlining.RunHoudini(program, true); Console.WriteLine("Inferred {0} contracts", assignment.Count); // Read the program again, add contracts program = inprog.getProgram(); program.Typecheck(); var contracts = CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, assignment); BoogieUtil.PrintProgram(program, "si_query.bpl"); // Run SI var err = new List <BoogieErrorTrace>(); var rstatus = BoogieVerify.Verify(program, out err, true); Console.WriteLine("SI Return status: {0}", rstatus); if (err == null || err.Count == 0) { Console.WriteLine("program verified"); } else { foreach (var trace in err.OfType <BoogieAssertErrorTrace>()) { Console.WriteLine("{0} did not verify", trace.impl.Name); //if (!config.noTrace) trace.cex.Print(0, Console.Out); } } Console.WriteLine(string.Format("Procedures Inlined: {0}", BoogieVerify.CallTreeSize)); Console.WriteLine(string.Format("Boogie verification time: {0} s", BoogieVerify.verificationTime.TotalSeconds.ToString("F2"))); if (printcontracts) { foreach (var tup in contracts) { Console.WriteLine("{0}: {1}", tup.Key, tup.Value); } } }
// Prune away non-candidates, verify using the rest static BoogieVerify.ReturnStatus PruneAndRun(HashSet <int> candidateTemplates, out Dictionary <string, int> perf, out HashSet <string> filesVerified, out string fileFailed) { perf = new Dictionary <string, int>(); filesVerified = new HashSet <string>(); fileFailed = null; var rest = new HashSet <string>(fileToProg.Keys); rest.ExceptWith(PreviousRunFailures); foreach (var file in PreviousRunFailures.Concat <string>(rest)) { var program = fileToProg[file].getProgram(); program.Typecheck(); // all constants var allconstants = new HashSet <string>( program.TopLevelDeclarations.OfType <Constant>() .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, "existential")) .Select(c => c.Name)); // candidate constants var candidates = new HashSet <string>(); candidateTemplates.Where(t => templateMap[t].ContainsKey(file)) .Iter(t => candidates.UnionWith(templateMap[t][file])); // to keep var keep = fileToKeepConstants[file].Intersection(allconstants); var cache_try = new HashSet <string>(candidates.Concat(keep)); IterCnt++; if (PreviousRun.ContainsKey(file)) { var cache_entry = PreviousRun[file]; if (cache_try.Count == cache_entry.Item1.Count && cache_entry.Item1.SetEquals(cache_try)) { CacheHit++; filesVerified.Add(file); perf[file] = cache_entry.Item2; continue; } } // drop DropConstants(program, allconstants.Difference(candidates.Union(keep))); // Run Houdini var ot = CommandLineOptions.Clo.ProverKillTime; CommandLineOptions.Clo.ProverKillTime = HoudiniTimeout; var assignment = CoreLib.HoudiniInlining.RunHoudini(program, true); CommandLineOptions.Clo.ProverKillTime = ot; //Console.WriteLine(" >> Contracts: {0}", assignment.Count); // Read the program again, add contracts program = fileToProg[file].getProgram(); program.Typecheck(); // Enforce the assignment back into the program CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, assignment); // Run SI var err = new List <BoogieErrorTrace>(); // Set bound BoogieVerify.options.maxInlinedBound = 0; if (fileToPerf[file] != 0) { BoogieVerify.options.maxInlinedBound = PerfMetric(fileToPerf[file]); } var rstatus = BoogieVerify.Verify(program, out err, true); if (dbg) { Console.WriteLine(string.Format(" >> Procedures Inlined: {0} / {1}", BoogieVerify.CallTreeSize, BoogieVerify.options.maxInlinedBound)); Console.WriteLine(string.Format("Boogie verification time: {0} s", BoogieVerify.verificationTime.TotalSeconds.ToString("F2"))); } var procs_inlined = BoogieVerify.CallTreeSize + 1; BoogieVerify.options.CallTree = new HashSet <string>(); BoogieVerify.CallTreeSize = 0; BoogieVerify.verificationTime = TimeSpan.Zero; if (rstatus != BoogieVerify.ReturnStatus.OK) { fileFailed = file; PreviousRunFailures.Add(file); return(BoogieVerify.ReturnStatus.NOK); } perf[file] = procs_inlined; filesVerified.Add(file); // cache if (rstatus == BoogieVerify.ReturnStatus.OK) { PreviousRun[file] = Tuple.Create(cache_try, procs_inlined); } } return(BoogieVerify.ReturnStatus.OK); }
public static Dictionary <string, int> Compute(CBAProgram program, int max, List <string> Annotations, BoogieVerifyOptions options) { var loopBounds = new Dictionary <string, int>(); Initialize(Annotations); maxBound = max; var start = DateTime.Now; // remove non-free ensures and requires program.TopLevelDeclarations.OfType <Procedure>() .Iter(proc => proc.Ensures = proc.Ensures.Filter(en => en.Free)); program.TopLevelDeclarations.OfType <Procedure>() .Iter(proc => proc.Requires = proc.Requires.Filter(en => en.Free)); // remove assertions program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds = blk.Cmds.Map(c => { var ac = c as AssertCmd; if (ac == null) { return(c); } return(new AssumeCmd(ac.tok, /*ac.Expr*/ Expr.True, ac.Attributes)); }))); // delete yield program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.RemoveAll(c => c is YieldCmd))); // Call graph ComputeCallGraph(program); // Gather the set of implementations with "loop" inside their name var allLoopImpls = new List <Implementation>(); program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => { if (impl.Name.Contains("loop")) { allLoopImpls.Add(impl); } }); // Prune to the right form var loopImpls = allLoopImpls.Filter(CheckImpl); #region Process user annotations // Include user anntations var allLoops = new HashSet <string>(); loopImpls.Iter(impl => allLoops.Add(impl.Name)); foreach (var sp in UserAnnotations .Where(s => s.StartsWith("LB:")) .Select(s => s.Split(':')) .Where(sp => sp.Length == 3)) { // grab bound var bound = 0; if (!Int32.TryParse(sp[2], out bound)) { continue; } // grab proc if (!allLoops.Contains(sp[1])) { continue; } loopBounds[sp[1]] = bound; Console.WriteLine("LB: Loop {0} requires minimum {1} iterations (annotated)", sp[1], bound); } loopImpls = loopImpls.Filter(impl => !loopBounds.ContainsKey(impl.Name)); #endregion if (loopImpls.Count == 0) { return(loopBounds); } // Prepare query var query = PrepareQuery(loopImpls, program); // Set general options BoogieVerify.options = options; // Set rec. bound var oldBound = CommandLineOptions.Clo.RecursionBound; CommandLineOptions.Clo.RecursionBound = maxBound; // Query var allErrors = new List <BoogieErrorTrace>(); BoogieVerify.Verify(query, out allErrors); foreach (var trace in allErrors) { var loopName = QKeyValue.FindStringAttribute(trace.impl.Attributes, "LB_Mapping"); var bound = RecBound(loopName, trace.cex, trace.impl.Name); if (bound <= 1) { continue; } loopBounds.Add(loopName, bound); Console.WriteLine("LB: Loop {0} requires minimum {1} iterations", loopName, bound); } CommandLineOptions.Clo.RecursionBound = oldBound; timeTaken = (DateTime.Now - start); return(loopBounds); }