示例#1
0
        public static void DoDecorate(CallGraph cg)
        {
            var decorator = new ReadWriteSetDecorator();

            decorator.CGraph = cg;

            foreach (var root in cg.Roots)
            {
                decorator.Visit(root);
            }
        }
示例#2
0
        public static CallGraph Make(Program program)
        {
            if (program == null)
            {
                return(null);
            }

            CallGraph cg = new CallGraph();

            program.TopLevelDeclarations.Iter(x => cg.AddDeclaration(x));

            return(cg);
        }
示例#3
0
文件: Driver.cs 项目: liyistc/symdiff
        public static int RecursionCheck(string filename)
        {
            var program = BoogieUtils.ParseProgram(filename);

            if (program == null)
            {
                return(1);
            }
            BoogieUtils.ResolveAndTypeCheckThrow(program, filename);

            var flag  = false;
            var mflag = false;
            var nflag = false;

            var cg = CallGraph.Make(program);

            var recs = cg.SinglyRecursiveFns();

            foreach (var node in recs)
            {
                Console.WriteLine(node.Name);
            }

            nflag = cg.HasCycle();

            foreach (var scc in cg.ComputeSCCs())
            {
                if ((scc.Count == 1 && scc[0].IsSinglyRecursive()))
                {
                    flag = true;
                }
                if (scc.Count > 1)
                {
                    mflag = true;
                }
            }

            if (flag)
            {
                Console.WriteLine("Recursive.");
            }
            if (mflag)
            {
                Console.WriteLine("Multi_Recursive");
            }
            if (nflag)
            {
                Console.WriteLine("Naive cycle detector found a non-singleton cycle!");
            }
            return(0);
        }
示例#4
0
        public Worklist Make(CallGraph c1, CallGraph c2, Config cfg)
        {
            var c1Roots = SimpleGraph.FindRoots((IEnumerable <ISimpleGraphNode>)c1.GetNodes()).Cast <CallGraphNode>();
            var c2Roots = SimpleGraph.FindRoots((IEnumerable <ISimpleGraphNode>)c2.GetNodes()).Cast <CallGraphNode>();

            if (c1Roots.Count() != c2Roots.Count())
            {
                Log.Out(Log.Urgent, "Unequal number of nodes at root level in worklist construction");
            }

            //for(int i = 0; i < c1Roots.Count; i++)
            //  c1Roots[i].Name
            return(null);
        }
