Ejemplo n.º 1
0
        //////////////////////////////////////////////
        // 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());
        }
Ejemplo n.º 2
0
        // 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));
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        // 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);
        }
Ejemplo n.º 5
0
        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);
                }
            }
        }
Ejemplo n.º 6
0
        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));
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        // 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);
        }