private bool IsRelevant(Bpl.Cmd cmd) { Bpl.AssertCmd assertCmd = cmd as Bpl.AssertCmd; if (assertCmd == null) { return(false); } string sourceFile = Bpl.QKeyValue.FindStringAttribute(assertCmd.Attributes, "sourceFile"); if (sourceFile == null) { return(false); } string[] ds = sourceFile.Split('\\'); if (sourceFile != fileName && ds[ds.Length - 1] != fileName) { return(false); } int sourceLine = Bpl.QKeyValue.FindIntAttribute(assertCmd.Attributes, "sourceLine", -1); Debug.Assert(sourceLine != -1); if (sourceLine != lineNumber) { return(false); } return(true); }
void PredicateCmd(Expr p, Expr pDom, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) { var cCmd = cmd as CallCmd; if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) { if (p == null) { block.Cmds.Add(cmd); nextBlock = block; return; } var trueBlock = new Block(); blocks.Add(trueBlock); trueBlock.Label = block.Label + ".call.true"; trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p)); trueBlock.Cmds.Add(cmd); var falseBlock = new Block(); blocks.Add(falseBlock); falseBlock.Label = block.Label + ".call.false"; falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p))); var contBlock = new Block(); blocks.Add(contBlock); contBlock.Label = block.Label + ".call.cont"; block.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock }); trueBlock.TransferCmd = falseBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { contBlock }); nextBlock = contBlock; } else { PredicateCmd(p, pDom, block.Cmds, cmd); nextBlock = block; } }
public static Bpl.StmtList BuildStmtList(Bpl.Cmd cmd, Bpl.TransferCmd tcmd) { Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); builder.Add(cmd); builder.Add(tcmd); return(builder.Collect(Bpl.Token.NoToken)); }
public bool isSyncCall(bpl.Cmd cmd) { if (!(cmd is bpl.CallCmd)) { return(false); } var callCmd = cmd as bpl.CallCmd; return(!callCmd.IsAsync); }
public bool isAtomicEnd(bpl.Cmd cmd) { if (cmd == null) { return(false); } if (!(cmd is bpl.CallCmd)) { return(false); } return((cmd as bpl.CallCmd).callee == atomicEndProc); }
public Cmd CopyCmd(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<Cmd>() != null); if (Subst == null) { return cmd; } else if (OldSubst == null) { return Substituter.Apply(Subst, cmd); } else { return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, cmd); } }
public bool isYield(bpl.Cmd cmd) { if (cmd == null) { return(false); } if (!(cmd is bpl.CallCmd)) { return(false); } return((cmd as bpl.CallCmd).callee == yieldProc); }
public override Bpl.CmdSeq VisitCmdSeq(Bpl.CmdSeq cmdSeq) { Bpl.CmdSeq newCmdSeq = new Bpl.CmdSeq(); for (int i = 0; i < cmdSeq.Length; i++) { Bpl.Cmd cmd = cmdSeq[i]; if (IsRelevant(cmd)) { newCmdSeq.Add(new Bpl.AssertCmd(cmd.tok, Bpl.Expr.False)); } newCmdSeq.Add(cmd); } return(newCmdSeq); }
public int readInvariantLabel(bpl.Cmd cmd) { var callCmd = cmd as bpl.CallCmd; if (callCmd == null) { throw new ConcurrentHoudiniException("[Context::readInvariantLabel] Not a call command"); } var args = getAttrParams(callCmd.Attributes, invariantAttr); if (args.Count() < 1 || !(args[0] is bpl.LiteralExpr)) { throw new ConcurrentHoudiniException("[Context::readInvariantLabel] Ill formed parameter"); } var numExpr = args[0] as bpl.LiteralExpr; return(numExpr.asBigNum.ToInt); }
public bpl.QKeyValue getAssumeAttrFromCmd(bpl.Cmd cmd) { if (!isYield(cmd) && !isR(cmd)) { return(null); } var attr = (cmd as bpl.CallCmd).Attributes; while (attr != null) { if (attr.Key == yieldAttr) { var num = (attr.Params[0] as bpl.LiteralExpr).asBigNum; var paramList = new List <object>(); paramList.Add(new bpl.LiteralExpr(bpl.Token.NoToken, num)); return(new bpl.QKeyValue(bpl.Token.NoToken, invariantAttr, paramList, null)); } attr = attr.Next; } return(null); }
/// <summary> /// The abstract transition relation. /// 'cmd' is allowed to be a StateCmd. /// </summary> static NativeLattice.Element Step(NativeLattice lattice, Cmd cmd, NativeLattice.Element elmt) { Contract.Requires(lattice != null); Contract.Requires(cmd != null); Contract.Requires(elmt != null); Contract.Ensures(Contract.Result<NativeLattice.Element>() != null); if (cmd is AssignCmd) { // parallel assignment var c = (AssignCmd)cmd; elmt = lattice.Update(elmt, c.AsSimpleAssignCmd); } else if (cmd is HavocCmd) { var c = (HavocCmd)cmd; foreach (IdentifierExpr id in c.Vars) { Contract.Assert(id != null); elmt = lattice.Eliminate(elmt, id.Decl); } } else if (cmd is PredicateCmd) { var c = (PredicateCmd)cmd; var conjuncts = new List<Expr>(); foreach (var ee in Conjuncts(c.Expr)) { Contract.Assert(ee != null); elmt = lattice.Constrain(elmt, ee); } } else if (cmd is StateCmd) { var c = (StateCmd)cmd; // Iterate the abstract transition on all the commands in the desugaring of the call foreach (Cmd callDesug in c.Cmds) { Contract.Assert(callDesug != null); elmt = Step(lattice, callDesug, elmt); } // Project out the local variables of the StateCmd foreach (Variable local in c.Locals) { Contract.Assert(local != null); elmt = lattice.Eliminate(elmt, local); } } else if (cmd is SugaredCmd) { var c = (SugaredCmd)cmd; elmt = Step(lattice, c.Desugaring, elmt); } else if (cmd is CommentCmd) { // skip } else { Contract.Assert(false); // unknown command } return elmt; }
public bpl.Program split(bpl.Program prog) { originalProgram = prog; ////////////////// First identify the thread entries in the program //////////////////// // A procedure is a thread entry if there is any async call to it HashSet <string> threadEntries = new HashSet <string>(); var impls = new Func <bpl.Program, IEnumerable <bpl.Implementation> >(p => from impl in p.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation); foreach (var impl in impls(originalProgram)) { var cmdsRaw = from blk in impl.Blocks select blk.Cmds; var cmds = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); }); var asyncCalls = from cmd in cmds where con.isAsyncCall(cmd as bpl.Cmd) select cmd; foreach (bpl.Cmd asyncCall in asyncCalls) { threadEntries.Add((asyncCall as bpl.CallCmd).callee); } } // Finally add the entry function also as a thread entry. threadEntries.Add(con.entryFunc); //////////////// Next, identify all the procedures belonging to each thread //////////// Dictionary <string, HashSet <string> > threadToProcs = new Dictionary <string, HashSet <string> >(); // This is done in two steps. // First step: Find all non-async calls in each procedure. var procToCalls = new Dictionary <string, HashSet <string> >(); //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation; foreach (var impl in impls(originalProgram)) { procToCalls[impl.Name] = new HashSet <string>(); var cmdsRaw = from blk in impl.Blocks select blk.Cmds; var cmds = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); }); var syncCalls = from cmd in cmds where con.isSyncCall(cmd as bpl.Cmd) select cmd; foreach (bpl.Cmd syncCall in syncCalls) { procToCalls[impl.Name].Add((syncCall as bpl.CallCmd).callee); } } // Second step: Find all procedures in each thread. foreach (var thr in threadEntries) { threadToProcs[thr] = new HashSet <string>(); } foreach (var thr in threadEntries) { findReachable(procToCalls, thr, threadToProcs[thr]); } //DEBUGGING if (dbg) { System.Console.WriteLine("Threads in the original program:"); foreach (var iter in threadToProcs) { System.Console.Write(iter.Key + ": "); foreach (var proc in iter.Value) { System.Console.Write(proc + " "); } System.Console.WriteLine(); } } // [Optional] // Remove unreachable procs. // These procedures are neither reachable from Main, nor from a thread entry. They can obviously not be called in any execution. var reachableProcs = new HashSet <string>(); foreach (var vals in threadToProcs.Values) { foreach (var proc in vals) { reachableProcs.Add(proc); } } foreach (var val in threadToProcs.Keys) { reachableProcs.Add(val); } removeUnreachable(reachableProcs); //////////////// Finally, Actually split the procedures when needed ////////////////// // For every procedure, find out how many threads contain it. We need as many copies of // that procedure. // Note: We do not want to duplicate procedures without implementation. //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation; var implNames = from impl in impls(originalProgram) select impl.Name; Dictionary <string, int> procCopies = new Dictionary <string, int>(); var procs = from proc in originalProgram.TopLevelDeclarations where proc is bpl.Procedure select proc as bpl.Procedure; foreach (var proc in procs) { procCopies[proc.Name] = 0; } foreach (var iter in threadToProcs) { foreach (var proc in iter.Value) { if (implNames.Contains(proc)) { procCopies[proc]++; } } } // Now duplicate // The new procedures and implementations for each thread // thread name --> (old procedure name --> new procedure) var newProcsPerThread = new Dictionary <string, Dictionary <string, bpl.Procedure> >(); // thread name --> (old procedure name --> new implementation) var newImplsPerThread = new Dictionary <string, Dictionary <string, bpl.Implementation> >(); // old name --> proc, old name --> impl var oldNameToImpl = new Dictionary <string, bpl.Implementation>(); foreach (var impl in impls(originalProgram)) { oldNameToImpl[impl.Name] = impl; } var oldNameToProc = new Dictionary <string, bpl.Procedure>(); foreach (var proc in procs) { oldNameToProc[proc.Name] = proc; } foreach (var elem in threadToProcs) { string threadName = elem.Key; newProcsPerThread[threadName] = new Dictionary <string, bpl.Procedure>(); newImplsPerThread[threadName] = new Dictionary <string, bpl.Implementation>(); foreach (var procName in elem.Value) { if (procCopies[procName] > 1) { // We will duplicate this procedure. // Make a copy of the procedure and implementation var dup = new cba.Util.FixedDuplicator(); var impl = (bpl.Implementation)dup.VisitDeclaration(oldNameToImpl[procName]); var proc = (bpl.Procedure)dup.VisitDeclaration(oldNameToProc[procName]); impl.Proc = proc; // Rename the new instances using thread id. impl.Name = con.getSplitProcName(procName); proc.Name = con.getSplitProcName(procName); var origProcAttr = con.originalProcAttr(procName); origProcAttr.Next = proc.Attributes; proc.Attributes = origProcAttr; // Also add an attribute to the definition specifying the thread. var threadAttr = con.getThreadAttr(threadName); threadAttr.Next = proc.Attributes; proc.Attributes = threadAttr; //add to duplicated procedures/impls newProcsPerThread[threadName][procName] = proc; newImplsPerThread[threadName][procName] = impl; //Add to the program originalProgram.AddTopLevelDeclaration(proc); originalProgram.AddTopLevelDeclaration(impl); var s1 = new HashSet <string>(); var s2 = new HashSet <string>(); foreach (var im in originalProgram.TopLevelDeclarations.OfType <bpl.Implementation>()) { s1.Add(im.Name); } foreach (var im in impls(originalProgram)) { s2.Add(im.Name); } // We have split away the procedure calls for one thread. procCopies[procName]--; } else if (procCopies[procName] == 1) { //We still need to rename this procedure var impl = oldNameToImpl[procName]; var proc = oldNameToProc[procName]; //rename the new instances using thread id. impl.Name = con.getSplitProcName(procName); proc.Name = con.getSplitProcName(procName); var origProcAttr = con.originalProcAttr(procName); origProcAttr.Next = proc.Attributes; proc.Attributes = origProcAttr; // Also add an attribute to the definition specifying the thread. var threadAttr = con.getThreadAttr(threadName); threadAttr.Next = proc.Attributes; proc.Attributes = threadAttr; //add to duplicated procedures/impls newProcsPerThread[threadName][procName] = proc; newImplsPerThread[threadName][procName] = impl; // We have split away the procedure calls for one thread. procCopies[procName]--; } } // Tell con that we're done with one thread. con.nextThread(); } // New re-route procedure calls as needed // First async calls. foreach (var impl in impls(originalProgram)) { foreach (var blk in impl.Blocks) { for (int i = 0; i < blk.Cmds.Count; i++) { bpl.Cmd cmd = blk.Cmds[i]; if (con.isAsyncCall(cmd)) { var callCmd = cmd as bpl.CallCmd; var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[callCmd.callee][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync); newCallCmd.TypeParameters = callCmd.TypeParameters; newCallCmd.Proc = newProcsPerThread[callCmd.callee][callCmd.callee]; blk.Cmds[i] = newCallCmd; } } } } // Now sync calls. foreach (var elem in newImplsPerThread) { string threadName = elem.Key; var newImpls = newImplsPerThread[threadName]; foreach (var implTuple in newImpls) { var impl = implTuple.Value; foreach (var blk in impl.Blocks) { for (int i = 0; i < blk.Cmds.Count; ++i) { bpl.Cmd cmd = blk.Cmds[i]; if (con.isSyncCall(cmd) && newProcsPerThread[threadName].ContainsKey((cmd as bpl.CallCmd).callee)) { var callCmd = cmd as bpl.CallCmd; var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[threadName][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync); newCallCmd.TypeParameters = callCmd.TypeParameters; newCallCmd.Proc = newProcsPerThread[threadName][callCmd.callee]; blk.Cmds[i] = newCallCmd; } } } } } // Finally, label the entry of each thread as thread entry. foreach (var elem in newProcsPerThread) { var proc = elem.Value[elem.Key]; var threadEntryAttr = con.getThreadEntryAttr(); threadEntryAttr.Next = proc.Attributes; proc.Attributes = threadEntryAttr; } return(originalProgram); }
private static GenKillWeight getWeight(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); return getWeight(cmd, null, null); }
private static Bpl.IfCmd BuildIfCmd(Bpl.Expr b, Bpl.Cmd cmd, Bpl.IfCmd ifCmd) { Bpl.StmtListBuilder ifStmtBuilder = new Bpl.StmtListBuilder(); ifStmtBuilder.Add(cmd); return(new Bpl.IfCmd(b.tok, b, ifStmtBuilder.Collect(b.tok), ifCmd, null)); }
void PredicateCmd(List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) { if (!useProcedurePredicates && cmd is CallCmd) { var trueBlock = new Block(); blocks.Add(trueBlock); trueBlock.Label = block.Label + ".call.true"; trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p)); trueBlock.Cmds.Add(cmd); var falseBlock = new Block(); blocks.Add(falseBlock); falseBlock.Label = block.Label + ".call.false"; falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p))); var contBlock = new Block(); blocks.Add(contBlock); contBlock.Label = block.Label + ".call.cont"; block.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock }); trueBlock.TransferCmd = falseBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { contBlock }); nextBlock = contBlock; } else { PredicateCmd(block.Cmds, cmd); nextBlock = block; } }
bool ContainsReachVariable(Cmd c) { Contract.Requires(c != null); AssertCmd artc = c as AssertCmd; AssumeCmd amec = c as AssumeCmd; Expr e; if (artc != null) { e = artc.Expr; } else if (amec != null) { e = amec.Expr; } else { return false; } Set freevars = new Set(); e.ComputeFreeVariables(freevars); foreach (Variable v in freevars) { Contract.Assert(v != null); if (v.Name.Contains(reachvarsuffix)) return true; } return false; }
public Parser(Scanner/*!*/ scanner, Errors/*!*/ errors, bool disambiguation) : this(scanner, errors) { // initialize readonly fields Pgm = new Program(); dummyExpr = new LiteralExpr(Token.NoToken, false); dummyCmd = new AssumeCmd(Token.NoToken, dummyExpr); dummyBlock = new Block(Token.NoToken, "dummyBlock", new List<Cmd>(), new ReturnCmd(Token.NoToken)); dummyType = new BasicType(Token.NoToken, SimpleType.Bool); dummyExprSeq = new List<Expr> (); dummyTransferCmd = new ReturnCmd(Token.NoToken); dummyStructuredCmd = new BreakCmd(Token.NoToken, null); }
void ParCallCmd(out Cmd d) { Contract.Ensures(Contract.ValueAtReturn(out d) != null); IToken x; QKeyValue kv = null; Cmd c = null; List<CallCmd> callCmds = new List<CallCmd>(); Expect(54); x = t; while (la.kind == 28) { Attribute(ref kv); } CallParams(false, false, kv, x, out c); callCmds.Add((CallCmd)c); while (la.kind == 55) { Get(); CallParams(false, false, kv, x, out c); callCmds.Add((CallCmd)c); } Expect(9); d = new ParCallCmd(x, callCmds, kv); }
void LabelOrAssign(out Cmd c, out IToken label) { IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0; c = dummyCmd; label = null; AssignLhs/*!*/ lhs; List<AssignLhs/*!*/>/*!*/ lhss; List<Expr/*!*/>/*!*/ rhss; List<Expr/*!*/>/*!*/ indexes; Ident(out id); x = t; if (la.kind == 12) { Get(); c = null; label = x; } else if (la.kind == 13 || la.kind == 18 || la.kind == 51) { lhss = new List<AssignLhs/*!*/>(); lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); while (la.kind == 18) { MapAssignIndex(out y, out indexes); lhs = new MapAssignLhs(y, lhs, indexes); } lhss.Add(lhs); while (la.kind == 13) { Get(); Ident(out id); lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); while (la.kind == 18) { MapAssignIndex(out y, out indexes); lhs = new MapAssignLhs(y, lhs, indexes); } lhss.Add(lhs); } Expect(51); x = t; /* use location of := */ Expression(out e0); rhss = new List<Expr/*!*/> (); rhss.Add(e0); while (la.kind == 13) { Get(); Expression(out e0); rhss.Add(e0); } Expect(9); c = new AssignCmd(x, lhss, rhss); } else SynErr(111); }
// perform in place update of liveSet public static void Propagate(Cmd cmd, HashSet<Variable/*!*/>/*!*/ liveSet) { Contract.Requires(cmd != null); Contract.Requires(cce.NonNullElements(liveSet)); if (cmd is AssignCmd) { AssignCmd/*!*/ assignCmd = (AssignCmd)cce.NonNull(cmd); // I must first iterate over all the targets and remove the live ones. // After the removals are done, I must add the variables referred on // the right side of the removed targets AssignCmd simpleAssignCmd = assignCmd.AsSimpleAssignCmd; HashSet<int> indexSet = new HashSet<int>(); int index = 0; foreach (AssignLhs/*!*/ lhs in simpleAssignCmd.Lhss) { Contract.Assert(lhs != null); SimpleAssignLhs salhs = lhs as SimpleAssignLhs; Contract.Assert(salhs != null); Variable var = salhs.DeepAssignedVariable; if (var != null && liveSet.Contains(var)) { indexSet.Add(index); liveSet.Remove(var); } index++; } index = 0; foreach (Expr/*!*/ expr in simpleAssignCmd.Rhss) { Contract.Assert(expr != null); if (indexSet.Contains(index)) { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); liveSet.UnionWith(collector.usedVars); } index++; } } else if (cmd is HavocCmd) { HavocCmd/*!*/ havocCmd = (HavocCmd)cmd; foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) { Contract.Assert(expr != null); if (expr.Decl != null && !(QKeyValue.FindBoolAttribute(expr.Decl.Attributes, "assumption") && expr.Decl.Name.StartsWith("a##cached##"))) { liveSet.Remove(expr.Decl); } } } else if (cmd is PredicateCmd) { Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd)); PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd); if (predicateCmd.Expr is LiteralExpr) { LiteralExpr le = (LiteralExpr)predicateCmd.Expr; if (le.IsFalse) { liveSet.Clear(); } } else { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(predicateCmd.Expr); liveSet.UnionWith(collector.usedVars); } } else if (cmd is CommentCmd) { // comments are just for debugging and don't affect verification } else if (cmd is SugaredCmd) { SugaredCmd/*!*/ sugCmd = (SugaredCmd)cce.NonNull(cmd); Propagate(sugCmd.Desugaring, liveSet); } else if (cmd is StateCmd) { StateCmd/*!*/ stCmd = (StateCmd)cce.NonNull(cmd); List<Cmd>/*!*/ cmds = cce.NonNull(stCmd.Cmds); int len = cmds.Count; for (int i = len - 1; i >= 0; i--) { Propagate(cmds[i], liveSet); } foreach (Variable/*!*/ v in stCmd.Locals) { Contract.Assert(v != null); liveSet.Remove(v); } } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } }
private static GenKillWeight getWeightBeforeCall(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); Contract.Assert((cmd is CallCmd)); if (weightCacheBeforeCall.ContainsKey(cmd)) return weightCacheBeforeCall[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); CallCmd/*!*/ ccmd = cce.NonNull((CallCmd/*!*/)cmd); foreach (Expr/*!*/ expr in ccmd.Ins) { Contract.Assert(expr != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); gen.UnionWith(collector.usedVars); } Contract.Assert(ccmd.Proc != null); // Variables in requires are considered as "read" foreach (Requires/*!*/ re in ccmd.Proc.Requires) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.usedVars) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } // Old variables in ensures are considered as "read" foreach (Ensures/*!*/ re in ccmd.Proc.Ensures) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.oldVarsUsed) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill); Contract.Assert(ret != null); weightCacheAfterCall[cmd] = ret; return ret; }
private static GenKillWeight getWeightAfterCall(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); if (weightCacheAfterCall.ContainsKey(cmd)) return weightCacheAfterCall[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); Contract.Assert(cmd is CallCmd); CallCmd/*!*/ ccmd = cce.NonNull((CallCmd)cmd); foreach (IdentifierExpr/*!*/ ie in ccmd.Outs) { Contract.Assert(ie != null); if (ie.Decl != null) kill.Add(ie.Decl); } // Variables in ensures are considered as "read" foreach (Ensures/*!*/ re in cce.NonNull(ccmd.Proc).Ensures) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.usedVars) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill); Contract.Assert(ret != null); weightCacheAfterCall[cmd] = ret; return ret; }
private static GenKillWeight getWeight(Cmd cmd, Implementation impl, Program prog) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); if (weightCache.ContainsKey(cmd)) return weightCache[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); GenKillWeight/*!*/ ret; if (cmd is AssignCmd) { AssignCmd/*!*/ assignCmd = (AssignCmd)cmd; Contract.Assert(cmd != null); // I must first iterate over all the targets and remove the live ones. // After the removals are done, I must add the variables referred on // the right side of the removed targets foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) { Contract.Assert(lhs != null); Variable var = lhs.DeepAssignedVariable; if (var != null) { if (lhs is SimpleAssignLhs) { // we should only remove non-map target variables because there is an implicit // read of a map variable in an assignment to it kill.Add(var); } } } int index = 0; foreach (Expr/*!*/ expr in assignCmd.Rhss) { Contract.Assert(expr != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); gen.UnionWith(collector.usedVars); AssignLhs lhs = assignCmd.Lhss[index]; if (lhs is MapAssignLhs) { // If the target is a map, then all indices are also read MapAssignLhs malhs = (MapAssignLhs)lhs; foreach (Expr e in malhs.Indexes) { VariableCollector/*!*/ c = new VariableCollector(); c.Visit(e); gen.UnionWith(c.usedVars); } } index++; } ret = new GenKillWeight(gen, kill); } else if (cmd is HavocCmd) { HavocCmd/*!*/ havocCmd = (HavocCmd)cce.NonNull(cmd); foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) { Contract.Assert(expr != null); if (expr.Decl != null) { kill.Add(expr.Decl); } } ret = new GenKillWeight(gen, kill); } else if (cmd is PredicateCmd) { Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd)); PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd); if (predicateCmd.Expr is LiteralExpr && prog != null && impl != null) { LiteralExpr le = (LiteralExpr)predicateCmd.Expr; if (le.IsFalse) { var globals = prog.GlobalVariables; Contract.Assert(cce.NonNullElements(globals)); foreach (Variable/*!*/ v in globals) { Contract.Assert(v != null); kill.Add(v); } foreach (Variable/*!*/ v in impl.LocVars) { Contract.Assert(v != null); kill.Add(v); } foreach (Variable/*!*/ v in impl.OutParams) { Contract.Assert(v != null); kill.Add(v); } } } else { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(predicateCmd.Expr); gen.UnionWith(collector.usedVars); } ret = new GenKillWeight(gen, kill); } else if (cmd is CommentCmd) { ret = new GenKillWeight(gen, kill); // comments are just for debugging and don't affect verification } else if (cmd is SugaredCmd) { SugaredCmd/*!*/ sugCmd = (SugaredCmd)cmd; Contract.Assert(sugCmd != null); ret = getWeight(sugCmd.Desugaring, impl, prog); } else if (cmd is StateCmd) { StateCmd/*!*/ stCmd = (StateCmd)cmd; Contract.Assert(stCmd != null); List<Cmd>/*!*/ cmds = stCmd.Cmds; Contract.Assert(cmds != null); int len = cmds.Count; ret = GenKillWeight.one(); for (int i = len - 1; i >= 0; i--) { GenKillWeight/*!*/ w = getWeight(cmds[i], impl, prog); Contract.Assert(w != null); ret = GenKillWeight.extend(w, ret); } foreach (Variable/*!*/ v in stCmd.Locals) { Contract.Assert(v != null); kill.Add(v); } ret = GenKillWeight.extend(new GenKillWeight(gen, kill), ret); } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } weightCache[cmd] = ret; return ret; }
void CallCmd(out Cmd c) { Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken x; bool isAsync = false; bool isFree = false; QKeyValue kv = null; c = null; if (la.kind == 52) { Get(); isAsync = true; } if (la.kind == 36) { Get(); isFree = true; } Expect(53); x = t; while (la.kind == 28) { Attribute(ref kv); } CallParams(isAsync, isFree, kv, x, out c); }
static List<Cmd> GetOptimizedBody(List<Cmd> cmds) { Contract.Requires(cmds != null); Contract.Ensures(Contract.Result<List<Cmd>>() != null); int n = 0; foreach (Cmd c in cmds) { n++; PredicateCmd pc = c as PredicateCmd; if (pc != null && pc.Expr is LiteralExpr && ((LiteralExpr)pc.Expr).IsFalse) { // return a sequence consisting of the commands seen so far Cmd[] s = new Cmd[n]; for (int i = 0; i < n; i++) { s[i] = cmds[i]; } return new List<Cmd>(s); } } return cmds; }
void CallParams(bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c) { List<IdentifierExpr> ids = new List<IdentifierExpr>(); List<Expr> es = new List<Expr>(); Expr en; IToken first; IToken p; c = null; Ident(out first); if (la.kind == 10) { Get(); if (StartOf(9)) { Expression(out en); es.Add(en); while (la.kind == 13) { Get(); Expression(out en); es.Add(en); } } Expect(11); c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; } else if (la.kind == 13 || la.kind == 51) { ids.Add(new IdentifierExpr(first, first.val)); if (la.kind == 13) { Get(); Ident(out p); ids.Add(new IdentifierExpr(p, p.val)); while (la.kind == 13) { Get(); Ident(out p); ids.Add(new IdentifierExpr(p, p.val)); } } Expect(51); Ident(out first); Expect(10); if (StartOf(9)) { Expression(out en); es.Add(en); while (la.kind == 13) { Get(); Expression(out en); es.Add(en); } } Expect(11); c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; } else SynErr(112); }
/// <summary> /// Computes the wlp for an assert or assume command "cmd". /// </summary> public static VCExpr P_Cmd(Block b, HashSet<string> constantsAssumed, Cmd cmd, VCExpr N, VCContext ctxt) { Contract.Requires(cmd != null); Contract.Requires(N != null); Contract.Requires(ctxt != null); Contract.Ensures(Contract.Result<VCExpr>() != null); VCExpressionGenerator gen = ctxt.Ctxt.ExprGen; Contract.Assert(gen != null); if (cmd is AssertCmd) { AssertCmd ac = (AssertCmd)cmd; ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr); ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) { return gen.Implies(C, N); } else { int id = ac.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = ac; } switch (Subsumption(ac)) { case CommandLineOptions.SubsumptionOption.Never: break; case CommandLineOptions.SubsumptionOption.Always: N = gen.Implies(C, N); break; case CommandLineOptions.SubsumptionOption.NotForQuantifiers: if (!(C is VCExprQuantifier)) { N = gen.Implies(C, N); } break; default: Contract.Assert(false); throw new cce.UnreachableException(); // unexpected case } // (MSchaef) Hack: This line might be useless, but at least it is not harmful // need to test it if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) return gen.Implies(C, N); ctxt.AssertionCount++; if (ctxt.ControlFlowVariableExpr == null) { Contract.Assert(ctxt.Label2absy != null); return gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N); } else { VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId))); Contract.Assert(controlFlowFunctionAppl != null); VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId))); if (ctxt.Label2absy == null) { return gen.AndSimp(gen.Implies(assertFailure, C), N); } else { return gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N); } } } } else if (cmd is AssumeCmd) { AssumeCmd ac = (AssumeCmd)cmd; if (CommandLineOptions.Clo.StratifiedInlining > 0) { Contract.Assert(false); throw new System.Exception(string.Format("VC Generation in ICE-learning does not handle stratified inlining")); var pname = QKeyValue.FindStringAttribute(ac.Attributes, "candidate"); if (pname != null) { return gen.ImpliesSimp(gen.LabelPos("candidate_" + pname.ToString(), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } // Label the assume if it is a procedure call NAryExpr naryExpr = ac.Expr as NAryExpr; if (naryExpr != null) { if (naryExpr.Fun is FunctionCall) { int id = ac.UniqueId; ctxt.Label2absy[id] = ac; return gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } } } else { if (constantsAssumed == null) return gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N); // check if the assume command contains any of the constantsAssumed (corresponding to existential function calls)? var funcsUsed = FunctionCollector.Collect(ac.Expr); bool hasAnyConstantAssumed = false; foreach (var tup in funcsUsed) { var constantFunc = tup.Item1; if (constantsAssumed.Contains(constantFunc.Name)) { hasAnyConstantAssumed = true; break; } } if (hasAnyConstantAssumed) { int id = ac.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = ac; } //ctxt.AssertionCount++; if (ctxt.ControlFlowVariableExpr == null) { Contract.Assert(ctxt.Label2absy != null); return gen.ImpliesSimp(gen.LabelPos(cce.NonNull(id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } else { /* TODO: Check if this is correct!! */ VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId))); Contract.Assert(controlFlowFunctionAppl != null); VCExpr assumeFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId))); if (ctxt.Label2absy == null) { throw new System.Exception(string.Format("Dont know how to handle labels for the assume cmd")); //return gen.ImpliesSimp(gen.LabelPos(cce.NonNull(id.ToString()), gen.Implies(assumeFailure, ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr))), N); } else { return gen.ImpliesSimp(gen.LabelPos(cce.NonNull(id.ToString()), gen.Implies(assumeFailure, ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr))), N); } } } else return gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N); } } else { Console.WriteLine(cmd.ToString()); Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command } }
void LabelOrCmd(out Cmd c, out IToken label) { IToken/*!*/ x; Expr/*!*/ e; List<IToken>/*!*/ xs; List<IdentifierExpr> ids; c = dummyCmd; label = null; Cmd/*!*/ cn; QKeyValue kv = null; switch (la.kind) { case 1: { LabelOrAssign(out c, out label); break; } case 47: { Get(); x = t; while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssertCmd(x, e, kv); Expect(9); break; } case 48: { Get(); x = t; while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssumeCmd(x, e, kv); Expect(9); break; } case 49: { Get(); x = t; Idents(out xs); Expect(9); ids = new List<IdentifierExpr>(); foreach(IToken/*!*/ y in xs){ Contract.Assert(y != null); ids.Add(new IdentifierExpr(y, y.val)); } c = new HavocCmd(x,ids); break; } case 36: case 52: case 53: { CallCmd(out cn); Expect(9); c = cn; break; } case 54: { ParCallCmd(out cn); c = cn; break; } case 50: { Get(); x = t; Expect(9); c = new YieldCmd(x); break; } default: SynErr(106); break; } }
// ----------------------------- Substitutions for Cmd ------------------------------- /// <summary> /// Apply a substitution to a command. Any variables not in domain(subst) /// is not changed. The substitutions apply within the "old", but the "old" /// expression remains. /// </summary> public static Cmd Apply(Substitution subst, Cmd cmd) { Contract.Requires(subst != null); Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<Cmd>() != null); return (Cmd)new NormalSubstituter(subst).Visit(cmd); }
private void GenerateErrorMessage(Cmd causalStatement, List<Cmd> causals) { Contract.Requires(causalStatement != null); Contract.Requires(cce.NonNullElements(causals)); AssumeCmd uc = causalStatement as AssumeCmd; AssertCmd ac = causalStatement as AssertCmd; ConsoleColor col = Console.ForegroundColor; // Trivial case. Must be either assume or assert false if (m_doomedCmds.Count == 1) { Console.WriteLine("Found a trivial error:"); if (uc != null) { Console.Write("Trivial false assumption: "); Console.Write("({0};{1}):", uc.tok.line, uc.tok.col); } if (ac != null) { Console.Write("Trivial false assertion: "); Console.Write("({0};{1}):", ac.tok.line, ac.tok.col); } causalStatement.Emit(new TokenTextWriter("<console>", Console.Out, false), 0); } else { // Safety error if (ac != null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Safety error:"); Console.ForegroundColor = col; Console.Write("This assertion is violated: "); Console.Write("({0};{1}):", ac.tok.line, ac.tok.col); ac.Emit(new TokenTextWriter("<console>", Console.Out, false), 0); } if (uc != null) { bool containsAssert = false; foreach (Cmd c in m_doomedCmds) { Contract.Assert(c != null); if (causals.Contains(c)) { continue; } AssertCmd asrt = c as AssertCmd; if (asrt != null) { containsAssert = true; break; } } // Plausibility error if (containsAssert) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Plausibility error:"); Console.ForegroundColor = col; Console.Write("There is no legal exeuction passing: "); Console.Write("({0};{1})", uc.tok.line, uc.tok.col); uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0); } else { // Reachability error Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Reachability error:"); Console.ForegroundColor = col; Console.Write("No execution can reach: "); Console.Write("({0};{1})", uc.tok.line, uc.tok.col); uc.Emit(new TokenTextWriter("<console>", Console.Out, false), 0); } } Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("...on any execution passing through:"); foreach (Cmd c in m_doomedCmds) { Contract.Assert(c != null); if (causals.Contains(c)) { continue; } Console.ForegroundColor = col; Console.Write("In ({0};{1}): ", c.tok.line, c.tok.col); Console.ForegroundColor = ConsoleColor.DarkYellow; c.Emit(new TokenTextWriter("<console>", Console.Out, false), 0); } Console.ForegroundColor = col; Console.WriteLine("--"); } }
/// <summary> /// Computes the wlp for an assert or assume command "cmd". /// </summary> public static VCExpr Cmd(Block b, Cmd cmd, VCExpr N, VCContext ctxt) { Contract.Requires(cmd != null); Contract.Requires(N != null); Contract.Requires(ctxt != null); Contract.Ensures(Contract.Result<VCExpr>() != null); VCExpressionGenerator gen = ctxt.Ctxt.ExprGen; Contract.Assert(gen != null); if (cmd is AssertCmd) { AssertCmd ac = (AssertCmd)cmd; ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr); ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) { return gen.Implies(C, N); } else { int id = ac.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = ac; } switch (Subsumption(ac)) { case CommandLineOptions.SubsumptionOption.Never: break; case CommandLineOptions.SubsumptionOption.Always: N = gen.Implies(C, N); break; case CommandLineOptions.SubsumptionOption.NotForQuantifiers: if (!(C is VCExprQuantifier)) { N = gen.Implies(C, N); } break; default: Contract.Assert(false); throw new cce.UnreachableException(); // unexpected case } // (MSchaef) Hack: This line might be useless, but at least it is not harmful // need to test it if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) return gen.Implies(C, N); ctxt.AssertionCount++; if (ctxt.ControlFlowVariableExpr == null) { Contract.Assert(ctxt.Label2absy != null); return gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N); } else { VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId))); Contract.Assert(controlFlowFunctionAppl != null); VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId))); if (ctxt.Label2absy == null) { return gen.AndSimp(gen.Implies(assertFailure, C), N); } else { return gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N); } } } } else if (cmd is AssumeCmd) { AssumeCmd ac = (AssumeCmd)cmd; if (CommandLineOptions.Clo.StratifiedInlining > 0) { var pname = QKeyValue.FindStringAttribute(ac.Attributes, "candidate"); if (pname != null) { return gen.ImpliesSimp(gen.LabelPos("candidate_" + pname.ToString(), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } // Label the assume if it is a procedure call NAryExpr naryExpr = ac.Expr as NAryExpr; if (naryExpr != null) { if (naryExpr.Fun is FunctionCall) { int id = ac.UniqueId; ctxt.Label2absy[id] = ac; return gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } } } return gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N); } else { Console.WriteLine(cmd.ToString()); Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command } }
void PredicateCmd(List<Cmd> cmdSeq, Cmd cmd) { if (cmd is AssignCmd) { var aCmd = (AssignCmd)cmd; cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss, new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) => new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, rhs, lhs.AsExpr }))))); } else if (cmd is AssertCmd) { var aCmd = (AssertCmd)cmd; if (cmdSeq.Last() is AssignCmd && cmdSeq.Cast<Cmd>().SkipEnd(1).All(c => c is AssertCmd)) { // This may be a loop invariant. Make sure it continues to appear as // the first statement in the block. var assign = cmdSeq.Last(); cmdSeq.RemoveAt(cmdSeq.Count-1); Expr newExpr = new EnabledReplacementVisitor(pExpr).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(pExpr, newExpr); cmdSeq.Add(aCmd); // cmdSeq.Add(new AssertCmd(aCmd.tok, Expr.Imp(pExpr, aCmd.Expr))); cmdSeq.Add(assign); } else { aCmd.Expr = Expr.Imp(p, aCmd.Expr); cmdSeq.Add(aCmd); // cmdSeq.Add(new AssertCmd(aCmd.tok, Expr.Imp(p, aCmd.Expr))); } } else if (cmd is AssumeCmd) { var aCmd = (AssumeCmd)cmd; cmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Imp(p, aCmd.Expr))); } else if (cmd is HavocCmd) { var hCmd = (HavocCmd)cmd; foreach (IdentifierExpr v in hCmd.Vars) { Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type; Contract.Assert(type != null); IdentifierExpr havocTempExpr; if (havocVars.ContainsKey(type)) { havocTempExpr = havocVars[type]; } else { var havocVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_HAVOC_" + type.ToString(), type)); impl.LocVars.Add(havocVar); havocVars[type] = havocTempExpr = new IdentifierExpr(Token.NoToken, havocVar); } cmdSeq.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr> { havocTempExpr })); cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v, new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, havocTempExpr, v }))); } } else if (cmd is CallCmd) { Debug.Assert(useProcedurePredicates); var cCmd = (CallCmd)cmd; cCmd.Ins.Insert(0, p); cmdSeq.Add(cCmd); } else if (cmd is CommentCmd) { // skip } else if (cmd is StateCmd) { var sCmd = (StateCmd)cmd; var newCmdSeq = new List<Cmd>(); foreach (Cmd c in sCmd.Cmds) PredicateCmd(newCmdSeq, c); sCmd.Cmds = newCmdSeq; cmdSeq.Add(sCmd); } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
public void Add(Cmd cmd) { Contract.Requires(cmd != null); if (simpleCmds == null) { simpleCmds = new List<Cmd>(); } simpleCmds.Add(cmd); }
private bool IsCallCmdExitPoint(Cmd cmd, int yTypeCheckCurrentPhaseNum) { if (cmd is CallCmd) { CallCmd callee = cmd as CallCmd; int phaseSpecCallee = moverTypeChecker.FindPhaseNumber(callee.Proc); if (phaseSpecCallee >= yTypeCheckCurrentPhaseNum) { #if DEBUG && !DEBUG_DETAIL Console.Write("\nCall Cmd Check is " + callCmd.Proc.Name + "\n"); #endif return true; } } return false; }
/* * Visitor functions of basic commands */ private string GetEdgeType(Cmd cmd) { if (cmd is YieldCmd) { return "Y"; } else if (cmd is HavocCmd) { return "Q"; } else if (cmd is AssumeCmd) { return "P"; } else if (cmd is AssertCmd) { return "E"; } else if (cmd is CallCmd) { CallCmd callCmd = cmd as CallCmd; foreach (Ensures e in callCmd.Proc.Ensures) { if (QKeyValue.FindBoolAttribute(e.Attributes, "atomic")) { return "A"; } else if (QKeyValue.FindBoolAttribute(e.Attributes, "right")) { return "R"; } else if (QKeyValue.FindBoolAttribute(e.Attributes, "left")) { return "L"; } else if (QKeyValue.FindBoolAttribute(e.Attributes, "both")) { return "B"; } } } //rest can only be assigncmd AssignCmd assgnCmd = cmd as AssignCmd; return "Q"; }
void PredicateCmd(Expr p, Expr pDom, List<Cmd> cmdSeq, Cmd cmd) { if (cmd is CallCmd) { var cCmd = (CallCmd)cmd; Debug.Assert(useProcedurePredicates(cCmd.Proc)); cCmd.Ins.Insert(0, p != null ? p : Expr.True); cmdSeq.Add(cCmd); } else if (p == null) { new EnabledReplacementVisitor(Expr.True, pDom).Visit(cmd); cmdSeq.Add(cmd); } else if (cmd is AssignCmd) { var aCmd = (AssignCmd)cmd; cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss, new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) => new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, rhs, lhs.AsExpr }))))); } else if (cmd is AssertCmd) { var aCmd = (AssertCmd)cmd; Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr); cmdSeq.Add(aCmd); } else if (cmd is AssumeCmd) { var aCmd = (AssumeCmd)cmd; Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr); cmdSeq.Add(aCmd); } else if (cmd is HavocCmd) { var hCmd = (HavocCmd)cmd; foreach (IdentifierExpr v in hCmd.Vars) { Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type; Contract.Assert(type != null); IdentifierExpr havocTempExpr; if (havocVars.ContainsKey(type)) { havocTempExpr = havocVars[type]; } else { var havocVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_HAVOC_" + type.ToString(), type)); impl.LocVars.Add(havocVar); havocVars[type] = havocTempExpr = new IdentifierExpr(Token.NoToken, havocVar); } cmdSeq.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr> { havocTempExpr })); cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v, new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, havocTempExpr, v }))); } } else if (cmd is CommentCmd) { // skip } else if (cmd is StateCmd) { var sCmd = (StateCmd)cmd; var newCmdSeq = new List<Cmd>(); foreach (Cmd c in sCmd.Cmds) PredicateCmd(p, pDom, newCmdSeq, c); sCmd.Cmds = newCmdSeq; cmdSeq.Add(sCmd); } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
/// <summary> /// Computes the wlp for an assert or assume command "cmd". /// </summary> internal static VCExpr Cmd(Block b, Cmd cmd, VCExpr N, VCContext ctxt) { Contract.Requires(cmd != null); Contract.Requires(N != null); Contract.Requires(ctxt != null); Contract.Ensures(Contract.Result<VCExpr>() != null); VCExpressionGenerator gen = ctxt.Ctxt.ExprGen; Contract.Assert(gen != null); if (cmd is AssertCmd) { AssertCmd ac = (AssertCmd)cmd; var isFullyVerified = false; if (ac.VerifiedUnder != null) { var litExpr = ac.VerifiedUnder as LiteralExpr; isFullyVerified = litExpr != null && litExpr.IsTrue; } if (!isFullyVerified) { ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; } VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr); VCExpr VU = null; if (!isFullyVerified) { if (ac.VerifiedUnder != null) { VU = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.VerifiedUnder); if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) { ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd); VU = gen.Or(VU, gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++)))); } } else if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) { ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd); VU = gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++))); } ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; } VCExpr R = null; if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) { R = gen.Implies(C, N); } else { var subsumption = Subsumption(ac); if (subsumption == CommandLineOptions.SubsumptionOption.Always || (subsumption == CommandLineOptions.SubsumptionOption.NotForQuantifiers && !(C is VCExprQuantifier))) { N = gen.ImpliesSimp(C, N, false); } if (isFullyVerified) { return N; } else if (VU != null) { C = gen.OrSimp(VU, C); } int id = ac.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = ac; } ctxt.AssertionCount++; if (ctxt.ControlFlowVariableExpr == null) { Contract.Assert(ctxt.Label2absy != null); R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N); } else { VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId))); Contract.Assert(controlFlowFunctionAppl != null); VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId))); if (ctxt.Label2absy == null) { R = gen.AndSimp(gen.Implies(assertFailure, C), N); } else { R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N); } } } return R; } else if (cmd is AssumeCmd) { AssumeCmd ac = (AssumeCmd)cmd; if (CommandLineOptions.Clo.StratifiedInlining > 0) { // Label the assume if it is a procedure call NAryExpr naryExpr = ac.Expr as NAryExpr; if (naryExpr != null) { if (naryExpr.Fun is FunctionCall) { int id = ac.UniqueId; ctxt.Label2absy[id] = ac; return MaybeWrapWithOptimization(ctxt, gen, ac.Attributes, gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N)); } } } var expr = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr); var aid = QKeyValue.FindStringAttribute(ac.Attributes, "id"); if (aid != null) { var isTry = QKeyValue.FindBoolAttribute(ac.Attributes, "try"); var v = gen.Variable((isTry ? "try$$" : "assume$$") + aid, Microsoft.Boogie.Type.Bool); expr = gen.Function(VCExpressionGenerator.NamedAssumeOp, v, gen.ImpliesSimp(v, expr)); } var soft = QKeyValue.FindBoolAttribute(ac.Attributes, "soft"); var softWeight = QKeyValue.FindIntAttribute(ac.Attributes, "soft", 0); if ((soft || 0 < softWeight) && aid != null) { var v = gen.Variable("soft$$" + aid, Microsoft.Boogie.Type.Bool); expr = gen.Function(new VCExprSoftOp(Math.Max(softWeight, 1)), v, gen.ImpliesSimp(v, expr)); } return MaybeWrapWithOptimization(ctxt, gen, ac.Attributes, gen.ImpliesSimp(expr, N)); } else { Console.WriteLine(cmd.ToString()); Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command } }
/// <summary> /// Apply a substitution to a command replacing "old" expressions. /// Outside "old" expressions, the substitution "always" is applied; any variable not in /// domain(always) is not changed. Inside "old" expressions, apply map "forOld" to /// variables in domain(forOld), apply map "always" to variables in /// domain(always)-domain(forOld), and leave variable unchanged otherwise. /// </summary> public static Cmd ApplyReplacingOldExprs(Substitution always, Substitution forOld, Cmd cmd) { Contract.Requires(always != null); Contract.Requires(forOld != null); Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<Cmd>() != null); return (Cmd)new ReplacingOldSubstituter(always, forOld).Visit(cmd); }
/// <summary> /// Computes the wlp for an assert or assume command "cmd". /// </summary> public static VCExpr Cmd(Block b, Cmd cmd, VCExpr N, VCContext ctxt) { Contract.Requires(cmd != null); Contract.Requires(N != null); Contract.Requires(ctxt != null); Contract.Ensures(Contract.Result<VCExpr>() != null); VCExpressionGenerator gen = ctxt.Ctxt.ExprGen; Contract.Assert(gen != null); if (cmd is AssertCmd) { AssertCmd ac = (AssertCmd)cmd; var isFullyVerified = false; if (ac.VerifiedUnder != null) { var litExpr = ac.VerifiedUnder as LiteralExpr; isFullyVerified = litExpr != null && litExpr.IsTrue; } if (!isFullyVerified) { ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; } VCExpr C = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr); VCExpr VU = null; if (!isFullyVerified) { if (ac.VerifiedUnder != null) { VU = ctxt.Ctxt.BoogieExprTranslator.Translate(ac.VerifiedUnder); if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) { ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd); VU = gen.Or(VU, gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++)))); } } else if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) { ctxt.Ctxt.TimeoutDiagnosticIDToAssertion[ctxt.Ctxt.TimoutDiagnosticsCount] = new Tuple<AssertCmd,TransferCmd>(ac, b.TransferCmd); VU = gen.Function(VCExpressionGenerator.TimeoutDiagnosticsOp, gen.Integer(BigNum.FromInt(ctxt.Ctxt.TimoutDiagnosticsCount++))); } ctxt.Ctxt.BoogieExprTranslator.isPositiveContext = !ctxt.Ctxt.BoogieExprTranslator.isPositiveContext; } VCExpr R = null; if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) { R = gen.Implies(C, N); } else { var subsumption = Subsumption(ac); if (subsumption == CommandLineOptions.SubsumptionOption.Always || (subsumption == CommandLineOptions.SubsumptionOption.NotForQuantifiers && !(C is VCExprQuantifier))) { N = gen.ImpliesSimp(C, N, false); } if (isFullyVerified) { return N; } else if (VU != null) { C = gen.OrSimp(VU, C); } int id = ac.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = ac; } ctxt.AssertionCount++; if (ctxt.ControlFlowVariableExpr == null) { Contract.Assert(ctxt.Label2absy != null); R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), C), N); } else { VCExpr controlFlowFunctionAppl = gen.ControlFlowFunctionApplication(ctxt.ControlFlowVariableExpr, gen.Integer(BigNum.FromInt(b.UniqueId))); Contract.Assert(controlFlowFunctionAppl != null); VCExpr assertFailure = gen.Eq(controlFlowFunctionAppl, gen.Integer(BigNum.FromInt(-ac.UniqueId))); if (ctxt.Label2absy == null) { R = gen.AndSimp(gen.Implies(assertFailure, C), N); } else { R = gen.AndSimp(gen.LabelNeg(cce.NonNull(id.ToString()), gen.Implies(assertFailure, C)), N); } } } return R; } else if (cmd is AssumeCmd) { AssumeCmd ac = (AssumeCmd)cmd; if (CommandLineOptions.Clo.StratifiedInlining > 0) { // Label the assume if it is a procedure call NAryExpr naryExpr = ac.Expr as NAryExpr; if (naryExpr != null) { if (naryExpr.Fun is FunctionCall) { int id = ac.UniqueId; ctxt.Label2absy[id] = ac; return gen.ImpliesSimp(gen.LabelPos(cce.NonNull("si_fcall_" + id.ToString()), ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr)), N); } } } return gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N); } else { Console.WriteLine(cmd.ToString()); Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command } }