示例#5
0
        /// <summary>
        /// The entry point of the RVT decomposition method
        /// </summary>
        /// <param name="cg1"></param>
        /// <param name="cg2"></param>
        /// <param name="cgP"></param>
        /// <param name="cfgP"></param>
        /// <param name="mergedProgramP"></param>
        /// <param name="fnMap"></param>
        public static void RVTMain(SDiff.CallGraph cg1, SDiff.CallGraph cg2, SDiff.CallGraph cgP,
                                   Config cfgP, Program mergedProgramP,
                                   Dictionary <string, string> fnMap)
        {
            cg             = cgP;
            mergedProgram  = mergedProgramP;
            cfg            = cfgP;
            funs           = new Dictionary <string, string>(fnMap);
            eqProcsCreated = new Dictionary <string, Duple <Duple <Procedure, Implementation>, List <Variable> > >();

            //compute the cg sizes
            int cg1size, cg2size;

            var cg1Nodes = cg1.GetNodes();
            var cg2Nodes = cg2.GetNodes();

            cg1size = cg1Nodes.Count();
            cg2size = cg2Nodes.Count();

            //create the mapping from fn --> index
            fnNameToIndex1 = new Dictionary <string, int>();
            fnIndexToName1 = new Dictionary <int, string>();
            fnNameToIndex2 = new Dictionary <string, int>();
            fnIndexToName2 = new Dictionary <int, string>();
            int count = 0;

            string[] s1 = new string[cg1Nodes.Count()], s2 = new string[cg1Nodes.Count + cg2Nodes.Count()];
            foreach (var cgNode in cg1Nodes)
            {
                var fnName = cgNode.Proc.Name;
                fnNameToIndex1.Add(fnName, count);
                fnIndexToName1.Add(count, fnName);
                s1[count] = RemoveVersionPrefix(fnName);
                count++;
            }

            //We want the indices to be distinct

            foreach (var cgNode in cg2Nodes)
            {
                var fnName = cgNode.Proc.Name;
                fnNameToIndex2.Add(fnName, count);
                fnIndexToName2.Add(count, fnName);
                s2[count] = RemoveVersionPrefix(fnName);
                count++;
            }

            //create the edge list
            List <Tuple <int, int> > edgeList1, edgeList2;

            edgeList1 = new List <Tuple <int, int> >();
            edgeList2 = new List <Tuple <int, int> >();

            foreach (var cgNode in cg1Nodes)
            {
                var src    = cgNode.Proc.Name;
                var srcIdx = fnNameToIndex1[src];

                var callees = cgNode.Callees;
                foreach (var callee in callees)
                {
                    var dest    = callee.Proc.Name;
                    var destIdx = fnNameToIndex1[dest];
                    var edge    = new Tuple <int, int>(srcIdx, destIdx);
                    edgeList1.Add(edge);
                }
            }

            foreach (var cgNode in cg2Nodes)
            {
                var src    = cgNode.Proc.Name;
                var srcIdx = fnNameToIndex2[src];

                var callees = cgNode.Callees;
                foreach (var callee in callees)
                {
                    var dest    = callee.Proc.Name;
                    var destIdx = fnNameToIndex2[dest];
                    var edge    = new Tuple <int, int>(srcIdx, destIdx);
                    edgeList2.Add(edge);
                }
            }


            //call the Decomposer
            List <int> synEq = new List <int>();

            List <Tuple <int, int> > fnMapIndex = new List <Tuple <int, int> >();

            fnMapIndexDict = new Dictionary <int, int>();
            List <int> empty1 = new List <int>(), empty2 = new List <int>();

            foreach (var fnPair in fnMap)
            {
                var left  = fnNameToIndex1[fnPair.Key];
                var right = fnNameToIndex2[fnPair.Value];
                var lr    = new Tuple <int, int>(left, right);

                //Add the same uninterpreted function by default
                Procedure leftP  = cg.NodeOfName(fnPair.Key).Proc;
                Procedure rightP = cg.NodeOfName(fnPair.Value).Proc;
                InjectUIFsOnBothProcs(leftP, rightP);
                if (RVTCreateEQProcs(left, ref synEq, ref empty1, ref empty2))
                {
                    //add the mapping if the eq generation succeeded
                    //HACK!!! should be filtered from the list given to RVT
                    fnMapIndex.Add(lr);
                    fnMapIndexDict.Add(left, right);
                }
            }


            // marking functions that were originated from loops (these will be marked differently in the dotty graphs)
            List <int> loop_functions_1, loop_functions_2;

            loop_functions_1 = new List <int>();
            loop_functions_2 = new List <int>();

            foreach (var cgNode in cg1Nodes)
            {
                string src = cgNode.Proc.Name;
                if (src.Contains(Options.LoopStringIdentifier))
                {
                    loop_functions_1.Add(fnNameToIndex1[src]);
                }
            }

            foreach (var cgNode in cg2Nodes)
            {
                string src = cgNode.Proc.Name;
                if (src.Contains(Options.LoopStringIdentifier))
                {
                    loop_functions_2.Add(fnNameToIndex2[src]);
                }
            }
            //RunRVTDecomposer(cg1size, cg2size, edgeList1, edgeList2, fnMapIndex, synEq);

            DECOMPOSE_CS.RVT_Decompose.Decompose_main(cg1size, cg1size + cg2size, edgeList1, edgeList2, loop_functions_1, loop_functions_2, fnMapIndex, synEq, empty1, empty2, s1, s2);
        }
