////////////////////////////////////////////// // Private guys -- need not bother about these ////////////////////////////////////////////// protected override Program getInput(ProgTransformation.PersistentProgram inp) { PersistentCBAProgram ap = inp as PersistentCBAProgram; Debug.Assert(ap != null); return(ap.getCBAProgram()); }
// Return the additional set of constants to keep HashSet <string> FindMin(PersistentProgram inprog, HashSet <string> candidates, Dictionary <string, int> constantToPerfDelta, ref int perf) { var iter = 1; var assignment = new HashSet <string>(); var additional = new HashSet <string>(); candidates = new HashSet <string>(candidates); while (candidates.Count != 0) { Console.WriteLine("------ ITER {0} -------", iter++); // Drop one and re-run var c = PickRandom(candidates); candidates.Remove(c); Console.WriteLine(" >> Trying {0}", c); int inlined = perf; var rt = PruneAndRun(inprog, candidates.Union(keep), out assignment, ref inlined); if (rt == BoogieVerify.ReturnStatus.OK) { // dropping was fine Console.WriteLine(" >> Dropping it and {0} others", (candidates.Count + keep.Count - assignment.Count)); constantToPerfDelta.Add(c, (inlined - perf)); // MustKeep is a subset of assignment, if no user annotation is given. // Under user annotations, mustkeep is really "should keep" //Debug.Assert(mustkeep.IsSubsetOf(assignment)); keep.IntersectWith(assignment); dropped.Add(c); dropped.UnionWith(candidates.Union(keep).Difference(assignment)); candidates = assignment; candidates.ExceptWith(keep); perf = inlined; Debug.Assert(!candidates.Contains(c)); } else { Console.WriteLine(" >> Cannot drop"); keep.Add(c); additional.Add(c); } //Log(iter); Console.WriteLine("Time elapsed: {0} sec", sw.Elapsed.TotalSeconds.ToString("F2")); } return(additional.Intersection(keep)); }
public PersistentCBAProgram run(PersistentCBAProgram inp) { var time1 = DateTime.Now; ProgTransformation.PersistentProgram outp = run(inp as ProgTransformation.PersistentProgram); var ret = outp as PersistentCBAProgram; var time2 = DateTime.Now; lastRun = (time2 - time1); return(ret); }
// 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); } } }
public ProofMin(PersistentProgram program) { keep = new HashSet <string>(); dropped = null; sw = new Stopwatch(); rand = new Random((int)DateTime.Now.Ticks); this.inprog = program; // logging program.writeToFile("pm_query" + (InvocationCounter++) + ".bpl"); // gather keep vars var prog = inprog.getProgram(); prog.TopLevelDeclarations.OfType <Constant>() .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, Driver.MustKeepAttr)) .Iter(c => keep.Add(c.Name)); }
static void Main(string[] args) { con = new Context(); string inFileName = null, unrolledFileName = null, tidRewrittenFileName = null, expandedFileName = null, annotatedFileName = null, splitFileName = null, yieldedFileName = null, instantiatedFileName = null, finalFileName = null, mhpFileName = null, hmifFileName = null; dbg = false; inFileName = parseCommandLine(args); string[] parts = inFileName.Split('.'); if (parts.Count() == 1) { unrolledFileName = inFileName + "_unrolled"; hmifFileName = inFileName + "_hmif"; expandedFileName = inFileName + "_expanded"; tidRewrittenFileName = inFileName + "_tidRewritten"; annotatedFileName = inFileName + "_annotated"; splitFileName = inFileName + "_split"; yieldedFileName = inFileName + "_yielded"; finalFileName = inFileName + "_final"; mhpFileName = inFileName + "_mhp"; instantiatedFileName = inFileName + "_inst"; } else { string name = parts[0]; unrolledFileName = name + "_unrolled"; hmifFileName = name + "_hmif"; expandedFileName = name + "_expanded"; annotatedFileName = name + "_annotated"; splitFileName = name + "_split"; yieldedFileName = name + "_yielded"; finalFileName = name + "_final"; mhpFileName = name + "_mhp"; instantiatedFileName = name + "_inst"; tidRewrittenFileName = name + "_tidRewritten"; for (int i = 1; i < parts.Count(); ++i) { unrolledFileName += "." + parts[i]; hmifFileName += "." + parts[i]; expandedFileName += "." + parts[i]; annotatedFileName += "." + parts[i]; splitFileName += "." + parts[i]; yieldedFileName += "." + parts[i]; finalFileName += "." + parts[i]; tidRewrittenFileName += "." + parts[i]; mhpFileName += "." + parts[i]; instantiatedFileName += "." + parts[i]; } } var tmpFileName = "og__tmp.bpl"; ExecutionEngine.printer = new ConsolePrinter(); //CommanLineOptions will control how boogie parses the program and gives us the IR CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.Parse(new string[] { }); CommandLineOptions.Clo.PrintInstrumented = true; CommandLineOptions.Clo.StratifiedInliningVerbose = 2; CommandLineOptions.Clo.UseArrayTheory = true; CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic; Program program; program = BoogieUtil.ReadAndOnlyResolve(inFileName); // TODO: assert that no procedure can be called in both sync and async mode! // Find entrypoint and initialize con var entry = program.TopLevelDeclarations.OfType <Procedure>() .Where(proc => QKeyValue.FindBoolAttribute(proc.Attributes, "entrypoint")) .FirstOrDefault(); if (entry == null) { Console.WriteLine("Warning: No entrypoint given"); con.entryFunc = null; } else { con.entryFunc = entry.Name; } // Remove unreachable procedures BoogieUtil.pruneProcs(program, con.entryFunc); // Extract loops if (extractLoops) { program.ExtractLoops(); } BoogieUtil.DoModSetAnalysis(program); if (pruneAsserts) { program = og.GuardAsserts(program); } if (injectYields) { program = og.InsertYields(program); } if (instantiateTemplates) { var inst = new TemplateInstantiator(program); inst.Instantiate(program); program = BoogieUtil.ReResolve(program, dbg ? instantiatedFileName : tmpFileName); } var sp = new SplitThreads(con, dbg); var hmif = new HowManyInstanceFinder(con, dbg); var split = new Converter <Program, Program>(sp.split); var findHowManyInstances = new Converter <Program, Program>(hmif.Compute); if (entry != null && splitThreads) { if (dbg) { Console.WriteLine("Splitting procedures on thread entry: {0}", splitFileName); } program = split(program); program = BoogieUtil.ReResolve(program, dbg ? hmifFileName : tmpFileName); program = findHowManyInstances(program); program = BoogieUtil.ReResolve(program, dbg ? splitFileName : tmpFileName); } // Get rid of corral_yield program = og.RemoveCorralYield(program, con.yieldProc); var yieldedProgram = new ProgTransformation.PersistentProgram(program); if (dbg) { Console.WriteLine("Instrumenting: {0}", annotatedFileName); } if (!noTid) { program = og.InstrumentTid(program); } program = og.InstrumentAtomicBlocks(program); if (instrumentPermissions) { program = og.InstrumentPermissions(program); } program = BoogieUtil.ReResolve(program, dbg ? annotatedFileName : tmpFileName); CommandLineOptions.Clo.ContractInfer = true; CommandLineOptions.Clo.AbstractHoudini = absDomain; CommandLineOptions.Clo.UseProverEvaluate = true; CommandLineOptions.Clo.ModelViewFile = "z3model"; Microsoft.Boogie.Houdini.AbstractDomainFactory.Initialize(program); // First, do sequential var answer = DoInference(program, InferenceMode.SEQUENTIAL, annotatedFileName, expandedFileName); program = BoogieUtil.ReadAndOnlyResolve(dbg ? annotatedFileName : tmpFileName); // prune "true" functions var progFuncs = new Dictionary <string, Function>(); program.TopLevelDeclarations.OfType <Function>() .Iter(f => progFuncs.Add(f.Name, f)); var truefuncs = new List <Function>(); foreach (var f in answer) { if (f.Body is LiteralExpr && (f.Body as LiteralExpr).IsTrue) { truefuncs.Add(f); var actualf = progFuncs[f.Name]; actualf.Attributes = BoogieUtil.removeAttr("existential", actualf.Attributes); actualf.Body = Expr.True; } } Console.WriteLine("Sequential check pruned away {0} functions, {1} remain", truefuncs.Count, answer.Count() - truefuncs.Count); // now do concurrent answer = DoInference(program, InferenceMode.CONCURRENT, annotatedFileName, expandedFileName); answer = answer.Concat(truefuncs); var provedAsserts = new Dictionary <string, bool>(); answer.Where(func => QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard")) .Iter(func => { var le = func.Body as LiteralExpr; System.Diagnostics.Debug.Assert(le != null); provedAsserts.Add(func.Name, le.IsFalse); }); // remove injected existential functions answer = answer.Where(func => !QKeyValue.FindBoolAttribute(func.Attributes, "chignore") && !QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard")); if (printAssignment) { using (var tt = new TokenTextWriter(Console.Out)) answer.ToList().Iter(func => func.Emit(tt, 0)); } if (dbg) { Console.WriteLine("Injecting invariants back into the original program: {0}", finalFileName); } program = yieldedProgram.getProgram(); // remove existential functions program.RemoveTopLevelDeclarations(decl => (decl is Function) && QKeyValue.FindBoolAttribute((decl as Function).Attributes, "existential")); program.AddTopLevelDeclarations(answer); program = og.PruneProvedAsserts(program, f => provedAsserts[f]); // Remove ensures and requires program = og.RemoveRequiresAndEnsures(program); // Remove tid func program = og.RemoveThreadIdFunc(program); using (Microsoft.Boogie.TokenTextWriter writer = new Microsoft.Boogie.TokenTextWriter(finalFileName)) program.Emit(writer); }
public override CBAProgram runCBAPass(CBAProgram p) { if (p.mode == ConcurrencyMode.FixedContext) { InstrumentationConfig.addRaiseException = false; } // Step1: Gather program information pinfo = new ProgramInfo(p.mainProcName, p, LanguageSemantics.assertNotReachableName()); TidArithmetic.reset(); if (pinfo.threadIdType.IsBv) { TidArithmetic.useIntArithmetic = false; p.AddTopLevelDeclaration(TidArithmetic.getBvAdd()); p.AddTopLevelDeclaration(TidArithmetic.getBvGt()); } else { TidArithmetic.useIntArithmetic = true; } // Step2: Set up a variable manager vmgr = new VariableManager(pinfo); // Step3: Set up the instrumentation policy // The globals not to instrument are: // -- ones not modified by any procedure // -- ones not shared // -- ones to treat as thread-local HashSet <string> globalsToInstrument = new HashSet <string>(); foreach (var g in pinfo.declaredGlobals) { string name = g.Key; if (!pinfo.modifiedGlobals.ContainsKey(name)) { continue; } if (!LanguageSemantics.isShared(name)) { continue; } if (pinfo.threadLocalGlobals.ContainsKey(name)) { continue; } globalsToInstrument.Add(name); } var rprocs = findRecursiveProcs(p); //foreach (var be in rprocs) Console.WriteLine("{0} -> {1}", be.Item1, be.Item2); policy = new InstrumentationPolicy(p.contextBound, globalsToInstrument, pinfo.procsWithImplementation, pinfo.asyncProcs, rprocs, p.mode); //policy.print(Log.getWriter(Log.Debug)); // Step4: Split program declarations based on the instrumentation policy // skipping this step (not needed for basic CBA reduction) // Step5: Carry out the K-split instrumentation inst = new Instrumenter(policy, vmgr, pinfo, tinfo_instrument); List <Declaration> newDecls = inst.instrument(p.TopLevelDeclarations.ToList()); foreach (var trp in inst.blocksWithFixedK) { blockExecutionContextMap.Add(trp.fst + "::" + trp.snd, trp.trd); } // Step6: Instrument main with initialization and the Checker Implementation mainProcImpl = BoogieUtil.findProcedureImpl(newDecls, p.mainProcName); inst.instrumentGivenMainImpl(mainProcImpl); // Step7: Instrument Async calls bool instrumentedAsync = false; InstrumentAsyncCalls ainst = new InstrumentAsyncCalls(vmgr, pinfo, tinfo_async); foreach (var decl in newDecls) { if (decl is Implementation) { ainst.VisitImplementation(decl as Implementation); instrumentedAsync = instrumentedAsync || ainst.hasAsync; } } if (!instrumentedAsync) { Log.WriteLine(Log.Debug, "Warning: Did not find any async call"); } // Step8: Set entrypoint mainProcImpl.AddAttribute("entrypoint"); // Step9: Add new variable declarations newDecls.AddRange(vmgr.getNewDeclarations(policy.executionContextBound)); newDecls.AddRange(BoogieAstFactory.newDecls); BoogieAstFactory.newDecls.Clear(); // Thats it. Program ret = new Program(); ret.TopLevelDeclarations = newDecls; if (InstrumentationConfig.printInstrumented) { // Re-resolve ret ProgTransformation.PersistentProgram tprog = new ProgTransformation.PersistentProgram(ret); var instrumented = tprog.getProgram(); // Re-do the modsets -- make them as concise as possible. BoogieUtil.DoModSetAnalysis(instrumented); // Temporary fix for Boogie's bug while inlining calls // that have don't care expressions. RewriteCallDontCares rdc = new RewriteCallDontCares(); rdc.VisitProgram(instrumented); BoogieUtil.PrintProgram(instrumented, InstrumentationConfig.instrumentedFile); throw new NormalExit("Printed " + InstrumentationConfig.instrumentedFile); } // Resolve the program (Do not typecheck because that does inlining). //BoogieUtil.PrintProgram(ret, "instrumented.bpl"); //ret = BoogieUtil.ReadAndOnlyResolve("instrumented.bpl"); if (p.mode == ConcurrencyMode.FixedContext) { InstrumentationConfig.addRaiseException = true; } p = new CBAProgram(ret, p.mainProcName, p.contextBound); return(p); }
// minimize disjunctions in the templates // Returns true if new constants were created // Add new templates (and existing ones for which new constants were created) to newTemplates public static bool PruneDisjuncts(int template, ref HashSet <int> newTemplates) { Console.WriteLine("Breaking down template {0}: {1}", template, templateToStr[template]); var newConstantsCreated = false; var files = new HashSet <string>(fileToProg.Keys); foreach (var file in files) { if (!templateMap[template].ContainsKey(file)) { continue; } var constants = templateMap[template][file].Difference(fileToKeepConstants[file]); if (constants.Count == 0) { continue; } var program = fileToProg[file].getProgram(); var newconstants = new List <Constant>(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { var newEnsures = new List <Ensures>(); foreach (var ens in impl.Proc.Ensures.Where(e => !e.Free)) { string constantName = null; Expr expr = null; var isloop = QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "LoopProcedure"); var match = Microsoft.Boogie.Houdini.Houdini.GetCandidateWithoutConstant( ens.Condition, constants, out constantName, out expr); if (!match) { continue; } var disjuncts = SimplifyExpr.GetExprDisjuncts(expr); if (disjuncts.Count == 1) { continue; } var pow = SimplifyExpr.GetPowSetDisjunctions(disjuncts); foreach (var d in pow) { var conjuncts = SimplifyExpr.GetExprConjunctions(d); foreach (var c in conjuncts) { var nc = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "PMnewConst" + (NewConstCounter++), btype.Bool), false); nc.AddAttribute("existential"); newconstants.Add(nc); templateMap[template][file].Add(nc.Name); //Console.WriteLine(" New constant created: {0}", nc.Name); newConstantsCreated = true; var e = Expr.Imp(Expr.Ident(nc), c); newEnsures.Add(new Ensures(false, e)); // Add template var temp = SimplifyExpr.ExprToTemplateGeneral(c); if (strToTemplate.ContainsKey(temp)) { // template for it exists addTemplate(strToTemplate[temp], file, nc.Name, Tuple.Create(isloop, c)); } else { // create new template int v = TemplateCounterStart + strToTemplate.Count; strToTemplate.Add(temp, v); templateToStr.Add(v, temp); addTemplate(strToTemplate[temp], file, nc.Name, Tuple.Create(isloop, c)); } if (!candidateToCost.ContainsKey(strToTemplate[temp])) { candidateToCost.Add(strToTemplate[temp], conjuncts.Count > 1 ? disjuncts.Count : disjuncts.Count - SimplifyExpr.GetExprDisjuncts(d).Count); } Console.WriteLine(" Template revived or created {0} :: {1} (cost = {2})", strToTemplate[temp], temp, candidateToCost[strToTemplate[temp]]); newTemplates.Add(strToTemplate[temp]); } } } impl.Proc.Ensures.AddRange(newEnsures); } program.AddTopLevelDeclarations(newconstants); fileToProg[file] = new PersistentProgram(program); } return(newConstantsCreated); }