private AssignCmd VisitMapAssignment(AssignLhs lhs, Expr rhs) { Debug.Assert(lhs.DeepAssignedVariable.TypedIdent.Type.IsMap); var ac = new AssignCmd(Token.NoToken, new List <AssignLhs>() { lhs }, new List <Expr>() { rhs }); if (lhs.Type.IsMap) { ac = VisitEntireMapAssignment(lhs, rhs); return(ac); } var index = (lhs.AsExpr as NAryExpr).Args[1]; var l = VisitMapStore(lhs.DeepAssignedIdentifier, index, rhs); if (l != null) { ac = new AssignCmd(Token.NoToken, new List <AssignLhs>(), new List <Expr>()); //overwrite //to generate M'[x] := y ac.Lhss = l .Select(x => new MapAssignLhs(Token.NoToken, new SimpleAssignLhs(Token.NoToken, x.Item1), new List <Expr>() { index })) .ToList <AssignLhs>(); ac.Rhss = l .Select(x => x.Item2) .ToList(); } return(ac); }
/// <summary> /// M := E /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <returns></returns> private AssignCmd VisitEntireMapAssignment(AssignLhs lhs, Expr rhs) { Debug.Assert(lhs.DeepAssignedVariable.TypedIdent.Type.IsMap); var ac = new AssignCmd(Token.NoToken, new List <AssignLhs>() { lhs }, new List <Expr>() { rhs }); //M := old(M) if (! (rhs is OldExpr && ((OldExpr)rhs).Expr is IdentifierExpr && ((IdentifierExpr)((OldExpr)rhs).Expr).Decl == lhs.DeepAssignedVariable) ) { Console.WriteLine("Don't handle direct stores M := e yet, found {0}", ac.ToString()); unhandledCommands.Add(ac); return(ac); } var splitVars = allAllocSites .Select(x => GetOrCreateSplitMap(lhs.DeepAssignedVariable, x)) .ToList(); ac.Lhss = splitVars.Select(x => (AssignLhs) new SimpleAssignLhs(Token.NoToken, IdentifierExpr.Ident(x))).ToList(); ac.Rhss = splitVars.Select(x => (Expr) new OldExpr(Token.NoToken, (Expr)IdentifierExpr.Ident(x))).ToList(); return(ac); }
public static Expr SelectOfAssignLhs(AssignLhs lhs) { if (lhs is MapAssignLhs) { return(Expr.Select(SelectOfAssignLhs(((MapAssignLhs)lhs).Map), ((MapAssignLhs)lhs).Indexes)); } else { return(Expr.Ident(lhs.DeepAssignedVariable)); } }
public override Block VisitBlock(Block node) { foreach (Cmd c in node.Cmds) { AssignCmd ac = c as AssignCmd; if (ac == null) { continue; } Utils.Assert(ac.Lhss.Count == 1 && ac.Rhss.Count == 1, "Expected assignments to have 1 lhs and 1 rhs"); AssignLhs lhs = ac.Lhss.ElementAt(0); Expr rhs = ac.Rhss.ElementAt(0); if (!(lhs.Type.IsBv && lhs.DeepAssignedIdentifier.Name.Equals("RSP"))) { continue; } //lhs is RSP if (!(rhs is NAryExpr)) { continue; } //rhs is function application if (!((NAryExpr)rhs).Fun.FunctionName.Equals("MINUS_64")) { continue; } //rhs is a minus operation if (!(((NAryExpr)rhs).Args.ElementAt(0) is IdentifierExpr)) { continue; } //1st argument is a id like RHS if (!(((NAryExpr)rhs).Args.ElementAt(0) as IdentifierExpr).Name.Equals("RSP")) { continue; } //1st argument is a id like RHS if (!(((NAryExpr)rhs).Args.ElementAt(1) is LiteralExpr)) { continue; } //2nd argument is a constant like 384bv64 if (!((((NAryExpr)rhs).Args.ElementAt(1) as LiteralExpr).Type == BType.GetBvType(64))) { continue; } //2nd argument is bitvector literal int operand = ((((NAryExpr)rhs).Args.ElementAt(1) as LiteralExpr).asBvConst).Value.ToInt; Utils.Assert(blocksWithinNautralLoops.All(x => x.Label != node.Label), "Setting RSP within a loop: " + ac + " at label " + node.Label); rsp_subtractions.Add(operand); } return(base.VisitBlock(node)); }
/* returns (mem, rcx, rdi, al) */ public static Tuple <Variable, Expr, Expr, Expr> getRepStosbArgs(AssignCmd c) { Utils.Assert(getSlashVerifyCmdType(c) == SlashVerifyCmdType.RepStosB, "getRepStosbArgs not a RepStosb command"); Utils.Assert(c.Lhss.Count == 1 && c.Rhss.Count == 1, "getRepStosbArgs not handling parallel assignCmds"); AssignLhs lhs = c.Lhss[0]; Expr rhs = c.Rhss[0]; Utils.Assert(((NAryExpr)rhs).Args.Count == 4, "RepStosb must have 4 arguments"); return(Tuple.Create <Variable, Expr, Expr, Expr>((((NAryExpr)rhs).Args[0] as IdentifierExpr).Decl, ((NAryExpr)rhs).Args[1], ((NAryExpr)rhs).Args[2], ((NAryExpr)rhs).Args[3])); }
//////////////////////////////////////////////////////////////////////////////////// internal ReferenceExpression makeReferenceExpression(AssignLhs assignLhs) { if (assignLhs is SimpleAssignLhs) { return(makeReferenceExpression((SimpleAssignLhs)assignLhs)); } else if (assignLhs is MapAssignLhs) { return(makeReferenceExpression((MapAssignLhs)assignLhs)); } else { throw new Exception("Unsupported Boogie LHS type:" + assignLhs.ToString()); } }
///////////////////////////////////////////////////////////////////////////////////// private Expression getAssignmentSourceExpression(AssignLhs target, Expression source) { if (target is SimpleAssignLhs) { return(getAssignmentSourceExpression((SimpleAssignLhs)target, source)); } else if (target is MapAssignLhs) { return(getAssignmentSourceExpression((MapAssignLhs)target, source)); } else { throw new NotImplementedException(); } }
public override Cmd VisitAssignCmd(AssignCmd node) { HashSet<Variable> rhsVars = new HashSet<Variable>(); for (int i = 0; i < node.Lhss.Count; i++) { AssignLhs lhs = node.Lhss[i]; Variable lhsVar = lhs.DeepAssignedVariable; string domainName = FindDomainName(lhsVar); if (domainName == null) continue; if (!(lhs is SimpleAssignLhs)) { Error(node, $"Only simple assignment allowed on linear variable {lhsVar.Name}"); continue; } IdentifierExpr rhs = node.Rhss[i] as IdentifierExpr; if (rhs == null) { Error(node, $"Only variable can be assigned to linear variable {lhsVar.Name}"); continue; } string rhsDomainName = FindDomainName(rhs.Decl); if (rhsDomainName == null) { Error(node, $"Only linear variable can be assigned to linear variable {lhsVar.Name}"); continue; } if (domainName != rhsDomainName) { Error(node, $"Linear variable of domain {rhsDomainName} cannot be assigned to linear variable of domain {domainName}"); continue; } if (rhsVars.Contains(rhs.Decl)) { Error(node, $"Linear variable {rhs.Decl.Name} can occur only once in the right-hand-side of an assignment"); continue; } rhsVars.Add(rhs.Decl); } return base.VisitAssignCmd(node); }
// Return the variable that is being assigned to in the LHS of an assignment. // id := ... then id // m[...] := ... then m private static IdentifierExpr getAssignedVariable(AssignLhs lhs) { if (lhs is SimpleAssignLhs) { SimpleAssignLhs sl = (SimpleAssignLhs)lhs; return(sl.AssignedVariable); } else if (lhs is MapAssignLhs) { MapAssignLhs ml = (MapAssignLhs)lhs; return(getAssignedVariable(ml.Map)); } else { lhs.Emit(new TokenTextWriter(Console.Out)); throw new InternalError("Unknown type of AssignLhs"); } }
/* returns (mem, addr, data) */ public static Tuple <Variable, Expr, Expr> getStoreArgs(AssignCmd c) { Func <Expr, string, bool> RhsMatch = delegate(Expr x, String s) { return(x is NAryExpr && ((NAryExpr)x).Fun.FunctionName.Equals(s)); }; Utils.Assert(c.Lhss.Count == 1 && c.Rhss.Count == 1, "getStoreArgs not handling parallel assignCmds"); AssignLhs lhs = c.Lhss[0]; Expr rhs = c.Rhss[0]; Utils.Assert(RhsMatch(rhs, "STORE_LE_8") || RhsMatch(rhs, "STORE_LE_16") || RhsMatch(rhs, "STORE_LE_32") || RhsMatch(rhs, "STORE_LE_64"), "Expected store expression"); Utils.Assert(((NAryExpr)rhs).Args.Count == 3, "Store must have 3 arguments"); return(Tuple.Create <Variable, Expr, Expr>((((NAryExpr)rhs).Args[0] as IdentifierExpr).Decl, ((NAryExpr)rhs).Args[1], ((NAryExpr)rhs).Args[2])); }
public static Duple <StoreLhs, Expr> Make(AssignLhs alhs, Expr e) { if (alhs is SimpleAssignLhs) { return(new Duple <StoreLhs, Expr>(new StoreLhs(alhs.DeepAssignedVariable), e)); } if (alhs is MapAssignLhs) { var mlhs = alhs as MapAssignLhs; var var = mlhs.DeepAssignedVariable; var curLhs = mlhs.Map; var curExpr = Expr.Store(SelectOfAssignLhs(curLhs), mlhs.Indexes, e); if (curLhs is MapAssignLhs) { return(Make(curLhs, curExpr)); } return(new Duple <StoreLhs, Expr>(new StoreLhs(var), curExpr)); } return(null); //impossible! }
///////////////// // here begin the visit overrides that are only necessary for the cloning, and have nothing to do with the substitution itself // --> one might move them to a clone visitor.. ///////////////// public override AssignLhs VisitMapAssignLhs(MapAssignLhs node) { var dispatchedIndices = new List <Expr>(); foreach (var ind in node.Indexes) { dispatchedIndices.Add(VisitExpr(ind)); } AssignLhs newAssignLhs = null; if (node.Map is MapAssignLhs) { newAssignLhs = VisitMapAssignLhs(node.Map as MapAssignLhs); } else if (node.Map is SimpleAssignLhs) { newAssignLhs = VisitSimpleAssignLhs(node.Map as SimpleAssignLhs); } return(new MapAssignLhs(node.tok, newAssignLhs, dispatchedIndices)); }
private AssignLhs TransformLhs(AssignLhs lhs) { var mapLhs = lhs as MapAssignLhs; if (mapLhs == null || !(mapLhs.Map is SimpleAssignLhs) || mapLhs.Indexes.Count() != 1) { return((AssignLhs)Visit(lhs)); } var map = (mapLhs.Map as SimpleAssignLhs).AssignedVariable; if (!Arrays.ContainsKey(map.Name)) { return((AssignLhs)Visit(lhs)); } Debug.Assert(mapLhs.Indexes[0] is LiteralExpr); return(new SimpleAssignLhs( lhs.tok, new IdentifierExpr(Token.NoToken, Eliminator.MakeVariableForArrayIndex(map.Decl, mapLhs.Indexes[0].ToString())))); }
private Block Abstract(Block b) { var newCmds = new List <Cmd>(); foreach (Cmd c in b.Cmds) { if (c is CallCmd) { var call = c as CallCmd; if (QKeyValue.FindBoolAttribute(call.Attributes, "atomic")) { // Discard the call Debug.Assert(call.Ins.Count >= 1); var ie = call.Ins[0] as IdentifierExpr; Debug.Assert(ie != null); Debug.Assert(verifier.ArrayModelledAdversarially(ie.Decl)); continue; } for (int i = 0; i < call.Ins.Count; i++) { ReadCollector rc = new ReadCollector(verifier.KernelArrayInfo); rc.Visit(call.Ins[i]); bool foundAdversarial = false; foreach (AccessRecord ar in rc.NonPrivateAccesses) { if (verifier.ArrayModelledAdversarially(ar.V)) { foundAdversarial = true; break; } } if (foundAdversarial) { LocalVariable lv = new LocalVariable( Token.NoToken, new TypedIdent(Token.NoToken, "_abstracted_call_arg_" + abstractedCallArgCounter, call.Ins[i].Type)); abstractedCallArgCounter++; newLocalVars.Add(lv); newCmds.Add(new HavocCmd( Token.NoToken, new List <IdentifierExpr>(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, lv) }))); call.Ins[i] = new IdentifierExpr(Token.NoToken, lv); } } } if (c is AssignCmd) { AssignCmd assign = c as AssignCmd; var lhss = new List <AssignLhs>(); var rhss = new List <Expr>(); foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss)) { AssignLhs lhs = lhsRhs.Item1; Expr rhs = lhsRhs.Item2; ReadCollector rc = new ReadCollector(verifier.KernelArrayInfo); rc.Visit(rhs); bool foundAdversarial = false; foreach (AccessRecord ar in rc.NonPrivateAccesses) { if (verifier.ArrayModelledAdversarially(ar.V)) { foundAdversarial = true; break; } } if (foundAdversarial) { Debug.Assert(lhs is SimpleAssignLhs); newCmds.Add(new HavocCmd(c.tok, new List <IdentifierExpr>(new IdentifierExpr[] { (lhs as SimpleAssignLhs).AssignedVariable }))); continue; } WriteCollector wc = new WriteCollector(verifier.KernelArrayInfo); wc.Visit(lhs); if (wc.FoundNonPrivateWrite()) { if (verifier.ArrayModelledAdversarially(wc.GetAccess().V)) { continue; // Just remove the write } } lhss.Add(lhs); rhss.Add(rhs); } if (lhss.Count != 0) { newCmds.Add(new AssignCmd(assign.tok, lhss, rhss)); } continue; } newCmds.Add(c); } b.Cmds = newCmds; return(b); }
///////////////////////////////////////////////////////////////////////////////////// private ProgramVariable getAssignmentTarget(BasicBlock current, AssignLhs target) { return(scope.findVariable(scope.getVarUName(target.DeepAssignedVariable))); }
private List <Cmd> AbstractAssign(AssignCmd acmd) { var newcmd = new List <Cmd>(); // !KeepSimple: then map indices are given special treatment var KeepSimple = UseSimpleSlicing || (currImplementation == null) || (acmd.Lhss.Count != 1); if (acmd.Lhss.Count != 1) { EncounteredParallelAssignment = true; } var newLhss = new List <AssignLhs>(); var newRhss = new List <Expr>(); var varsToHavoc = new HashSet <Variable>(); for (int i = 0; i < acmd.Lhss.Count; i++) { AssignLhs lhs = acmd.Lhss[i]; Expr rhs = acmd.Rhss[i]; //IdentifierExpr assignedVar = getAssignedVariable(lhs); IdentifierExpr assignedVar = lhs.DeepAssignedIdentifier; if (isTrackedVariable(assignedVar.Decl)) { if (lhs is MapAssignLhs && !indicesAreTracked((MapAssignLhs)lhs)) { // convert to assignedVar := * varsToHavoc.Add(assignedVar.Decl); } else if (!isTracked(rhs)) { // Convert to lhs := * if (KeepSimple || lhs is SimpleAssignLhs) { varsToHavoc.Add(assignedVar.Decl); } else { // convert to "havoc lhs" as follows: // havoc dummy; lhs := dummy; // This is done when lhs is Mem[x]. We're not // allowed to say "havoc Mem[x]". // We should be doing this only when we can add new // local variables Debug.Assert(currImplementation != null); // Get new local variable dummy LocalVariable dummy = getNewLocal(lhs.Type, currImplementation); // havoc dummy newcmd.Add(BoogieAstFactory.MkHavocVar(dummy)); // lhs := dummy newLhss.Add(lhs); newRhss.Add(Expr.Ident(dummy)); } } else { // It is possible to come here because a variable may be untracked in this scope, // yet tracked globally because it is on the lhs newLhss.Add(lhs); newRhss.Add(rhs); } } } if (newLhss.Count != 0) { newcmd.Add(new AssignCmd(Token.NoToken, newLhss, newRhss)); } if (varsToHavoc.Count != 0) { var ieseq = new List <IdentifierExpr>(); varsToHavoc.Iter(v => ieseq.Add(Expr.Ident(v))); newcmd.Add(new HavocCmd(Token.NoToken, ieseq)); } return(newcmd); }
/* looks at the function used in the NAryExpr to determine the type: LOAD8, LOAD16,...,STORE64 */ public static SlashVerifyCmdType getSlashVerifyCmdType(Cmd c) { Func <Expr, string, bool> RhsMatch = delegate(Expr x, String s) { return(x is NAryExpr && ((NAryExpr)x).Fun.FunctionName.Equals(s)); }; if (c is AssignCmd) { AssignCmd ac = c as AssignCmd; Utils.Assert(ac.Lhss.Count == 1 && ac.Rhss.Count == 1, "getSlashVerifyCmdType not handling parallel assignCmds"); AssignLhs lhs = ac.Lhss[0]; Expr rhs = ac.Rhss[0]; if (lhs.Type.IsMap && RhsMatch(rhs, "STORE_LE_8")) { return(SlashVerifyCmdType.Store8); } else if (lhs.Type.IsMap && RhsMatch(rhs, "STORE_LE_16")) { return(SlashVerifyCmdType.Store16); } else if (lhs.Type.IsMap && RhsMatch(rhs, "STORE_LE_32")) { return(SlashVerifyCmdType.Store32); } else if (lhs.Type.IsMap && RhsMatch(rhs, "STORE_LE_64")) { return(SlashVerifyCmdType.Store64); } else if (lhs.Type.IsMap && RhsMatch(rhs, "REP_STOSB")) { return(SlashVerifyCmdType.RepStosB); } else if (lhs.Type.IsBv && lhs.DeepAssignedIdentifier.Name.Equals("RSP")) { return(SlashVerifyCmdType.SetRSP); } } else if (c is AssertCmd) { AssertCmd ac = c as AssertCmd; //extract instruction type string attribute_cmdtype = QKeyValue.FindStringAttribute(ac.Attributes, "SlashVerifyCommandType"); string attribute_jmptarget = QKeyValue.FindStringAttribute(ac.Attributes, "SlashVerifyJmpTarget"); if (attribute_cmdtype != null && attribute_cmdtype.Equals("ret")) { return(SlashVerifyCmdType.Ret); } else if (attribute_cmdtype != null && attribute_cmdtype.Equals("call")) { return(SlashVerifyCmdType.Call); } else if (attribute_cmdtype != null && attribute_jmptarget != null && attribute_cmdtype.Equals("remotejmp")) { return(SlashVerifyCmdType.RemoteJmp); } else if (attribute_cmdtype != null && attribute_jmptarget != null && attribute_cmdtype.Equals("indirectjmp") && attribute_jmptarget.Equals("remote")) { return(SlashVerifyCmdType.RemoteIndirectJmp); } } return(SlashVerifyCmdType.None); }