public override Cmd VisitHavocCmd(HavocCmd node) { Block currBlock = worklist.cmdBlocks[node]; Dependencies dependencies = worklist.GatherPredecessorsState(node, currBlock); // Havoc x translates to x <- * foreach (var v in node.Vars.Select(x => x.Decl)) { dependencies[v] = new VarSet(); dependencies[v].Add(Utils.VariableUtils.NonDetVar); InferDominatorDependency(currBlock, dependencies[v]); if (changedProcs.Contains(nodeToImpl[node].Proc) || changedBlocks.Contains(currBlock)) // native taint { if (Analysis.DacMerged == null || IsImpactedSummary(nodeToImpl[node].Proc, v)) { dependencies[v].Add(Utils.VariableUtils.BottomUpTaintVar); } } } if (worklist.Assign(node, dependencies)) { worklist.Propagate(node); } return(node); }
private void m_HavocLoopBody(Loop l) { List <Block> loopblocks = new List <Block>(); foreach (GraphNode g in l.LoopNodes) { loopblocks.Add(g.Label); } HavocCmd hcmd = m_ComputHavocCmd(loopblocks, l.Cutpoint.Label.tok); //Add Havoc before and after the loop body foreach (GraphNode g in l.Cutpoint.Suc) // before { if (l.LoopNodes.Contains(g)) { m_AddHavocCmdToFront(g.Label, hcmd); } } foreach (GraphNode g in l.Cutpoint.Pre) // and after { if (l.LoopNodes.Contains(g)) { m_AddHavocCmdToFront(g.Label, hcmd); } } }
private ConstantProp ApplyHavoc(HavocCmd cmd) { var ret = new Dictionary <string, Value>(); // Deep copy val.Iter(kvp => ret.Add(kvp.Key, new Value(kvp.Value))); foreach (var v in cmd.Vars.OfType <IdentifierExpr>()) { if (!val.ContainsKey(v.Name)) { continue; } if (!ret.ContainsKey(v.Name)) { ret.Add(v.Name, Value.GetTop()); } else { ret[v.Name] = Value.GetTop(); } } return(new ConstantProp(ret, impl)); }
private void m_AddHavocCmdToFront(Block b, HavocCmd hcmd) { List <Cmd> cs = new List <Cmd>(); cs.Add(hcmd); cs.AddRange(b.Cmds); b.Cmds = cs; }
public virtual Cmd VisitHavocCmd(HavocCmd node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result <Cmd>() != null); node.Vars = this.VisitIdentifierExprSeq(node.Vars); return(node); }
private void AddPath() { HashSet <Variable> existsVars = new HashSet <Variable>(); Dictionary <Variable, Expr> varToExpr = new Dictionary <Variable, Expr>(); foreach (Variable v in frame) { varToExpr[v] = Expr.Ident(v); } if (first != null) { foreach (Variable v in first.thatOutParams) { varToExpr[v] = Expr.Ident(v); } } foreach (Variable v in second.thisOutParams) { varToExpr[v] = Expr.Ident(v); } List <Expr> pathExprs = new List <Expr>(); int boundVariableCount = 0; foreach (Cmd cmd in cmdStack) { if (cmd is AssumeCmd) { AssumeCmd assumeCmd = cmd as AssumeCmd; FlattenAnd(assumeCmd.Expr, pathExprs); } else if (cmd is AssignCmd) { AssignCmd assignCmd = (cmd as AssignCmd).AsSimpleAssignCmd; Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); for (int k = 0; k < assignCmd.Lhss.Count; k++) { map[assignCmd.Lhss[k].DeepAssignedVariable] = assignCmd.Rhss[k]; } Substitute(map, ref pathExprs, ref varToExpr); } else if (cmd is HavocCmd) { HavocCmd havocCmd = cmd as HavocCmd; Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (IdentifierExpr ie in havocCmd.Vars) { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "#tmp_" + boundVariableCount++, ie.Decl.TypedIdent.Type)); map[ie.Decl] = Expr.Ident(bv); existsVars.Add(bv); } Substitute(map, ref pathExprs, ref varToExpr); } else { Debug.Assert(false); } } paths.Add(new PathInfo(existsVars, varToExpr, pathExprs)); }
public override Cmd VisitHavocCmd(HavocCmd node) { if (node.Vars.All(x => !x.Type.IsMap)) { return(base.VisitHavocCmd(node)); } throw new Exception(string.Format("Do not allow havoc over map variables, found {0}", node.ToString())); }
public override Cmd VisitHavocCmd(HavocCmd node) { var dispatchedVars = new List <IdentifierExpr>(); foreach (var x in node.Vars) { dispatchedVars.Add(VisitIdentifierExpr(x) as IdentifierExpr); } return(new HavocCmd(Token.NoToken, dispatchedVars)); }
public SymbolicVariable(string name, HavocCmd cmd, int varsIndex) : base(Token.NoToken, CopyAndRename(cmd.Vars[varsIndex].Decl.TypedIdent, name)) { Expr = new IdentifierExpr(Token.NoToken, this, /*immutable=*/ true); this.Origin = cmd.GetProgramLocation(); Debug.Assert(this.Origin.IsCmd && (this.Origin.AsCmd is HavocCmd), "Expected ProgramLocation to be a HavocCmd"); this.Name = name; Debug.WriteLine("Creating Symbolic " + this); // Should we record VarsIndex? }
//desugar into single havoc commands private IList <Term> TranslateHavocCmd(HavocCmd node) { var varResults = node.Vars.Select(var => TranslateIdentifierExpr(var)); IList <Term> results = new List <Term>(); foreach (var v in varResults) { results.Add(IsaBoogieTerm.Havoc(v)); } return(results); }
private void AbstractReadAccesses(InstrumentationRegion region) { foreach (var b in region.Blocks()) { for (int k = 0; k < b.Cmds.Count; k++) { if (!(b.Cmds[k] is AssignCmd)) { continue; } foreach (var rhs in (b.Cmds[k] as AssignCmd).Rhss.OfType <NAryExpr>()) { if (!(rhs.Fun is MapSelect) || rhs.Args.Count != 2 || !((rhs.Args[0] as IdentifierExpr).Name.StartsWith("$M."))) { continue; } Variable v = (b.Cmds[k] as AssignCmd).Lhss[0].DeepAssignedVariable; HavocCmd havoc = new HavocCmd(Token.NoToken, new List <IdentifierExpr> { new IdentifierExpr(v.tok, v) }); b.Cmds[k] = havoc; } if (!(b.Cmds[k] is AssignCmd)) { continue; } foreach (var rhs in (b.Cmds[k] as AssignCmd).Rhss.OfType <IdentifierExpr>()) { if (!(rhs.Name.StartsWith("$M."))) { continue; } Variable v = (b.Cmds[k] as AssignCmd).Lhss[0].DeepAssignedVariable; HavocCmd havoc = new HavocCmd(Token.NoToken, new List <IdentifierExpr> { new IdentifierExpr(v.tok, v) }); b.Cmds[k] = havoc; } } } }
public override Cmd VisitHavocCmd(HavocCmd node) { var cmd = base.VisitHavocCmd(node) as HavocCmd; var newVars = new List <IdentifierExpr>(); var seen = new HashSet <string>(); foreach (IdentifierExpr ie in cmd.Vars) { if (!seen.Contains(ie.Name)) { newVars.Add(ie); seen.Add(ie.Name); } } cmd.Vars = newVars; return(cmd); }
private void TransitionRelationComputationHelper(Program program, AtomicActionInfo first, AtomicActionInfo second) { this.program = program; this.first = first; this.second = second; this.cmdStack = new Stack <Cmd>(); this.paths = new List <PathInfo>(); List <IdentifierExpr> havocVars = new List <IdentifierExpr>(); this.second.thisOutParams.ForEach(v => havocVars.Add(Expr.Ident(v))); this.second.thisAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v))); if (havocVars.Count > 0) { HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars); cmdStack.Push(havocCmd); } Search(this.second.thisAction.Blocks[0], false); }
public SymbolicVariable GetFreshSymbolic(HavocCmd havocCmd, int varsIndex, ExecutionState owner) { ++Requests; SymbolicVariableStack havocVarStack = null; var key = Tuple.Create(havocCmd, varsIndex); try { havocVarStack = HavocCmdStacks[key]; } catch (KeyNotFoundException) { // XXX: This is a little misleading the "Pool" doesn't use the owner argument // so the SymbolicVariableStack doesn't known about this owner havocVarStack = new SymbolicVariableStack(() => Pool.GetFreshSymbolic(havocCmd, varsIndex, null)); HavocCmdStacks.Add(key, havocVarStack); } return(havocVarStack.GetVariable(owner)); }
private void Search(Block b, bool inFirst) { int pathSizeAtEntry = cmdStack.Count; foreach (Cmd cmd in b.Cmds) { cmdStack.Push(cmd); } if (b.TransferCmd is ReturnCmd) { if (first == null || inFirst) { AddPath(); } else { List <IdentifierExpr> havocVars = new List <IdentifierExpr>(); first.thatOutParams.ForEach(v => havocVars.Add(Expr.Ident(v))); first.thatAction.LocVars.ForEach(v => havocVars.Add(Expr.Ident(v))); if (havocVars.Count > 0) { HavocCmd havocCmd = new HavocCmd(Token.NoToken, havocVars); cmdStack.Push(havocCmd); } Search(first.thatAction.Blocks[0], true); } } else { GotoCmd gotoCmd = b.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { Search(target, inFirst); } } Debug.Assert(cmdStack.Count >= pathSizeAtEntry); while (cmdStack.Count > pathSizeAtEntry) { cmdStack.Pop(); } }
public override Cmd VisitHavocCmd(HavocCmd node) { // gather state from all predecesors Block currBlock = worklist.cmdBlocks[node]; var predTaintSet = worklist.GatherPredecessorsState(node, currBlock); var taintSet = new TaintSet(predTaintSet); // the assignment has the potential to cleanse the taint taintSet.RemoveWhere(v => node.Vars.Exists(o => o.Decl == v)); if (changedProcs.Contains(nodeToImpl[node].Proc) || changedBlocks.Contains(currBlock) || // native taint InferDominatorTaint(currBlock)) // control taint { node.Vars.Iter(v => taintSet.Add(v.Decl)); } if (worklist.Assign(node, taintSet)) { worklist.Propagate(node); } return(node); }
public override Cmd VisitHavocCmd(HavocCmd node) { add(node); return(base.VisitHavocCmd(node)); }
public override Cmd VisitHavocCmd(HavocCmd node) { return(base.VisitHavocCmd((HavocCmd)node.Clone())); }
public override Cmd VisitHavocCmd(HavocCmd node) { node.Vars.Iter(v => createdVars.Add(v.Name)); return(node); }
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 SymbolicVariable GetFreshSymbolic(HavocCmd cmd, int varsIndex, ExecutionState owner) { ++Count; return(new SymbolicVariable(GetNewSymbolicVariableName(cmd, varsIndex), cmd, varsIndex)); }
private HashSet <Variable> PropagateAvailableLinearVarsAcrossBlock(Block b) { HashSet <Variable> start = new HashSet <Variable>(availableLinearVars[b]); foreach (Cmd cmd in b.Cmds) { if (cmd is AssignCmd) { AssignCmd assignCmd = (AssignCmd)cmd; for (int i = 0; i < assignCmd.Lhss.Count; i++) { if (FindDomainName(assignCmd.Lhss[i].DeepAssignedVariable) == null) { continue; } IdentifierExpr ie = assignCmd.Rhss[i] as IdentifierExpr; if (start.Contains(ie.Decl)) { start.Remove(ie.Decl); } else { Error(ie, "unavailable source for a linear read"); } } foreach (AssignLhs assignLhs in assignCmd.Lhss) { if (FindDomainName(assignLhs.DeepAssignedVariable) == null) { continue; } start.Add(assignLhs.DeepAssignedVariable); } } else if (cmd is CallCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name)); } CallCmd callCmd = (CallCmd)cmd; for (int i = 0; i < callCmd.Proc.InParams.Count; i++) { if (FindDomainName(callCmd.Proc.InParams[i]) == null) { continue; } IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr; if (start.Contains(ie.Decl)) { start.Remove(ie.Decl); } else { Error(ie, "unavailable source for a linear read"); } } availableLinearVars[callCmd] = new HashSet <Variable>(start); foreach (IdentifierExpr ie in callCmd.Outs) { if (FindDomainName(ie.Decl) == null) { continue; } start.Add(ie.Decl); } } else if (cmd is ParCallCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name)); } ParCallCmd parCallCmd = (ParCallCmd)cmd; foreach (CallCmd callCmd in parCallCmd.CallCmds) { for (int i = 0; i < callCmd.Proc.InParams.Count; i++) { if (FindDomainName(callCmd.Proc.InParams[i]) == null) { continue; } IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr; if (start.Contains(ie.Decl)) { start.Remove(ie.Decl); } else { Error(ie, "unavailable source for a linear read"); } } } availableLinearVars[parCallCmd] = new HashSet <Variable>(start); foreach (CallCmd callCmd in parCallCmd.CallCmds) { foreach (IdentifierExpr ie in callCmd.Outs) { if (FindDomainName(ie.Decl) == null) { continue; } start.Add(ie.Decl); } } } else if (cmd is HavocCmd) { HavocCmd havocCmd = (HavocCmd)cmd; foreach (IdentifierExpr ie in havocCmd.Vars) { if (FindDomainName(ie.Decl) == null) { continue; } start.Remove(ie.Decl); } } else if (cmd is YieldCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a yield", g.Name)); } availableLinearVars[cmd] = new HashSet <Variable>(start); } } return(start); }
protected string GetNewSymbolicVariableName(HavocCmd havocCmd, int varsIndex) { return(GetNewSymbolicVariableName(havocCmd.Vars[varsIndex].Decl)); }
// This procedure carries out variable slicing for all commands in the block. It will add more // local variables (needed for slicing) if impl is not null. The flag onlyGlobals restricts attention // to only slicing global variables private Block sliceBlock(Block block) { // The new list of commands that we will construct List <Cmd> sliced = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { // Eliminate trivial statements like assume true if (isAssumeTrue(cmd)) { // This is an assume true, don't put it in the final program if (tinfo != null) { tinfo.add(currImplementation.Name, block.Label, new InstrTrans(cmd, new List <Cmd>())); } continue; } // if cmd does not refer to a un-tracked global variable, then don't // bother, and move on to the next cmd if (isTracked(cmd)) { sliced.Add(cmd); if (tinfo != null) { tinfo.add(currImplementation.Name, block.Label, new InstrTrans(cmd, cmd)); } continue; } List <Cmd> newcmd = new List <Cmd>(); // Now we need to look at what sort of a command are we dealing with if (cmd is AssignCmd) { newcmd = AbstractAssign(cmd as AssignCmd); } else if (cmd is AssertCmd) { Log.WriteLine(Log.Debug, "\nWarning: An assert has an untracked variable: it'll become assert false"); newcmd.Add(new AssertCmd(Token.NoToken, Expr.Literal(false))); } else if (cmd is AssumeCmd) { // Do Nothing. } else if (cmd is CallCmd) { CallCmd ccmd = (CallCmd)cmd; // Process the call arguments: if anything is untracked, then // convert to a dummy variable var newIns = new List <Expr>(); foreach (var exp in ccmd.Ins) { if (exp == null) { newIns.Add(null); } else if (!isTracked(exp)) { Debug.Assert(currImplementation != null); var dvar = getNewLocal(exp.Type, currImplementation); newcmd.Add(new HavocCmd(Token.NoToken, new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(dvar) }))); newIns.Add(Expr.Ident(dvar)); } else { newIns.Add(exp); } } // Process the returns: if anything is untracked then simply call // the procedure, without storing its return value var newOuts = new List <IdentifierExpr>(); foreach (var exp in ccmd.Outs) { if (exp == null) { newOuts.Add(null); } else if (!isTracked(exp)) { Debug.Assert(currImplementation != null); var dvar = getNewLocal(exp.Type, currImplementation); newOuts.Add(Expr.Ident(dvar)); } else { newOuts.Add(exp); } } CallCmd tmp = new CallCmd(ccmd.tok, ccmd.Proc.Name, newIns, newOuts, ccmd.Attributes, ccmd.IsAsync); tmp.Proc = ccmd.Proc; // just to keep the proc declarations in sync newcmd.Add(tmp); } else if (cmd is HavocCmd) { // Remove the havoced variables that are not tracked. HavocCmd hcmd = (HavocCmd)cmd; var newvars = new List <IdentifierExpr>(); foreach (IdentifierExpr ie in hcmd.Vars) { if (isTrackedVariable(ie.Decl)) { newvars.Add(ie); } } if (newvars.Count != 0) { newcmd.Add(new HavocCmd(hcmd.tok, newvars)); } } else { cmd.Emit(new TokenTextWriter(Console.Out), 0); throw new InternalError("Unkown Cmd type encountered during variable slicing"); } sliced.AddRange(newcmd); if (tinfo != null) { tinfo.add(currImplementation.Name, block.Label, new InstrTrans(cmd, newcmd)); } } return(new Block(block.tok, block.Label, sliced, block.TransferCmd)); }
private Expr CalculatePathCondition() { Expr returnExpr = Expr.True; foreach (Variable v in program.GlobalVariables()) { var eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, v), new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); returnExpr = Expr.And(eqExpr, returnExpr); } if (first != null) { foreach (Variable v in first.thisOutParams) { var eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, v), new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); returnExpr = Expr.And(eqExpr, returnExpr); } } foreach (Variable v in second.thatOutParams) { var eqExpr = Expr.Eq(new IdentifierExpr(Token.NoToken, v), new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); returnExpr = Expr.And(eqExpr, returnExpr); } Block[] dfsStackAsArray = dfsStack.Reverse().ToArray(); for (int i = dfsStackAsArray.Length - 1; i >= 0; i--) { Block b = dfsStackAsArray[i]; for (int j = b.Cmds.Count - 1; j >= 0; j--) { Cmd cmd = b.Cmds[j]; if (cmd is AssumeCmd) { AssumeCmd assumeCmd = cmd as AssumeCmd; returnExpr = Expr.And(new OldExpr(Token.NoToken, assumeCmd.Expr), returnExpr); } else if (cmd is AssignCmd) { AssignCmd assignCmd = (cmd as AssignCmd).AsSimpleAssignCmd; Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); for (int k = 0; k < assignCmd.Lhss.Count; k++) { map[assignCmd.Lhss[k].DeepAssignedVariable] = assignCmd.Rhss[k]; } Substitution subst = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>()); Substitution oldSubst = Substituter.SubstitutionFromHashtable(map); returnExpr = (Expr) new MySubstituter(subst, oldSubst).Visit(returnExpr); } else if (cmd is HavocCmd) { HavocCmd havocCmd = cmd as HavocCmd; List <Variable> existVars = new List <Variable>(); Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (IdentifierExpr ie in havocCmd.Vars) { BoundVariable bv = GetBoundVariable(ie.Decl.TypedIdent.Type); map[ie.Decl] = new IdentifierExpr(Token.NoToken, bv); existVars.Add(bv); } Substitution subst = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>()); Substitution oldSubst = Substituter.SubstitutionFromHashtable(map); returnExpr = new ExistsExpr(Token.NoToken, existVars, (Expr) new MySubstituter(subst, oldSubst).Visit(returnExpr)); } else { Debug.Assert(false); } } } return(returnExpr); }
// perform in place update of liveSet public static void Propagate(Cmd cmd, HashSet <Variable /*!*/> /*!*/ liveSet, bool allGlobalsAreLive) { 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) || (allGlobalsAreLive && var is GlobalVariable))) { 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); if (allGlobalsAreLive) { liveSet.UnionWith(collector.usedVars.Where(v => v is LocalVariable || v is Formal)); } else { 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) { 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); if (allGlobalsAreLive) { liveSet.UnionWith(collector.usedVars.Where(v => v is LocalVariable || v is Formal)); } else { 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, allGlobalsAreLive); } 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, allGlobalsAreLive); } foreach (Variable /*!*/ v in stCmd.Locals) { Contract.Assert(v != null); liveSet.Remove(v); } } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } }
public static Duple <Procedure, Implementation> EqualityReduction(Implementation i1, Implementation i2, ParamMap argMap, HashSet <Variable> ignoreSet, out List <Variable> outputVarsForVFTask) { //map ins1 //map outs1 //save globals (1) //... //call //... //save outs //save globals (2) //restore globals (1) //... //call //... //compare Procedure d1 = i1.Proc, d2 = i2.Proc; var globals = new List <Variable>(); foreach (IdentifierExpr ie in d1.Modifies) { globals.Add(ie.Decl); } foreach (IdentifierExpr ie in d2.Modifies) { if (!globals.Contains(ie.Decl)) { globals.Add(ie.Decl); } } /***** Produce mapped list of identifiers *****/ string d1n = d1.Name, d2n = d2.Name; List <Variable> outs1 = FreshVariables(d1.OutParams, B.Factory.MakeLocal), outs2 = FreshVariables(d2.OutParams, B.Factory.MakeLocal), ins1 = FreshVariables(d1.InParams, (x, y) => B.Factory.MakeFormal(x, y, true)), ins2 = FreshVariables(d2.InParams, (x, y) => B.Factory.MakeFormal(x, y, true)); /***** Compute correspondence between d1's ins/outs and d2's ins/outs *****/ List <Variable> unionIns, unionOuts, newIns1, newOuts1, interIns, interOuts; MergeVariableSequencesByMap(ins1, ins2, argMap, out newIns1, out unionIns, out interIns); MergeVariableSequencesByMap(outs1, outs2, argMap, out newOuts1, out unionOuts, out interOuts); ins1 = newIns1; outs1 = newOuts1; /***** Map ignore set to the new variables *****/ for (int i = 0; i < i2.OutParams.Count; i++) { if (ignoreSet.Contains(i2.OutParams[i])) { Log.Out(Log.Warning, "Equality reduction ignoring variable: " + outs2[i].Name); ignoreSet.Add(outs2[i]); } } /***** Emit instructions for saving and restoring *****/ SaveBlock savedInitialGlobals = new SaveBlock(globals.Count); SaveBlock savedc1Globals = new SaveBlock(globals.Count); SaveBlock savedOutputs = new SaveBlock(interOuts.Count); var globalsArr = B.U.VariablesOfVariableSeq(globals); Cmd[] prec1Copy = savedInitialGlobals.EmitSave(globalsArr), postc1Copy = savedc1Globals.EmitSave(globalsArr), postc1Restore = savedInitialGlobals.EmitRestore(globalsArr), prec2Copy = savedOutputs.EmitSave(B.U.VariablesOfVariableSeq(interOuts)); /***** Emit function calls *****/ var c1Ins = B.U.ExprSeqOfVariableSeq(ins1); var c1Outs = B.U.IdentifierExprSeqOfVariableSeq(outs1); var c2Ins = B.U.ExprSeqOfVariableSeq(ins2); var c2Outs = B.U.IdentifierExprSeqOfVariableSeq(outs2); CallCmd c1 = new CallCmd(Token.NoToken, d1n, c1Ins, c1Outs), c2 = new CallCmd(Token.NoToken, d2n, c2Ins, c2Outs); /***** Emit comparison, outputVars *****/ var outputVars = new List <Duple <string, Variable> >(); int numComparables = savedOutputs.Count + savedc1Globals.Count; //wait! if there aren't any comparable values, don't bother emitting a comparator if (numComparables == 0) { Log.Out(Log.Verifier, "No outputs: skipping (" + d1n + ", " + d2n + ")"); outputVarsForVFTask = null; return(null); } if (Options.CheckOutputsForMaps) { foreach (Variable v in savedOutputs.Decls) { if (v.TypedIdent.Type is MapType) { Log.Out(Log.MapEquivs, v.Name + " in " + i1.Name + " is a map comparable!"); } } foreach (Variable v in savedc1Globals.Decls) { if (v.TypedIdent.Type is MapType || v.TypedIdent.Type is TypeSynonymAnnotation) { Log.Out(Log.MapEquivs, v.Name + " global is a map comparable!"); } } } StateBlock outputEqualityState = new StateBlock(numComparables, StateBlock.StateKind.FormalOut); Tuple <Expr, Variable>[] outputEqualityExprs = new Tuple <Expr, Variable> [numComparables]; outputEqualityState.Initialize(Microsoft.Boogie.Type.Bool); IdentifierExpr[] comparisonPostc1Vars = savedc1Globals.Idents, comparisonPrec2Vars = savedOutputs.Idents; List <IdentifierExpr> comparisonOutIds = B.U.IdentifierExprSeqOfVariableSeq(outs2), comparisonGlobals = B.U.IdentifierExprSeqOfVariableSeq(globals); for (int i = 0; i < savedOutputs.Count; i++) { outputEqualityExprs[i] = Tuple.Create(EmitEq(comparisonPrec2Vars[i], comparisonOutIds[i], ignoreSet), comparisonOutIds[i].Decl); outputVars.Add(new Duple <string, Variable>("Output_of_" + d1.Name + "_" + outs1[i].Name, savedOutputs.Decls[i])); outputVars.Add(new Duple <string, Variable>("Output_of_" + d2.Name + "_" + outs2[i].Name, outs2[i])); } for (int i = 0; i < savedc1Globals.Count; i++) { outputEqualityExprs[savedOutputs.Count + i] = Tuple.Create(EmitEq(comparisonPostc1Vars[i], comparisonGlobals[i], ignoreSet), comparisonGlobals[i].Decl); outputVars.Add(new Duple <string, Variable>("Output_of_" + d1.Name + "_" + globals[i].Name, savedc1Globals.Decls[i])); outputVars.Add(new Duple <string, Variable>("Output_of_" + d2.Name + "_" + globals[i].Name, globals[i])); } //new: we translate equalities as havoc lhs; lhs := lhs || x == x'; to enable diff counterexamples for each equality //havoc all lhs HavocCmd hcmd = new HavocCmd(Token.NoToken, outputEqualityState.Idents.ToList()); List <Expr> rhs = new List <Expr>(outputEqualityExprs.Map(i => i.Item1)); for (int i = 0; i < rhs.Count; ++i) { rhs[i] = Expr.Or(outputEqualityState.Idents[i], rhs[i]); } List <AssignLhs> lhs = new List <AssignLhs>(outputEqualityState.Idents.Map(x => new SimpleAssignLhs(Token.NoToken, x))); Cmd assgnCmd = new AssignCmd(Token.NoToken, lhs, rhs); /***** Save outputVars as globals (outputVarsForVFTask) *****/ //note that this list is order dependent. later code will assume that variables are paired SaveBlock leftRightOutputs = new SaveBlock(outputVars.Count, StateBlock.StateKind.Global); leftRightOutputs.Initialize(outputVars.Map(x => new Duple <string, Microsoft.Boogie.Type>(x.fst, x.snd.TypedIdent.Type))); Cmd[] saveOutputsIntoGlobals = leftRightOutputs.EmitSave(outputVars.Map(x => x.snd).ToArray()); outputVarsForVFTask = leftRightOutputs.Decls.ToList(); /***** Compile procedure body ****/ List <Cmd> body = new List <Cmd>(); foreach (Cmd c in prec1Copy) { body.Add(c); } body.Add(c1); foreach (Cmd c in postc1Copy) { body.Add(c); } foreach (Cmd c in postc1Restore) { body.Add(c); } foreach (Cmd c in prec2Copy) { body.Add(c); } body.Add(c2); foreach (Cmd c in saveOutputsIntoGlobals) { body.Add(c); } body.Add(hcmd); body.Add(assgnCmd); //special hack to limit outvar to {:stmtTaintCollectorGlobalVar} if (Options.refinedStmtTaint) { Options.OutputVars.Clear(); globals.Where(x => QKeyValue.FindBoolAttribute(x.Attributes, "stmtTaintCollectorGlobalVar")).Iter(x => Options.OutputVars.Add(x.ToString())); } List <Ensures> outputPostConditions = new List <Ensures>(); if (Options.splitOutputEqualities) { outputPostConditions.AddRange(outputEqualityState.Idents.Map(y => new Ensures(false, y))); System.Diagnostics.Debug.Assert(outputEqualityState.Count == outputEqualityExprs.Length); for (int i = 0; i < outputPostConditions.Count; ++i) { var name = outputEqualityExprs[i].Item2.Name; //check if name matches with at least one of the outputVars patterns if (Options.OutputVars.Count() > 0 && !Options.OutputVars.Any(x => name.Contains(x))) { outputPostConditions[i] = new Ensures(true, outputPostConditions[i].Condition); } outputPostConditions[i].Attributes = new QKeyValue(Token.NoToken, "EqVar", new List <object>() { name }, null); } } else if (!Options.EnumerateAllPaths) { outputPostConditions.Add(new Ensures(false, B.U.BigAnd(outputEqualityState.Idents))); } else //assert(false) causes all the paths to be enumerated { outputPostConditions.Add(new Ensures(false, Expr.False)); //to get exhaustive paths } var eqModifiesDupe = new List <IdentifierExpr>(d1.Modifies); eqModifiesDupe.AddRange(d2.Modifies); foreach (var v in leftRightOutputs.Decls) { eqModifiesDupe.Add(Expr.Ident(v)); } //uniqueify eqModifies var eqModifiesUn = new List <IdentifierExpr>(); var eqModifiesVars = new HashSet <Variable>(); var eqModifies = new List <IdentifierExpr>(); foreach (IdentifierExpr ie in eqModifiesDupe) { if (!eqModifiesVars.Contains(ie.Decl)) { eqModifies.Add(ie); } eqModifiesVars.Add(ie.Decl); } //var procName = "EQ_" + d1.Name + "__xx__" + d2.Name; var procName = mkEqProcName(d1.Name, d2.Name); Procedure eqProc = new Procedure(Token.NoToken, procName, B.C.empTypeVariableSeq, unionIns, new List <Variable>(outputEqualityState.Decls), B.C.empRequiresSeq, eqModifies, new List <Ensures>(outputPostConditions)); BigBlock bl = new BigBlock(Token.NoToken, "AA_INSTR_EQ_BODY", body, null, B.C.dmyTransferCmd); List <BigBlock> bll = new List <BigBlock>(); bll.Add(bl); List <Variable> locals = new List <Variable>(); foreach (Variable v in savedOutputs.Decls) { locals.Add(v); } foreach (Variable v in savedc1Globals.Decls) { locals.Add(v); } foreach (Variable v in savedInitialGlobals.Decls) { locals.Add(v); } locals.AddRange(unionOuts); Implementation eqImp = new Implementation(Token.NoToken, procName, B.C.empTypeVariableSeq, unionIns, new List <Variable>(outputEqualityState.Decls), locals, new StmtList(bll, Token.NoToken)); List <Declaration> l = new List <Declaration>(); return(new Duple <Procedure, Implementation>(eqProc, eqImp)); }
public override Cmd VisitHavocCmd(HavocCmd node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result <Cmd>() != null); return(base.VisitHavocCmd((HavocCmd)node.Clone())); }
private void MakeDual(List <Cmd> cs, Cmd c) { if (c is CallCmd) { CallCmd Call = c as CallCmd; if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "barrier_invariant")) { // There may be a predicate, and there must be an invariant expression and at least one instantiation Debug.Assert(Call.Ins.Count >= (2 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1))); var BIDescriptor = new UnaryBarrierInvariantDescriptor( verifier.uniformityAnalyser.IsUniform(Call.callee) ? Expr.True : Call.Ins[0], Expr.Neq(Call.Ins[verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1], verifier.Zero(1)), Call.Attributes, this, procName, verifier); for (var i = 1 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1); i < Call.Ins.Count; i++) { BIDescriptor.AddInstantiationExpr(Call.Ins[i]); } BarrierInvariantDescriptors.Add(BIDescriptor); return; } if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "binary_barrier_invariant")) { // There may be a predicate, and there must be an invariant expression and at least one pair of // instantiation expressions Debug.Assert(Call.Ins.Count >= (3 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1))); var BIDescriptor = new BinaryBarrierInvariantDescriptor( verifier.uniformityAnalyser.IsUniform(Call.callee) ? Expr.True : Call.Ins[0], Expr.Neq(Call.Ins[verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1], verifier.Zero(1)), Call.Attributes, this, procName, verifier); for (var i = 1 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1); i < Call.Ins.Count; i += 2) { BIDescriptor.AddInstantiationExprPair(Call.Ins[i], Call.Ins[i + 1]); } BarrierInvariantDescriptors.Add(BIDescriptor); return; } if (GPUVerifier.IsBarrier(Call.Proc)) { // Assert barrier invariants foreach (var BIDescriptor in BarrierInvariantDescriptors) { QKeyValue SourceLocationInfo = BIDescriptor.GetSourceLocationInfo(); cs.Add(BIDescriptor.GetAssertCmd()); var vd = new VariableDualiser(1, verifier.uniformityAnalyser, procName); if (GPUVerifyVCGenCommandLineOptions.BarrierAccessChecks) { foreach (Expr AccessExpr in BIDescriptor.GetAccessedExprs()) { var Assert = new AssertCmd(Token.NoToken, AccessExpr, MakeThreadSpecificAttributes(SourceLocationInfo, 1)); Assert.Attributes = new QKeyValue(Token.NoToken, "barrier_invariant_access_check", new List <object> { Expr.True }, Assert.Attributes); cs.Add(vd.VisitAssertCmd(Assert)); } } } } List <Expr> uniformNewIns = new List <Expr>(); List <Expr> nonUniformNewIns = new List <Expr>(); for (int i = 0; i < Call.Ins.Count; i++) { if (verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetInParameter(Call.callee, i))) { uniformNewIns.Add(Call.Ins[i]); } else if (!verifier.OnlyThread2.Contains(Call.callee)) { nonUniformNewIns.Add(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(Call.Ins[i])); } } for (int i = 0; i < Call.Ins.Count; i++) { if ( !(verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetInParameter(Call.callee, i))) && !verifier.OnlyThread1.Contains(Call.callee)) { nonUniformNewIns.Add(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(Call.Ins[i])); } } List <Expr> newIns = uniformNewIns; newIns.AddRange(nonUniformNewIns); List <IdentifierExpr> uniformNewOuts = new List <IdentifierExpr>(); List <IdentifierExpr> nonUniformNewOuts = new List <IdentifierExpr>(); for (int i = 0; i < Call.Outs.Count; i++) { if (verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetOutParameter(Call.callee, i))) { uniformNewOuts.Add(Call.Outs[i]); } else { nonUniformNewOuts.Add(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(Call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr); } } for (int i = 0; i < Call.Outs.Count; i++) { if (!(verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetOutParameter(Call.callee, i)))) { nonUniformNewOuts.Add(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(Call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr); } } List <IdentifierExpr> newOuts = uniformNewOuts; newOuts.AddRange(nonUniformNewOuts); CallCmd NewCallCmd = new CallCmd(Call.tok, Call.callee, newIns, newOuts); NewCallCmd.Proc = Call.Proc; NewCallCmd.Attributes = Call.Attributes; if (NewCallCmd.callee.StartsWith("_LOG_ATOMIC")) { QKeyValue curr = NewCallCmd.Attributes; if (curr.Key.StartsWith("arg")) { NewCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 1) }), curr.Next); } for (curr = NewCallCmd.Attributes; curr.Next != null; curr = curr.Next) { if (curr.Next.Key.StartsWith("arg")) { curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 1) }), curr.Next.Next); } } } else if (NewCallCmd.callee.StartsWith("_CHECK_ATOMIC")) { QKeyValue curr = NewCallCmd.Attributes; if (curr.Key.StartsWith("arg")) { NewCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 2) }), curr.Next); } for (curr = NewCallCmd.Attributes; curr.Next != null; curr = curr.Next) { if (curr.Next.Key.StartsWith("arg")) { curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 2) }), curr.Next.Next); } } } cs.Add(NewCallCmd); if (GPUVerifier.IsBarrier(Call.Proc)) { foreach (var BIDescriptor in BarrierInvariantDescriptors) { foreach (var Instantiation in BIDescriptor.GetInstantiationCmds()) { cs.Add(Instantiation); } } BarrierInvariantDescriptors.Clear(); } } else if (c is AssignCmd) { AssignCmd assign = c as AssignCmd; var vd1 = new VariableDualiser(1, verifier.uniformityAnalyser, procName); var vd2 = new VariableDualiser(2, verifier.uniformityAnalyser, procName); List <AssignLhs> lhss1 = new List <AssignLhs>(); List <AssignLhs> lhss2 = new List <AssignLhs>(); List <Expr> rhss1 = new List <Expr>(); List <Expr> rhss2 = new List <Expr>(); foreach (var pair in assign.Lhss.Zip(assign.Rhss)) { if (pair.Item1 is SimpleAssignLhs && verifier.uniformityAnalyser.IsUniform(procName, (pair.Item1 as SimpleAssignLhs).AssignedVariable.Name)) { lhss1.Add(pair.Item1); rhss1.Add(pair.Item2); } else { lhss1.Add(vd1.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs); lhss2.Add(vd2.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs); rhss1.Add(vd1.VisitExpr(pair.Item2.Clone() as Expr)); rhss2.Add(vd2.VisitExpr(pair.Item2.Clone() as Expr)); } } Debug.Assert(lhss1.Count > 0); cs.Add(new AssignCmd(Token.NoToken, lhss1, rhss1)); if (lhss2.Count > 0) { cs.Add(new AssignCmd(Token.NoToken, lhss2, rhss2)); } } else if (c is HavocCmd) { HavocCmd havoc = c as HavocCmd; Debug.Assert(havoc.Vars.Count() == 1); HavocCmd newHavoc; newHavoc = new HavocCmd(havoc.tok, new List <IdentifierExpr>(new IdentifierExpr[] { (IdentifierExpr)(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr)), (IdentifierExpr)(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr)) })); cs.Add(newHavoc); } else if (c is AssertCmd) { AssertCmd a = c as AssertCmd; if (QKeyValue.FindBoolAttribute(a.Attributes, "sourceloc") || QKeyValue.FindBoolAttribute(a.Attributes, "block_sourceloc") || QKeyValue.FindBoolAttribute(a.Attributes, "array_bounds")) { // This is just a location marker, so we do not dualise it cs.Add(new AssertCmd(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(a.Expr.Clone() as Expr), (QKeyValue)a.Attributes.Clone())); } else { var isUniform = verifier.uniformityAnalyser.IsUniform(procName, a.Expr); cs.Add(MakeThreadSpecificAssert(a, 1)); if (!GPUVerifyVCGenCommandLineOptions.AsymmetricAsserts && !ContainsAsymmetricExpression(a.Expr) && !isUniform) { cs.Add(MakeThreadSpecificAssert(a, 2)); } } } else if (c is AssumeCmd) { AssumeCmd ass = c as AssumeCmd; if (QKeyValue.FindStringAttribute(ass.Attributes, "captureState") != null) { cs.Add(c); } else if (QKeyValue.FindBoolAttribute(ass.Attributes, "backedge")) { AssumeCmd newAss = new AssumeCmd(c.tok, Expr.Or(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr), new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr))); newAss.Attributes = ass.Attributes; cs.Add(newAss); } else if (QKeyValue.FindBoolAttribute(ass.Attributes, "atomic_refinement")) { // Generate the following: // havoc v$1, v$2; // assume !_USED[offset$1][v$1]; // _USED[offset$1][v$1] := true; // assume !_USED[offset$2][v$2]; // _USED[offset$2][v$2] := true; Expr variable = QKeyValue.FindExprAttribute(ass.Attributes, "variable"); Expr offset = QKeyValue.FindExprAttribute(ass.Attributes, "offset"); List <Expr> offsets = (new int[] { 1, 2 }).Select(x => new VariableDualiser(x, verifier.uniformityAnalyser, procName).VisitExpr(offset.Clone() as Expr)).ToList(); List <Expr> vars = (new int[] { 1, 2 }).Select(x => new VariableDualiser(x, verifier.uniformityAnalyser, procName).VisitExpr(variable.Clone() as Expr)).ToList(); IdentifierExpr arrayref = new IdentifierExpr(Token.NoToken, verifier.FindOrCreateUsedMap(QKeyValue.FindStringAttribute(ass.Attributes, "arrayref"), vars[0].Type)); foreach (int i in (new int[] { 0, 1 })) { AssumeCmd newAss = new AssumeCmd(c.tok, Expr.Not(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { arrayref, offsets[i] }), vars[i] }))); cs.Add(newAss); var lhs = new MapAssignLhs(Token.NoToken, new MapAssignLhs(Token.NoToken, new SimpleAssignLhs(Token.NoToken, arrayref), new List <Expr> { offsets[i] }), new List <Expr> { vars[i] }); AssignCmd assign = new AssignCmd(c.tok, new List <AssignLhs> { lhs }, new List <Expr> { Expr.True }); cs.Add(assign); } } else { var isUniform = verifier.uniformityAnalyser.IsUniform(procName, ass.Expr); AssumeCmd newAss = new AssumeCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)); if (!ContainsAsymmetricExpression(ass.Expr) && !isUniform) { newAss.Expr = Expr.And(newAss.Expr, new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)); } newAss.Attributes = ass.Attributes; cs.Add(newAss); } } else { Debug.Assert(false); } }
//not implemented cmds public override Cmd VisitHavocCmd(HavocCmd node) { //handled elsewhere, since havoc of multiple variables is desugared into multiple basic havoc commands throw new NotImplementedException(); }