/// <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); }