示例#1
0
        public static HashSet <string> RunHoudini(Program program, bool RobustAgainstEvaluate = false)
        {
            HoudiniStats.Reset();
            HoudiniInlining.RobustAgainstEvaluate = DualHoudini? false : RobustAgainstEvaluate;
            if (DualHoudini && CommandLineOptions.Clo.InlineDepth > 0)
            {
                throw new DualHoudiniFail("InlineDepth not supported");
            }

            // Gather existential constants
            var CandidateConstants = new Dictionary <string, Constant>();

            program.TopLevelDeclarations.OfType <Constant>()
            .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, "existential"))
            .Iter(c => CandidateConstants.Add(c.Name, c));

            // Create a function, one for each impl, for book-keeping
            var CandidateFuncsAssumed  = new Dictionary <string, Function>();
            var CandidateFuncsAsserted = new Dictionary <string, Function>();
            var AssumeToAssert         = new Dictionary <Function, Function>();

            program.TopLevelDeclarations.OfType <Implementation>()
            .Iter(impl =>
            {
                var fassumed  = GetCandidateFunc(CandidateFuncPrefix, impl.Name);
                var fasserted = GetCandidateFunc(CandidateFuncAssertedPrefix, impl.Name);
                CandidateFuncsAssumed.Add(impl.Name, fassumed);
                CandidateFuncsAsserted.Add(impl.Name, fasserted);
                AssumeToAssert.Add(fassumed, fasserted);
            });


            // Tag the ensures so we can keep track of them
            var iterimpls = program.TopLevelDeclarations.OfType <Implementation>().ToList();

            iterimpls.Iter(impl => InstrumentEnsures(program, impl, CandidateFuncsAssumed[impl.Name], CandidateConstants));

            //BoogieUtil.PrintProgram(program, "h2.bpl");

            var RewriteAssumedToAssertedAction = new Action <Implementation>(impl =>
            {
                // Rewrite functions that are asserted
                var rewrite = new RewriteFuncs(AssumeToAssert);
                foreach (var blk in impl.Blocks)
                {
                    foreach (var acmd in blk.Cmds.OfType <AssertCmd>())
                    {
                        acmd.Expr = rewrite.VisitExpr(acmd.Expr);
                    }
                }

                var funcs = new HashSet <Function>(CandidateFuncsAssumed.Values);
                // Move call-site constant to the first argument of CandidateFuncs
                foreach (var blk in impl.Blocks)
                {
                    Expr cv = null;
                    // walk backwards
                    for (int i = blk.Cmds.Count - 1; i >= 0; i--)
                    {
                        var acmd = blk.Cmds[i] as AssumeCmd;
                        if (acmd == null)
                        {
                            continue;
                        }

                        if (QKeyValue.FindBoolAttribute(acmd.Attributes, StratifiedVCGenBase.callSiteVarAttr))
                        {
                            cv = acmd.Expr;
                            continue;
                        }

                        InsertControlVar.Apply(acmd.Expr, funcs, cv);
                    }
                }

                //impl.Emit(new TokenTextWriter(Console.Out), 0);
            });

            program.AddTopLevelDeclarations(CandidateFuncsAssumed.Values);
            program.AddTopLevelDeclarations(CandidateFuncsAsserted.Values);

            var callgraph     = BoogieUtil.GetCallGraph(program);
            var impl2Priority = DeterminePriorityOrder(program, callgraph);
            var impls         = new HashSet <string>(impl2Priority.Keys);

            HoudiniStats.Start("VCGen");

            // VC Gen
            var hi = new HoudiniInlining(program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, RewriteAssumedToAssertedAction);

            HoudiniStats.Stop("VCGen");

            var worklist = new SortedSet <Tuple <int, string> >();

            impl2Priority.Iter(tup => worklist.Add(Tuple.Create(tup.Value, tup.Key)));

            // Current assignment: set of true constants
            // Initially: everything is true
            var assignment = new HashSet <string>(CandidateConstants.Keys);

            var prover   = hi.prover;
            var reporter = new EmptyErrorReporter();

            // assert true to flush all one-time axioms, decls, etc
            prover.Assert(VCExpressionGenerator.True, true);

            HoudiniStats.Start("MainLoop");

            // worklist algorithm
            while (worklist.Any())
            {
                var implName = worklist.First().Item2;
                worklist.Remove(worklist.First());

                if (dbg)
                {
                    Console.WriteLine("Processing " + implName);
                }
                prover.LogComment("Processing " + implName);

                prover.Push();

                var hvc           = new HoudiniVC(hi.implName2StratifiedInliningInfo[implName], impls, assignment);
                var openCallSites = new HashSet <StratifiedCallSite>(hvc.CallSites);
                prover.Assert(hvc.vcexpr, true);

                var candidates = !DualHoudini ? new HashSet <string>(hvc.constantToAssertedExpr.Keys.Where(k => assignment.Contains(k))) :
                                 new HashSet <string>(hvc.constantToAssumedExpr.Select(t => t.Item1).Where(k => assignment.Contains(k)));

                var provedTrue  = new HashSet <string>();
                var provedFalse = new HashSet <string>();
                var idepth      = Math.Max(0, CommandLineOptions.Clo.InlineDepth);

                // iterate over idepth
                while (true)
                {
                    // Part 1: over-approximate
                    var proved = ProveCandidates(prover, hvc.constantToAssertedExpr, hvc.constantToAssumedExpr, candidates.Difference(provedTrue.Union(provedFalse)));
                    provedTrue.UnionWith(proved);
                    if (dbg)
                    {
                        Console.WriteLine("Proved {0} candiates at depth {1}", proved.Count, CommandLineOptions.Clo.InlineDepth - idepth);
                    }

                    if (idepth == 0 || openCallSites.Count == 0)
                    {
                        break;
                    }

                    // Part 2: under-approximate
                    prover.Push();
                    foreach (var cs in openCallSites)
                    {
                        prover.Assert(cs.callSiteExpr, false);
                    }

                    var remaining = candidates.Difference(provedTrue.Union(provedFalse));
                    proved = ProveCandidates(prover, hvc.constantToAssertedExpr, hvc.constantToAssumedExpr, remaining);
                    provedFalse.UnionWith(remaining.Difference(proved));
                    if (dbg)
                    {
                        Console.WriteLine("Disproved {0} candiates at depth {1}", remaining.Difference(proved).Count, CommandLineOptions.Clo.InlineDepth - idepth);
                    }

                    prover.Pop();

                    // resolved all?
                    if (candidates.Difference(provedTrue.Union(provedFalse)).Count == 0)
                    {
                        break;
                    }

                    // Inline one level
                    idepth--;
                    var nextOpenCallSites = new HashSet <StratifiedCallSite>();
                    foreach (var cs in openCallSites)
                    {
                        var callee   = new HoudiniVC(hi.implName2StratifiedInliningInfo[cs.callSite.calleeName], impls, assignment);
                        var calleevc = cs.Attach(callee);
                        prover.Assert(prover.VCExprGen.Implies(cs.callSiteExpr, calleevc), true);
                        nextOpenCallSites.UnionWith(callee.CallSites);
                    }
                    openCallSites = nextOpenCallSites;
                }

                prover.Pop();

                var failed = candidates.Difference(provedTrue);
                assignment.ExceptWith(failed);

                if (failed.Count != 0)
                {
                    // add dependencies back into the worklist
                    if (!DualHoudini)
                    {
                        foreach (var caller in callgraph.Predecessors(implName))
                        {
                            worklist.Add(Tuple.Create(impl2Priority[caller], caller));
                        }
                    }
                    else
                    {
                        foreach (var caller in callgraph.Successors(implName))
                        {
                            worklist.Add(Tuple.Create(impl2Priority[caller], caller));
                        }
                    }
                }
            }

            HoudiniStats.Stop("MainLoop");

            hi.Close();

            return(assignment);
        }
示例#2
0
        public static void Apply(Expr expr, HashSet <Function> insertControlVar, Expr controlVar)
        {
            var iv = new InsertControlVar(insertControlVar, controlVar);

            iv.VisitExpr(expr);
        }