示例#6
0
        /// <summary>
        /// Create the EQ_f_f' procedure statically (eagerly) to avoid generating it again and again
        /// </summary>
        /// <param name="f"></param>
        /// Outputs the list of synEq functions for stubs that have no bodies on both sides
        private static bool RVTCreateEQProcs(int f, ref List <int> synEq, ref List <int> empty1, ref List <int> empty2)
        {
            //name of the function
            string fname = fnIndexToName1[f];

            var n1     = cg.NodeOfName(fname);
            var n2Name = funs.Get(n1.Name);

            if (n2Name == null)
            {
                Log.Out(Log.Error, "Could not find mapping for " + n1.Name);
                Log.Out(Log.Error, "Dumping config...");
                Log.Out(Log.Error, cfg.ToString());
                return(false);
            }

            var n2 = cg.NodeOfName(n2Name);

            if (n2 == null)
            {
                Log.Out(Log.Error, "ERROR: Could not find " + n2Name + " in ARGS[1]");
                return(false);
            }

            if (n1.Proc == null || n2.Proc == null)
            {
                Log.Out(Log.Error, "Missing procedure for " + n1.Name + " or " + n2.Name + ": skipping...");
                return(false);
            }

            //TODO: currently return false for corner cases...FIX this carefully

            if (n1.Name.EndsWith("nondet_choice"))
            {
                Log.Out(Log.Normal, "skipping nondet_choice");
                return(false);
            }

            if (n1.Impl == null && n2.Impl == null)
            {
                Log.Out(Log.Normal, "No implementation for " + n1.Name + ": skipping...");
                synEq.Add(f);
                empty1.Add(f);
                empty2.Add(fnNameToIndex2[n2.Name]);
                return(true);
            }

            if (n1.Impl == null)
            {
                Log.Out(Log.Error, "!Missing implementation for " + n1.Name);
                empty1.Add(f);
                return(false);
            }

            if (n2.Impl == null)
            {
                Log.Out(Log.Error, "!Missing implementation for " + n2.Name);
                empty2.Add(fnNameToIndex2[n2.Name]);
                return(false);
            }

            var ignores = new HashSet <Variable>(n1.IgnoreSet);

            ignores.UnionWith(n2.IgnoreSet);

            // Creates EQ_f_f' function
            List <Variable> outputVars;
            string          eqpName = Transform.mkEqProcName(n1.Name, n2.Name);

            Duple <Procedure, Implementation> eqp;

            eqp = Transform.EqualityReduction(n1.Impl, n2.Impl, cfg.FindProcedure(n1.Name, n2.Name), ignores, out outputVars);

            // if any visible output
            //VerificationTask vt;
            if (eqp != null)
            {
                mergedProgram.AddTopLevelDeclarations(outputVars.Map(x => x as Declaration));
                mergedProgram.AddTopLevelDeclaration(eqp.fst);
                mergedProgram.AddTopLevelDeclaration(eqp.snd);
            }

            //declare the uninterpreted funcs/canonical set of constants  in merged program
            //mergedProgram.AddTopLevelDeclarations(newDecls);
            var canonicalConst = SDiff.Boogie.ConstantFactory.Get().Constants.Map(x => x as Declaration);

            mergedProgram.AddTopLevelDeclarations(canonicalConst);


            //Log.Out(Log.Normal, "Resolving and Typechecking again..");
            if (BoogieUtils.ResolveAndTypeCheckThrow(mergedProgram, Options.MergedProgramOutputFile))
            {
                Log.LogEmit(Log.Normal, mergedProgram.Emit);
                return(false);
            }

            if (Options.TraceVerify)
            {
                Log.Out(Log.Normal, "merged program with ufs etc");
                Log.LogEmit(Log.Normal, mergedProgram.Emit);
            }

            // callgraph has changed because EQ programs are added
            Log.Out(Log.Normal, "Building callgraphs and computing read and write sets");
            cg = CallGraph.Make(mergedProgram);
            ReadWriteSetDecorator.DoDecorate(cg); //start from scratch to fill in the read/write sets
            var mergedProgramNewDecl = new Program();

            mergedProgram.AddTopLevelDeclarations(mergedProgramNewDecl.TopLevelDeclarations);
            mergedProgram.TopLevelDeclarations = SDiff.Boogie.Process.RemoveDuplicateDeclarations(mergedProgram.TopLevelDeclarations.ToList());

            Duple <Duple <Procedure, Implementation>, List <Variable> > tmp = new Duple <Duple <Procedure, Implementation>, List <Variable> >(eqp, outputVars);

            eqProcsCreated.Add(eqpName, tmp);


            return(true);
        }