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()); } }
private bool Analyse(Implementation impl, List <Cmd> cmdSeq, bool ControlFlowIsUniform) { foreach (Cmd c in cmdSeq) { if (c is AssignCmd) { AssignCmd assignCmd = c as AssignCmd; foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss)) { if (a.Item1 is SimpleAssignLhs) { SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs; Expr rhs = a.Item2; if (IsUniform(impl.Name, lhs.AssignedVariable.Name) && (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs))) { SetNonUniform(impl.Name, lhs.AssignedVariable.Name); } } } } else if (c is HavocCmd) { HavocCmd havocCmd = c as HavocCmd; foreach (IdentifierExpr ie in havocCmd.Vars) { if (IsUniform(impl.Name, ie.Decl.Name)) { SetNonUniform(impl.Name, ie.Decl.Name); } } } else if (c is CallCmd) { CallCmd callCmd = c as CallCmd; DeclWithFormals Callee = GetProcedure(callCmd.callee); Debug.Assert(Callee != null); if (!ControlFlowIsUniform) { if (IsUniform(callCmd.callee)) { SetNonUniform(callCmd.callee); } } for (int i = 0; i < Callee.InParams.Count; i++) { if (IsUniform(callCmd.callee, Callee.InParams[i].Name) && !IsUniform(impl.Name, callCmd.Ins[i])) { SetNonUniform(callCmd.callee, Callee.InParams[i].Name); } } for (int i = 0; i < Callee.OutParams.Count; i++) { if (IsUniform(impl.Name, callCmd.Outs[i].Name) && !IsUniform(callCmd.callee, Callee.OutParams[i].Name)) { SetNonUniform(impl.Name, callCmd.Outs[i].Name); } } } else if (c is AssumeCmd) { var ac = (AssumeCmd)c; if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") && !IsUniform(impl.Name, ac.Expr)) { ControlFlowIsUniform = false; } } } return(ControlFlowIsUniform); }
public static void Predicate(Program p, Func <Procedure, bool> useProcedurePredicates = null, UniformityAnalyser uni = null) { useProcedurePredicates = useProcedurePredicates ?? (proc => false); if (uni != null) { var oldUPP = useProcedurePredicates; useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); } foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is Procedure || decl is Implementation) { var proc = decl as Procedure; Implementation impl = null; if (proc == null) { impl = (Implementation)decl; proc = impl.Proc; } bool upp = useProcedurePredicates(proc); if (upp) { var dwf = (DeclWithFormals)decl; var fpVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/ true); dwf.InParams = new List <Variable>( (new Variable[] { fpVar }.Concat(dwf.InParams.Cast <Variable>())) .ToArray()); if (impl == null) { var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar); foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition); if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) { r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition); } } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition); if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) { e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition); } } } } else { if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition); } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition); } } } if (impl != null) { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); } catch (Program.IrreducibleLoopException) { } } } } }
public static bool HasAttribute(this ICarriesAttributes obj, string attribute) { return(QKeyValue.FindBoolAttribute(obj.Attributes, attribute)); }
private void IntroduceIntermediateVars() { var oldSub = SubstitutionHelper.FromVariableMap(LatestCopies(trc.PreStateVars)); assignments = new List <Assignment>(); assumes = new List <Expr>(); for (int k = 0; k < trc.path.Count; k++) { if (trc.IsJoint && k == trc.transferIndex) { PopulateIntermediateFrameCopy(); oldSub = SubstitutionHelper.FromVariableMap(LatestCopies(trc.PreStateVars)); } Cmd cmd = trc.path[k]; if (cmd is AssignCmd assignCmd) { assignCmd = assignCmd.AsSimpleAssignCmd; var preState = LatestCopies(); foreach (var v in assignCmd.Lhss) { MakeNewCopy(v.DeepAssignedVariable); } var postState = LatestCopies(); if (QKeyValue.FindBoolAttribute(assignCmd.Attributes, CivlAttributes.BACKWARD)) { var tmp = preState; preState = postState; postState = tmp; } var rhsSub = SubstitutionHelper.FromVariableMap(preState); for (int i = 0; i < assignCmd.Lhss.Count; i++) { var var = postState[assignCmd.Lhss[i].DeepAssignedVariable]; var expr = Substituter.ApplyReplacingOldExprs(rhsSub, oldSub, assignCmd.Rhss[i]); assignments.Add(new Assignment(var, expr)); } } else if (cmd is AssumeCmd assumeCmd) { var sub = SubstitutionHelper.FromVariableMap(LatestCopies()); assumes.Add(Substituter.ApplyReplacingOldExprs(sub, oldSub, assumeCmd.Expr)); } else if (cmd is HavocCmd havocCmd) { foreach (var v in havocCmd.Vars) { MakeNewCopy(v.Decl); } } else { Debug.Assert(false); } } // In case there were no commands from the second action if (trc.IsJoint && trc.path.Count == trc.transferIndex) { PopulateIntermediateFrameCopy(); } }
public void TypeCheck() { foreach (var proc in program.Procedures) { if (!QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) { continue; } int createdAtLayerNum; // must be initialized by the following code, otherwise it is an error int availableUptoLayerNum = int.MaxValue; List <int> attrs = FindLayers(proc.Attributes); if (attrs.Count == 1) { createdAtLayerNum = attrs[0]; } else if (attrs.Count == 2) { createdAtLayerNum = attrs[0]; availableUptoLayerNum = attrs[1]; } else { Error(proc, "Incorrect number of layers"); continue; } foreach (Ensures e in proc.Ensures) { MoverType moverType = GetMoverType(e); if (moverType == MoverType.Top) { continue; } CodeExpr codeExpr = e.Condition as CodeExpr; if (codeExpr == null) { Error(e, "An atomic action must be a CodeExpr"); continue; } if (procToActionInfo.ContainsKey(proc)) { Error(proc, "A procedure can have at most one atomic action"); continue; } if (availableUptoLayerNum <= createdAtLayerNum) { Error(proc, "Creation layer number must be less than the available upto layer number"); continue; } minLayerNum = int.MaxValue; maxLayerNum = -1; canAccessSharedVars = true; enclosingProc = proc; enclosingImpl = null; base.VisitEnsures(e); canAccessSharedVars = false; if (maxLayerNum > createdAtLayerNum) { Error(e, "A variable being accessed is introduced after this action is created"); } else if (availableUptoLayerNum > minLayerNum) { Error(e, "A variable being accessed is hidden before this action becomes unavailable"); } else { procToActionInfo[proc] = new AtomicActionInfo(proc, e, moverType, createdAtLayerNum, availableUptoLayerNum); } } if (errorCount > 0) { continue; } if (!procToActionInfo.ContainsKey(proc)) { if (availableUptoLayerNum < createdAtLayerNum) { Error(proc, "Creation layer number must be no more than the available upto layer number"); continue; } else { procToActionInfo[proc] = new ActionInfo(proc, createdAtLayerNum, availableUptoLayerNum); } } } if (errorCount > 0) { return; } foreach (var impl in program.Implementations) { if (!procToActionInfo.ContainsKey(impl.Proc)) { continue; } procToActionInfo[impl.Proc].hasImplementation = true; } foreach (var proc in procToActionInfo.Keys) { ActionInfo actionInfo = procToActionInfo[proc]; if (actionInfo.isExtern && actionInfo.hasImplementation) { Error(proc, "Extern procedure cannot have an implementation"); continue; } if (actionInfo.isExtern || actionInfo.hasImplementation) { continue; } if (leastUnimplementedLayerNum == int.MaxValue) { leastUnimplementedLayerNum = actionInfo.createdAtLayerNum; } else if (leastUnimplementedLayerNum != actionInfo.createdAtLayerNum) { Error(proc, "All unimplemented atomic actions must be created at the same layer"); } } foreach (var g in this.globalVarToSharedVarInfo.Keys) { var info = globalVarToSharedVarInfo[g]; if (!this.AllCreatedLayerNums.Contains(info.introLayerNum)) { Error(g, "Variable must be introduced with creation of some atomic action"); } if (info.hideLayerNum != int.MaxValue && !this.AllCreatedLayerNums.Contains(info.hideLayerNum)) { Error(g, "Variable must be hidden with creation of some atomic action"); } } if (errorCount > 0) { return; } this.VisitProgram(program); foreach (Procedure proc in program.Procedures) { if (procToActionInfo.ContainsKey(proc)) { continue; } foreach (var ie in proc.Modifies) { if (!SharedVariables.Contains(ie.Decl)) { continue; } Error(proc, "A ghost procedure must not modify a global variable with layer annotation"); } } if (errorCount > 0) { return; } YieldTypeChecker.PerformYieldSafeCheck(this); new LayerEraser().VisitProgram(program); }
private void IntroduceIntermediateVars() { var oldSub = Substituter.SubstitutionFromHashtable(GetPreStateVars(). ToDictionary <Variable, Variable, Expr>(v => v, v => Expr.Ident(varCopies[0][v]))); newCmds = new List <Cmd>(); for (int k = 0; k < cmds.Count; k++) { if (IsJoint() && k == transitionRelationComputer.transferIndex) { PopulateIntermediateFrameCopy(); oldSub = Substituter.SubstitutionFromHashtable(GetPreStateVars(). ToDictionary <Variable, Variable, Expr>(v => v, v => Expr.Ident(varCopies[varLastCopyId[v]][v]))); } Cmd cmd = cmds[k]; if (cmd is AssignCmd) { AssignCmd assignCmd = ((AssignCmd)cmd).AsSimpleAssignCmd; var preState = GetVarCopiesFromIds(varLastCopyId); foreach (var v in assignCmd.Lhss) { MakeNewCopy(v.DeepAssignedVariable); } var postState = GetVarCopiesFromIds(varLastCopyId); Dictionary <Variable, Variable> lhsMap = postState, rhsMap = preState; if (QKeyValue.FindBoolAttribute(assignCmd.Attributes, CivlAttributes.BACKWARD)) { lhsMap = preState; rhsMap = postState; } var rhsSub = Substituter.SubstitutionFromHashtable( rhsMap.ToDictionary( kvp => kvp.Key, kvp => Expr.Ident(kvp.Value) as Expr )); List <AssignLhs> lhss = assignCmd.Lhss.Select(x => (AssignLhs) new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lhsMap[x.DeepAssignedVariable]))).ToList(); List <Expr> rhss = assignCmd.Rhss.Select(x => Substituter.ApplyReplacingOldExprs(rhsSub, oldSub, x)).ToList(); newCmds.Add(new AssignCmd(Token.NoToken, lhss, rhss, assignCmd.Attributes)); } else if (cmd is AssumeCmd) { var sub = Substituter.SubstitutionFromHashtable( GetVarCopiesFromIds(varLastCopyId).ToDictionary( kvp => kvp.Key, kvp => Expr.Ident(kvp.Value) as Expr )); newCmds.Add(new AssumeCmd(cmd.tok, Substituter.ApplyReplacingOldExprs(sub, oldSub, ((AssumeCmd)cmd).Expr))); } else if (cmd is HavocCmd havocCmd) { foreach (var v in havocCmd.Vars) { MakeNewCopy(v.Decl); } } else { Debug.Assert(false); } } // TODO: Add note on this if (!IsJoint() || cmds.Count == transitionRelationComputer.transferIndex) { PopulateIntermediateFrameCopy(); } }
public void TypeCheck() { foreach (var proc in program.Procedures) { if (!QKeyValue.FindBoolAttribute(proc.Attributes, "pure")) { continue; } if (QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) { Error(proc, "Pure procedure must not yield"); continue; } if (QKeyValue.FindBoolAttribute(proc.Attributes, "layer")) { Error(proc, "Pure procedure must not have layers"); continue; } if (proc.Modifies.Count > 0) { Error(proc, "Pure procedure must not modify a global variable"); continue; } procToAtomicProcedureInfo[proc] = new AtomicProcedureInfo(); } foreach (var proc in program.Procedures) { if (QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) { continue; } var procLayerNums = FindLayers(proc.Attributes); if (procLayerNums.Count == 0) { continue; } foreach (IdentifierExpr ie in proc.Modifies) { if (!globalVarToSharedVarInfo.ContainsKey(ie.Decl)) { Error(proc, "Atomic procedure cannot modify a global variable without layer numbers"); continue; } } int lower, upper; if (procLayerNums.Count == 1) { lower = procLayerNums[0]; upper = procLayerNums[0]; } else if (procLayerNums.Count == 2) { lower = procLayerNums[0]; upper = procLayerNums[1]; if (lower >= upper) { Error(proc, "Lower layer must be less than upper layer"); continue; } } else { Error(proc, "Atomic procedure must specify a layer range"); continue; } LayerRange layerRange = new LayerRange(lower, upper); procToAtomicProcedureInfo[proc] = new AtomicProcedureInfo(layerRange); } if (errorCount > 0) { return; } foreach (Implementation impl in program.Implementations) { if (!procToAtomicProcedureInfo.ContainsKey(impl.Proc)) { continue; } var atomicProcedureInfo = procToAtomicProcedureInfo[impl.Proc]; if (atomicProcedureInfo.isPure) { this.enclosingImpl = impl; (new PurityChecker(this)).VisitImplementation(impl); } else { this.enclosingImpl = impl; this.sharedVarsAccessed = new HashSet <Variable>(); (new PurityChecker(this)).VisitImplementation(impl); LayerRange upperBound = FindLayerRange(); LayerRange lowerBound = atomicProcedureInfo.layerRange; if (!lowerBound.Subset(upperBound)) { Error(impl, "Atomic procedure cannot access global variable"); } this.sharedVarsAccessed = null; } } if (errorCount > 0) { return; } foreach (var proc in program.Procedures) { if (!QKeyValue.FindBoolAttribute(proc.Attributes, "yields")) { continue; } int createdAtLayerNum; // must be initialized by the following code, otherwise it is an error int availableUptoLayerNum = int.MaxValue; List <int> attrs = FindLayers(proc.Attributes); if (attrs.Count == 1) { createdAtLayerNum = attrs[0]; } else if (attrs.Count == 2) { createdAtLayerNum = attrs[0]; availableUptoLayerNum = attrs[1]; } else { Error(proc, "Incorrect number of layers"); continue; } foreach (Ensures e in proc.Ensures) { MoverType moverType = GetMoverType(e); if (moverType == MoverType.Top) { continue; } CodeExpr codeExpr = e.Condition as CodeExpr; if (codeExpr == null) { Error(e, "An atomic action must be a CodeExpr"); continue; } if (procToActionInfo.ContainsKey(proc)) { Error(proc, "A procedure can have at most one atomic action"); continue; } if (availableUptoLayerNum <= createdAtLayerNum) { Error(proc, "Creation layer number must be less than the available upto layer number"); continue; } sharedVarsAccessed = new HashSet <Variable>(); enclosingProc = proc; enclosingImpl = null; base.VisitEnsures(e); LayerRange upperBound = FindLayerRange(); LayerRange lowerBound = new LayerRange(createdAtLayerNum, availableUptoLayerNum); if (lowerBound.Subset(upperBound)) { procToActionInfo[proc] = new AtomicActionInfo(proc, e, moverType, createdAtLayerNum, availableUptoLayerNum); } else { Error(e, "A variable being accessed in this action is unavailable"); } sharedVarsAccessed = null; } if (errorCount > 0) { continue; } if (!procToActionInfo.ContainsKey(proc)) { if (availableUptoLayerNum < createdAtLayerNum) { Error(proc, "Creation layer number must be no more than the available upto layer number"); continue; } else { procToActionInfo[proc] = new ActionInfo(proc, createdAtLayerNum, availableUptoLayerNum); } } } if (errorCount > 0) { return; } foreach (var impl in program.Implementations) { if (!procToActionInfo.ContainsKey(impl.Proc)) { continue; } ActionInfo actionInfo = procToActionInfo[impl.Proc]; procToActionInfo[impl.Proc].hasImplementation = true; if (actionInfo.isExtern) { Error(impl.Proc, "Extern procedure cannot have an implementation"); } } if (errorCount > 0) { return; } foreach (Procedure proc in procToActionInfo.Keys) { for (int i = 0; i < proc.InParams.Count; i++) { Variable v = proc.InParams[i]; var layer = FindLocalVariableLayer(proc, v, procToActionInfo[proc].createdAtLayerNum); if (layer == int.MinValue) { continue; } localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer); } for (int i = 0; i < proc.OutParams.Count; i++) { Variable v = proc.OutParams[i]; var layer = FindLocalVariableLayer(proc, v, procToActionInfo[proc].createdAtLayerNum); if (layer == int.MinValue) { continue; } localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer); } } foreach (Implementation node in program.Implementations) { if (!procToActionInfo.ContainsKey(node.Proc)) { continue; } foreach (Variable v in node.LocVars) { var layer = FindLocalVariableLayer(node, v, procToActionInfo[node.Proc].createdAtLayerNum); if (layer == int.MinValue) { continue; } localVarToLocalVariableInfo[v] = new LocalVariableInfo(layer); } for (int i = 0; i < node.Proc.InParams.Count; i++) { Variable v = node.Proc.InParams[i]; if (!localVarToLocalVariableInfo.ContainsKey(v)) { continue; } var layer = localVarToLocalVariableInfo[v].layer; localVarToLocalVariableInfo[node.InParams[i]] = new LocalVariableInfo(layer); } for (int i = 0; i < node.Proc.OutParams.Count; i++) { Variable v = node.Proc.OutParams[i]; if (!localVarToLocalVariableInfo.ContainsKey(v)) { continue; } var layer = localVarToLocalVariableInfo[v].layer; localVarToLocalVariableInfo[node.OutParams[i]] = new LocalVariableInfo(layer); } } if (errorCount > 0) { return; } this.VisitProgram(program); if (errorCount > 0) { return; } YieldTypeChecker.PerformYieldSafeCheck(this); new LayerEraser().VisitProgram(program); }
public static void Predicate(Program p, Func <Procedure, bool> useProcedurePredicates = null, UniformityAnalyser uni = null) { useProcedurePredicates = useProcedurePredicates ?? (proc => false); if (uni != null) { var oldUPP = useProcedurePredicates; useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); } foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is Procedure || decl is Implementation) { var proc = decl as Procedure; Implementation impl = null; if (proc == null) { impl = (Implementation)decl; proc = impl.Proc; } bool upp = useProcedurePredicates(proc); if (upp) { var dwf = (DeclWithFormals)decl; // Copy InParams, as the list is shared between impl and proc var inParams = new List <Variable>(dwf.InParams); var fpVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/ true); inParams.Insert(0, fpVar); var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar); // Add in-parameters for all out-parameters. These new in-parameters // are used to ensure we preserve the value of the variable assigned // to when the passed predicate value is false. var newEqParamExprs = new List <Expr>(); var newAssignCmds = new List <Cmd>(); foreach (Variable outV in dwf.OutParams) { var inV = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_V" + outV.TypedIdent.Name, outV.TypedIdent.Type), /*incoming=*/ true); inParams.Add(inV); var inVExpr = new IdentifierExpr(Token.NoToken, inV); var outVExpr = new IdentifierExpr(Token.NoToken, outV); newEqParamExprs.Add(Expr.Imp(Expr.Not(fpIdentifierExpr), Expr.Eq(inVExpr, outVExpr))); newAssignCmds.Add(new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, outVExpr) }, new List <Expr> { new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { fpIdentifierExpr, outVExpr, inVExpr }) })); } dwf.InParams = inParams; if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition); if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) { r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition); } } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition); if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) { e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition); } } foreach (Expr e in newEqParamExprs) { proc.Ensures.Add(new Ensures(false, e)); } } else { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); foreach (AssignCmd c in newAssignCmds) { impl.Blocks.First().Cmds.Insert(0, c); } } catch (Program.IrreducibleLoopException) { } } } else { if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition); } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition); } } else { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); } catch (Program.IrreducibleLoopException) { } } } } } }
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()); } }