public static void DoDecorate(CallGraph cg) { var decorator = new ReadWriteSetDecorator(); decorator.CGraph = cg; foreach (var root in cg.Roots) { decorator.Visit(root); } }
public static CallGraph Make(Program program) { if (program == null) { return(null); } CallGraph cg = new CallGraph(); program.TopLevelDeclarations.Iter(x => cg.AddDeclaration(x)); return(cg); }
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); }
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); }
/// <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); }
/// <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); }