Пример #1
0
        // 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));
        }
Пример #2
0
        static Program GetProgram(string filename)
        {
            var init = GetInputProgram(filename);

            if (Options.addInitialization)
            {
                ComputeandInitializeUninitializedLocals(init);
            }

            // Do some instrumentation for the input program
            if (Options.markAssumesAsSlic)
            {
                // Mark all assumes as "slic"
                var AddAnnotation = new Action <AssumeCmd>(ac =>
                {
                    ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes);
                });
                init.TopLevelDeclarations.OfType <Implementation>()
                .Iter(impl => impl.Blocks
                      .Iter(blk => blk.Cmds.OfType <AssumeCmd>()
                            .Iter(AddAnnotation)));
            }

            // Only keep assertions in assertProc procedures
            if (Options.assertProcs != null)
            {
                (new Instrumentations.PruneNonAssertProcs(Options.assertProcs)).Visit(init);
            }

            // Inline procedures supplied with {:inline} annotation
            cba.Driver.InlineProcedures(init);

            // Remove {:inline} impls
            init.RemoveTopLevelDeclarations(decl => (decl is Implementation) &&
                                            (BoogieUtil.checkAttrExists("inline", decl.Attributes) ||
                                             BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes)));

            // Restrict entrypoints to those provided explicitly (overrides any other way to providing entryPoints)
            if (Options.entryPointProcs != null)
            {
                //only consider the user provided entry points in command line
                Options.useHarnessTag          = false;
                Options.useProvidedEntryPoints = true;
                init.TopLevelDeclarations.OfType <NamedDeclaration>()
                .Iter(d => d.Attributes = BoogieUtil.removeAttr("entrypoint", d.Attributes));
            }
            var matchesEntryPointExclude = new Func <string, bool>(s =>
            {
                return(Options.entryPointExcludes.Any(t => new System.Text.RegularExpressions.Regex(t).IsMatch(s)));
            });

            //when both entryPointProcs == null and entryPointExcludes == null, it should not add any entrypointProcs
            if (Options.entryPointProcs != null || Options.entryPointExcludes != null)
            {
                init.TopLevelDeclarations.OfType <NamedDeclaration>()
                .Where(d => d is Procedure || d is Implementation)
                .Where(d => Options.entryPointProcs == null || Options.entryPointProcs.Contains(d.Name))
                .Where(d => (Options.entryPointExcludes == null || !matchesEntryPointExclude(d.Name)))
                .Iter(d => d.AddAttribute("entrypoint"));
            }
            // Add {:entrypoint} to procs with {:harness}
            if (Options.useHarnessTag)
            {
                foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>()
                         .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness")))
                {
                    decl.AddAttribute("entrypoint");
                }
            }

            // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements)
            //foreach (var impl in init.TopLevelDeclarations.OfType<Implementation>())
            //{
            //    impl.Blocks.Iter(blk =>
            //        blk.Cmds.RemoveAll(cmd => cmd is HavocCmd));
            //}
            ReplaceHavocsWithNonDet(init);

            //Instrument to create the harness
            harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints);
            harnessInstrumentation.DoInstrument();

            //resolve+typecheck wo bothering about modSets
            CommandLineOptions.Clo.DoModSetAnalysis = true;
            init = BoogieUtil.ReResolveInMem(init);
            CommandLineOptions.Clo.DoModSetAnalysis = false;

            // Update mod sets
            BoogieUtil.DoModSetAnalysis(init);

            if (Options.AddMapSelectNonNullAssumptions)
            {
                (new Instrumentations.AssertMapSelectsNonNull()).Visit(init);
            }


            BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC);

            if (Options.deadCodeDetect)
            {
                // Tag branches as reachable
                var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false);
                init = tup.Item1;
                // TODO: inject this information into the program itself
                DeadCodeBranchesDependencyInfo = tup.Item2;
            }

            return(init);
        }
Пример #3
0
        static Program GetProgram(string filename)
        {
            var init = GetInputProgram(filename);

            if (Options.addInitialization)
            {
                ComputeandInitializeUninitializedLocals(init);
            }

            // Do some instrumentation for the input program
            if (Options.markAssumesAsSlic)
            {
                // Mark all assumes as "slic"
                var AddAnnotation = new Action <AssumeCmd>(ac =>
                {
                    ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes);
                });
                init.TopLevelDeclarations.OfType <Implementation>()
                .Iter(impl => impl.Blocks
                      .Iter(blk => blk.Cmds.OfType <AssumeCmd>()
                            .Iter(AddAnnotation)));
            }

            // Inline procedures supplied with {:inline} annotation
            cba.Driver.InlineProcedures(init);

            // Remove {:inline} impls
            init.RemoveTopLevelDeclarations(decl => (decl is Implementation) &&
                                            (BoogieUtil.checkAttrExists("inline", decl.Attributes) ||
                                             BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes)));

            // Add {:entrypoint} to procs with {:harness}
            if (Options.useHarnessTag)
            {
                foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>()
                         .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness")))
                {
                    decl.AddAttribute("entrypoint");
                }
            }

            // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements)
            foreach (var impl in init.TopLevelDeclarations.OfType <Implementation>())
            {
                impl.Blocks.Iter(blk =>
                                 blk.Cmds.RemoveAll(cmd => cmd is HavocCmd));
            }

            //Instrument to create the harness
            harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints);
            harnessInstrumentation.DoInstrument();

            //resolve+typecheck wo bothering about modSets
            CommandLineOptions.Clo.DoModSetAnalysis = true;
            init = BoogieUtil.ReResolve(init);
            CommandLineOptions.Clo.DoModSetAnalysis = false;

            // Update mod sets
            BoogieUtil.DoModSetAnalysis(init);

            if (Options.AddMapSelectNonNullAssumptions)
            {
                (new Instrumentations.AssertMapSelectsNonNull()).Visit(init);
            }

            BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC);

            if (Options.deadCodeDetect)
            {
                // Tag branches as reachable
                var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false);
                init = tup.Item1;
                // TODO: inject this information into the program itself
                DeadCodeBranchesDependencyInfo = tup.Item2;
            }

            return(init);
        }