// Always safe to return Top public static Value Evaluate(Expr expr, Dictionary <string, Value> subst) { var vused = new VarsUsed(); vused.Visit(expr); // Make sure we have values of all variables except in-formals var informals = vused.Vars.Where(v => !subst.ContainsKey(v.Name)); if (informals.All(v => (v is Formal) && ((v as Formal).InComing))) { } else { return(Value.GetTop()); } if (vused.Vars.Any(v => subst.ContainsKey(v.Name) && subst[v.Name].ToSingletonVar() == null)) { return(GetTop()); } var vsubst = new Dictionary <string, Variable>(); subst.Keys.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar())); var dup = new FixedDuplicator(); var ne = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(expr)); return(Value.GetSingleton(ne)); }
public Value Subst(Dictionary <string, Value> subst) { if (isTrue) { return(this); } var newc = new HashSet <int>(constants); var newv = new HashSet <Variable>(); var newe = new HashSet <Expr>(); foreach (var v in vars) { Debug.Assert(subst.ContainsKey(v.Name)); if (subst[v.Name].isTrue) { return(GetTop()); } newc.UnionWith(subst[v.Name].constants); newv.UnionWith(subst[v.Name].vars); newe.UnionWith(subst[v.Name].constExprs); } foreach (var e in constExprs) { var vused = new VarsUsed(); vused.VisitExpr(e); Debug.Assert(vused.varsUsed.All(v => subst.ContainsKey(v))); if (vused.varsUsed.Any(v => subst[v].ToSingletonVar() == null)) { return(GetTop()); } var vsubst = new Dictionary <string, Variable>(); vused.varsUsed.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar())); var dup = new FixedDuplicator(); var ne = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(e)); newe.Add(ne); } newe = removeDuplicates(newe); if (newe.Count > maxExprsToTrack) { return(GetTop()); } var ret = new Value(); ret.vars = newv; ret.constants = newc; ret.constExprs = newe; ret.isTrue = false; return(ret); }
// Return a new copy of the program public override Program getProgram() { var startTime = DateTime.Now; Program ret; if (unresolved_program != null) { FixedDuplicator dup = new FixedDuplicator(); ret = dup.VisitProgram(unresolved_program); } else { var progStr = ""; if (programStream is FileStream || programStream is MemoryStream) { var stream = programStream as Stream; stream.Seek(0, SeekOrigin.Begin); progStr = ParserHelper.Fill(stream, new List <string>()); } else { Debug.Assert(programStream is string); progStr = (string)programStream; } var v = Parser.Parse(progStr, "PersistentProgram", out ret); if (v != 0) { writeToFile("error.bpl"); throw new InternalError("Illegal program given to PersistentProgram"); } if (PersistentProgram.clearTokens) { PersistentProgram.ClearTokens(ret); } // TODO: use this always (sometimes .NET-2-Boogie programs crash) if (useDuplicator) { FixedDuplicator dup = new FixedDuplicator(); unresolved_program = dup.VisitProgram(ret); } } if (ret.Resolve() != 0) { writeToFile("error.bpl"); throw new InternalError("Illegal program given to PersistentProgram"); } persistenceCost += (DateTime.Now - startTime); return(ret); }
// Adds a new main: // assertsPassed := true; // call main(); // assert assertsPassed; string addMain(CBAProgram program) { var dup = new FixedDuplicator(); var origMain = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, program.mainProcName); var newMain = dup.VisitImplementation(origMain); var newProc = dup.VisitProcedure(origMain.Proc); newMain.Name += "_SeqInstr"; newProc.Name += "_SeqInstr"; newMain.Proc = newProc; var mainIns = new List <Expr>(); foreach (Variable v in newMain.InParams) { mainIns.Add(Expr.Ident(v)); } var mainOuts = new List <IdentifierExpr>(); foreach (Variable v in newMain.OutParams) { mainOuts.Add(Expr.Ident(v)); } var callMain = new CallCmd(Token.NoToken, program.mainProcName, mainIns, mainOuts); callMain.Proc = origMain.Proc; var cmds = new List <Cmd>(); cmds.Add(BoogieAstFactory.MkVarEqConst(assertsPassed, true)); cmds.Add(callMain); cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(assertsPassed))); var blk = new Block(Token.NoToken, "start", cmds, new ReturnCmd(Token.NoToken)); newMain.Blocks = new List <Block>(); newMain.Blocks.Add(blk); program.AddTopLevelDeclaration(newProc); program.AddTopLevelDeclaration(newMain); program.mainProcName = newMain.Name; // Set entrypoint origMain.Attributes = BoogieUtil.removeAttr("entrypoint", origMain.Attributes); origMain.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", origMain.Proc.Attributes); newMain.AddAttribute("entrypoint"); return(newMain.Name); }
// Return a new copy of the program public override Program getProgram() { var startTime = DateTime.Now; FixedDuplicator dup = new FixedDuplicator(); Program ret = dup.VisitProgram(program); if (ret.Resolve() != 0 || ret.Typecheck() != 0) { BoogieUtil.PrintProgram(ret, "error.bpl"); throw new InternalError("Illegal program given to PersistentProgram"); } persistenceCost += (DateTime.Now - startTime); return(ret); }
private void readInProgram(Program p) { var startTime = DateTime.Now; // Make a copy of p into the persistent storage FixedDuplicator dup = new FixedDuplicator(); program = dup.VisitProgram(p); // Unresolve the program to break any pointer links var unresolver = new UnResolver(); unresolver.VisitProgram(program); persistenceCost += (DateTime.Now - startTime); }
public override CBAProgram runCBAPass(CBAProgram p) { p.Typecheck(); p.TopLevelDeclarations.OfType <Procedure>().Iter(proc => procsWithoutBody.Add(proc.Name)); p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => procsWithoutBody.Remove(impl.Name)); // remove malloc //procsWithoutBody.RemoveWhere(str => str.Contains("malloc")); // Make sure that procs without a body don't modify globals foreach (var proc in p.TopLevelDeclarations.OfType <Procedure>().Where(proc => procsWithoutBody.Contains(proc.Name))) { if (proc.Modifies.Count > 0 && !BoogieUtil.checkAttrExists("allocator", proc.Attributes)) { throw new InvalidInput("Produce Bug Witness: Procedure " + proc.Name + " modifies globals"); } } // Add the boogie_si_record_int procedure var inpVarInt = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Int), true); var inpVarBool = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Bool), true); var reProcInt = new Procedure(Token.NoToken, recordProcNameInt, new List <TypeVariable>(), new List <Variable> { inpVarInt }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); var reProcBool = new Procedure(Token.NoToken, recordProcNameBool, new List <TypeVariable>(), new List <Variable> { inpVarBool }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); // Add procedures for initialization of local variables foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>()) { var ncmds = new List <Cmd>(); foreach (var loc in (impl.LocVars.Concat(impl.OutParams))) { var cc = new CallCmd(Token.NoToken, GetInitLocalsProc(loc.TypedIdent.Type).Name, new List <Expr>(), new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(loc) })); cc.Attributes = new QKeyValue(Token.NoToken, RestrictToTrace.ConcretizeConstantNameAttr, new List <object> { LocalVarInitValueAttr }, cc.Attributes); cc.Proc = GetInitLocalsProc(loc.TypedIdent.Type); ncmds.Add(cc); } ncmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = ncmds; } typeToInitLocalsProc.Values.Iter(pr => procsWithoutBody.Add(pr.Name)); typeToInitLocalsProc.Values.Iter(pr => p.AddTopLevelDeclaration(pr)); // save the current program var fd = new FixedDuplicator(true); var modInpProg = fd.VisitProgram(p); // Instrument to record stuff p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrument(b))); // Name clash if this assert fails Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameInt) == null); Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameBool) == null); foreach (var rp in typeToRecordProc.Values) { Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, rp.Name) == null); } p.AddTopLevelDeclaration(reProcInt); p.AddTopLevelDeclaration(reProcBool); p.AddTopLevelDeclarations(typeToRecordProc.Values); var tmainimpl = BoogieUtil.findProcedureImpl(p.TopLevelDeclarations, p.mainProcName); if (!QKeyValue.FindBoolAttribute(tmainimpl.Attributes, "entrypoint")) { tmainimpl.AddAttribute("entrypoint"); } var program = new PersistentCBAProgram(p, p.mainProcName, 0); //program.writeToFile("beforeverify.bpl"); var vp = new VerificationPass(true); vp.run(program); success = vp.success; if (success) { return(null); } var trace = mapBackTraceRecord(vp.trace); RestrictToTrace.addConcretization = true; RestrictToTrace.addConcretizationAsConstants = true; var tinfo = new InsertionTrans(); var rt = new RestrictToTrace(modInpProg, tinfo); rt.addTrace(trace); RestrictToTrace.addConcretization = false; RestrictToTrace.addConcretizationAsConstants = false; var rtprog = rt.getProgram(); // Build a map of where the alloc constants are from allocConstants = rt.concretizeConstantToCall; // Add symbolic constants for angelic map havocs var newDecls = new List <Constant>(); rtprog.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrumentMapHavocs(b, allocConstants, newDecls))); rtprog.AddTopLevelDeclarations(newDecls); /* * foreach (var impl in rtprog.TopLevelDeclarations.OfType<Implementation>()) * { * // strip _trace from the impl name * var implName = impl.Name; * var c = implName.LastIndexOf("_trace"); * while (c != -1) * { * implName = implName.Substring(0, c); * c = implName.LastIndexOf("_trace"); * } * * var vu = new VarsUsed(); * vu.VisitImplementation(impl); * vu.varsUsed.Where(s => s.StartsWith("alloc_")) * .Iter(s => allocConstants[s] = implName); * } */ BoogieUtil.findProcedureImpl(rtprog.TopLevelDeclarations, rt.getFirstNameInstance(p.mainProcName)) .AddAttribute("entrypoint"); program = new PersistentCBAProgram(rtprog, rt.getFirstNameInstance(p.mainProcName), p.contextBound); // Lets inline it all var inlp = new InliningPass(1); program = inlp.run(program); var compress = new CompressBlocks(); var ret = program.getProgram(); compress.VisitProgram(ret); return(new CBAProgram(ret, program.mainProcName, 0)); }
public override CBAProgram runCBAPass(CBAProgram program) { var nameImplMap = BoogieUtil.nameImplMapping(program); // Construct call graph, compute SCCs var graph = new Graph <string>(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { impl.Blocks.Iter(block => block.Cmds.OfType <CallCmd>().Iter(cmd => graph.AddEdge(impl.Name, cmd.callee))); } graph.AddSource(program.mainProcName); var preds = new Adjacency <string>(st => graph.Predecessors(st)); var succs = new Adjacency <string>(st => graph.Successors(st)); var sccs = new StronglyConnectedComponents <string>(graph.Nodes, preds, succs); sccs.Compute(); //var dotFileCnt = 1; // For each SCC, compute backedges foreach (var scc in sccs) { if (scc.Count == 1) { var onlyProc = scc.First(); if (nameImplMap.ContainsKey(onlyProc) && QKeyValue.FindBoolAttribute(nameImplMap[onlyProc].Attributes, "LoopProcedure")) { continue; } if (graph.Successors(onlyProc).All(callee => callee != onlyProc)) { continue; } } Console.Write("Considering SCC: "); scc.Iter(s => Console.Write("{0} ", s)); Console.WriteLine(); foundRecursion = true; // pick source var sccProcs = new HashSet <string>(scc); var src = scc.FirstOrDefault(proc => graph.Predecessors(proc).Any(pred => !sccProcs.Contains(pred))); if (src == null) { src = scc.First(); } var grey = new HashSet <string>(); var black = new HashSet <string>(); grey.Add(src); backedges = new HashSet <Tuple <string, string> >(); dfsTreeParent = new Dictionary <string, string>(); someCycles = new List <HashSet <string> >(); dfs(graph, src, sccProcs, grey, black); InferWhatToCut(graph, scc); // create copies var procCopies = new Dictionary <Tuple <string, int>, Procedure>(); var implCopies = new Dictionary <Tuple <string, int>, Implementation>(); foreach (var name in scc) { var impl = nameImplMap[name]; program.RemoveTopLevelDeclaration(impl); program.RemoveTopLevelDeclaration(impl.Proc); for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++) { var dup = new FixedDuplicator(true); var nimpl = dup.VisitImplementation(impl); var nproc = dup.VisitProcedure(impl.Proc); nimpl.Name += string.Format("#{0}", i); nproc.Name += string.Format("#{0}", i); nimpl.Proc = nproc; program.AddTopLevelDeclaration(nimpl); program.AddTopLevelDeclaration(nproc); procCopies.Add(Tuple.Create(impl.Name, i), nproc); implCopies.Add(Tuple.Create(impl.Name, i), nimpl); } } // redirect calls foreach (var name in scc) { foreach (var pred in graph.Predecessors(name)) { if (sccProcs.Contains(pred)) { continue; } var pimpl = nameImplMap[pred]; foreach (var blk in pimpl.Blocks) { var newcmds = new List <Cmd>(); foreach (var cmd in blk.Cmds) { var ccmd = cmd as CallCmd; if (ccmd == null || !sccProcs.Contains(ccmd.callee)) { newcmds.Add(cmd); continue; } newcmds.Add( new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", CommandLineOptions.Clo.RecursionBound - 1), ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync)); } blk.Cmds = newcmds; } } for (int i = 0; i < CommandLineOptions.Clo.RecursionBound; i++) { var impl = implCopies[Tuple.Create(name, i)]; foreach (var blk in impl.Blocks) { var newcmds = new List <Cmd>(); foreach (var cmd in blk.Cmds) { var ccmd = cmd as CallCmd; if (ccmd == null || !sccProcs.Contains(ccmd.callee)) { newcmds.Add(cmd); continue; } var cnt = i; if (CutEdge(name, ccmd.callee)) { cnt--; } if (cnt < 0) { newcmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); } else { newcmds.Add(new CallCmd(ccmd.tok, ccmd.callee + string.Format("#{0}", cnt), ccmd.Ins, ccmd.Outs, ccmd.Attributes, ccmd.IsAsync)); } } blk.Cmds = newcmds; } } } } return(program); }
public override CBAProgram runCBAPass(CBAProgram p) { if (unrollNum >= 0) { return(base.runCBAPass(p)); } foreach (var impl in BoogieUtil.GetImplementations(p)) { impl.PruneUnreachableBlocks(); } // save RB var rb = CommandLineOptions.Clo.RecursionBound; if (BoogieVerify.irreducibleLoopUnroll >= 0) { CommandLineOptions.Clo.RecursionBound = BoogieVerify.irreducibleLoopUnroll; } var procsWithIrreducibleLoops = new HashSet <string>(); var passInfo = p.ExtractLoops(out procsWithIrreducibleLoops); // restore RB CommandLineOptions.Clo.RecursionBound = rb; // no loops found, then this transformation is identity if (passInfo.Count == 0 && procsWithIrreducibleLoops.Count == 0) { return(null); } if (addUniqueCallLabels) { // annotate calls with a unique number var addIds = new AddUniqueCallIds(); // Loop unrolling is done for procs with irreducible loops. // This simply copies Cmd objects. Duplicate them to remove // aliasing foreach (var impl in p.TopLevelDeclarations .OfType <Implementation>() .Where(impl => procsWithIrreducibleLoops.Contains(impl.Name))) { var dup = new FixedDuplicator(true); foreach (var blk in impl.Blocks) { blk.Cmds = dup.VisitCmdSeq(blk.Cmds); } } // Add labels again to all procedures foreach (var impl in p.TopLevelDeclarations .OfType <Implementation>()) { addIds.VisitImplementation(impl); } } info = new Dictionary <string, Dictionary <string, string> >(); passInfo.Iter(kvp => { info.Add(kvp.Key, new Dictionary <string, string>()); kvp.Value.Iter(sb => info[kvp.Key].Add(sb.Key, sb.Value.Label)); }); // Construct the set of procs in the original program // and the loop procedures allProcs = new HashSet <string>(); loopProcs = new HashSet <string>(); foreach (var decl in p.TopLevelDeclarations) { var impl = decl as Implementation; if (impl == null) { continue; } allProcs.Add(impl.Name); if (impl.Proc is LoopProcedure) { loopProcs.Add(impl.Name); impl.Proc.AddAttribute("LoopProcedure"); } } //foreach (var impl in BoogieUtil.GetImplementations(p)) //{ //removeAssumeFalseBlocks(impl); //} // Optimization: if no loop is found, then no need to print // out a new program if (loopProcs.Count == 0) { return(null); } // Remove vars from attributes that are not in scope anymore RemoveVarsFromAttributes.Prune(p); return(p); }
private static Program PrepareQuery(IEnumerable <Implementation> loopImpls, Program program) { // Sometimes loops have multiple backedges, hence multiple recursive calls: merge them loopImpls.Iter(impl => mergeRecCalls(impl)); var dup = new FixedDuplicator(true); // Make copies of loopImpl procs var loopProcsCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopProcsCopy.Add(impl.Name, dup.VisitProcedure(impl.Proc))); loopProcsCopy.Values.Iter(proc => proc.Name += "_PassiveCopy"); // Make copies of the caller implementations var loopCallerImplCopy = new Dictionary <string, Implementation>(); var loopCallerProcCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopCallerImplCopy.Add(impl.Name, dup.VisitImplementation(loopCaller[impl.Name]))); loopImpls .Iter(impl => loopCallerProcCopy.Add(impl.Name, dup.VisitProcedure(loopCaller[impl.Name].Proc))); loopCallerImplCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerProcCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerImplCopy .Iter(kvp => kvp.Value.Proc = loopCallerProcCopy[kvp.Key]); // Instrument callers foreach (var kvp in loopCallerImplCopy) { var impl = kvp.Value; var av = BoogieAstFactory.MkLocal("LoopBound_AssertVar", Microsoft.Boogie.Type.Bool); impl.LocVars.Add(av); // av := true var init = BoogieAstFactory.MkVarEqConst(av, true); var initCmds = new List <Cmd>(); initCmds.Add(init); initCmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = initCmds; // av := false foreach (var blk in impl.Blocks) { var newCmds = new List <Cmd>(); for (int i = 0; i < blk.Cmds.Count; i++) { // disable assertions if (blk.Cmds[i] is AssertCmd && !BoogieUtil.isAssertTrue(blk.Cmds[i])) { newCmds.Add(new AssumeCmd(Token.NoToken, (blk.Cmds[i] as AssertCmd).Expr)); continue; } var cc = blk.Cmds[i] as CallCmd; if (cc != null && cc.callee == kvp.Key) { newCmds.Add(blk.Cmds[i]); newCmds.Add(BoogieAstFactory.MkVarEqConst(av, false)); } else if (cc != null && loopProcsCopy.ContainsKey(cc.callee)) { var ncc = new CallCmd(cc.tok, loopProcsCopy[cc.callee].Name, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync); ncc.Proc = loopProcsCopy[cc.callee]; newCmds.Add(ncc); } else { newCmds.Add(blk.Cmds[i]); } } blk.Cmds = newCmds; } // assert av impl.Blocks .Where(blk => blk.TransferCmd is ReturnCmd) .Iter(blk => blk.Cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(av)))); } // Prepare program var ret = new Program(); program.TopLevelDeclarations .Where(decl => !(decl is Implementation)) .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopProcsCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerImplCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerProcCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopImpls .Iter(impl => ret.AddTopLevelDeclaration(impl)); loopCallerImplCopy.Values .Iter(impl => impl.AddAttribute("entrypoint")); // Store mapping: entrypoint -> loop loopImpls .Select(loop => Tuple.Create(loop, loopCallerImplCopy[loop.Name])) .Iter(tup => tup.Item2.AddAttribute("LB_Mapping", tup.Item1.Name)); ret = BoogieUtil.ReResolveInMem(ret); return(ret); }
// Split on the postconditions of procedure "proc" // 1. only retain its postconditions; make everything else as assumes // 2. drop the implementation of the procedure // 3. convert calls to itself to calls to a fake procedure with assumed postconditions static Program SplitOnProcedure(Program program, string proc) { var dup = new FixedDuplicator(); program = dup.VisitProgram(program); program = BoogieUtil.ReResolveInMem(program, true); var toremove = new HashSet <Implementation>(); Implementation procimpl = null; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { if (impl.Name == proc) { procimpl = impl; continue; } if (impl.Proc.Ensures.All(ens => ens.Free)) { continue; } var newens = new List <Ensures>(); impl.Proc.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment))); impl.Proc.Ensures = newens; toremove.Add(impl); } program.RemoveTopLevelDeclarations(decl => decl is Implementation && toremove.Contains(decl)); if (procimpl != null) { // create copy var proccopy = dup.VisitProcedure(procimpl.Proc); proccopy.Name += "_dup"; // make assumes var newens = new List <Ensures>(); proccopy.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment))); proccopy.Ensures = newens; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { for (int i = 0; i < blk.Cmds.Count; i++) { var ccmd = blk.Cmds[i] as CallCmd; if (ccmd == null || ccmd.callee != procimpl.Name) { continue; } blk.Cmds[i] = new CallCmd(ccmd.tok, proccopy.Name, ccmd.Ins, ccmd.Outs, ccmd.Attributes); } } } program.AddTopLevelDeclaration(proccopy); } return(program); }