public override Expr VisitNAryExpr(NAryExpr node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Expr>() != null); CheckTypeParams(node, cce.NonNull(node.TypeParameters)); return base.VisitNAryExpr(node); }
public void FunctionCall() { var fc = CreateFunctionCall("bv8slt", Microsoft.Boogie.Type.Bool, new List<Microsoft.Boogie.Type>() { BasicType.GetBvType(8), BasicType.GetBvType(8) }); var constantBv = new LiteralExpr(Token.NoToken, BigNum.FromInt(0) , 8); var nary = new NAryExpr(Token.NoToken,fc, new List<Expr>() { constantBv, constantBv} ); // Get shallow type (this was broken when this test was written) Assert.AreEqual(BasicType.Bool, nary.ShallowType); // Deep type check (this was not broken before writing this test) Assert.IsNull(nary.Type); var tc = new TypecheckingContext(this); nary.Typecheck(tc); Assert.AreEqual(BasicType.Bool, nary.Type); }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is BinaryOperator) { var op = (BinaryOperator)node.Fun; Contract.Assert(node.Args.Count == 2); var arg0 = node.Args[0]; var arg1 = node.Args[1]; var offset = arg0.Type.IsReal ? 0 : 1; BigInteger? k; switch (op.Op) { case BinaryOperator.Opcode.Eq: case BinaryOperator.Opcode.Neq: k = AsIntLiteral(arg0); if (k != null) { var i = (BigInteger)k; downs.Add(i - 1); downs.Add(i); ups.Add(i + 1); ups.Add(i + 2); } k = AsIntLiteral(arg1); if (k != null) { var i = (BigInteger)k; downs.Add(i - 1); downs.Add(i); ups.Add(i + 1); ups.Add(i + 2); } break; case BinaryOperator.Opcode.Le: k = AsIntLiteral(arg0); if (k != null) { var i = (BigInteger)k; downs.Add(i - 1); downs.Add(i); } k = AsIntLiteral(arg1); if (k != null) { var i = (BigInteger)k; ups.Add(i + offset); ups.Add(i + 1 + offset); } break; case BinaryOperator.Opcode.Lt: k = AsIntLiteral(arg0); if (k != null) { var i = (BigInteger)k; downs.Add(i ); downs.Add(i + 1); } k = AsIntLiteral(arg1); if (k != null) { var i = (BigInteger)k; ups.Add(i - 1 + offset); ups.Add(i + offset); } break; case BinaryOperator.Opcode.Ge: { var tmp = arg0; arg0 = arg1; arg1 = tmp; } goto case BinaryOperator.Opcode.Le; case BinaryOperator.Opcode.Gt: { var tmp = arg0; arg0 = arg1; arg1 = tmp; } goto case BinaryOperator.Opcode.Lt; default: break; } } return base.VisitNAryExpr(node); }
private NAryExpr GetUnTypedImmutableNAry() { var id = new IdentifierExpr(Token.NoToken, "foo", BasicType.Bool, /*immutable=*/true); Assert.IsTrue(id.Immutable); Assert.IsTrue(id.Type.IsBool); var e = new NAryExpr(Token.NoToken, new BinaryOperator(Token.NoToken, BinaryOperator.Opcode.And), new List<Expr>() { id, id }, /*immutable=*/true); Assert.IsNull(e.Type); Assert.IsTrue(e.Immutable); return e; }
public override Expr VisitNAryExpr(NAryExpr node) { node.Args = node.Args.Select(arg => VisitExpr(arg)).ToList(); return(node); }
public override Expr VisitNAryExpr(NAryExpr node) { if (currentTrigger != null) { // We found a function call within a trigger of a quantifier expression. var funCall = node.Fun as FunctionCall; if (funCall != null && funCall.Func != null && funCall.Func.Checksum != null && funCall.Func.Checksum != "stable") { funCall.Func.AddOtherDefinitionAxiom(currentAxiom); } } return base.VisitNAryExpr(node); }
private Expr SubsetExprs(LinearDomain domain, HashSet<Variable> scope, Variable partition, int count, Expr expr) { foreach (Variable v in scope) { if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue; Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) }); expr = Expr.And(SubsetExpr(domain, ie, partition, count), expr); count++; } expr = new ExistsExpr(Token.NoToken, new List<Variable> { partition }, expr); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); return expr; }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is FunctionCall) { var collector = new VariableCollector(); collector.Visit(node); functionsUsed.Add((node.Fun as FunctionCall).Func); } return base.VisitNAryExpr(node); }
public virtual Expr VisitNAryExpr(NAryExpr node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<Expr>() != null); node.Args = this.VisitExprSeq(node.Args); return node; }
public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { List <Cmd> newCmdSeq = new List <Cmd>(); foreach (Cmd c in cmdSeq) { //Do special stuff for those whose BAP modeling is broken if (c is AssertCmd) //call and return instructions are marked with attributes { AssertCmd ac = c as AssertCmd; string attribute_cmdtype = QKeyValue.FindStringAttribute(ac.Attributes, "SlashVerifyCommandType"); if (attribute_cmdtype != null && attribute_cmdtype.Equals("btc_rax_1d")) { //BAP has a bug with this. Model it explicitly ourselves. //CF := RAX[30:29]; newCmdSeq.Add(new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.CF)) }, new List <Expr>() { new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX), 30, 29) } )); //RAX := RAX[64:30] ++ NOT(RAX[30:29]) ++ RAX[29:0]; Expr e1 = new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX), 64, 30); Expr e2 = new NAryExpr(Token.NoToken, new FunctionCall(this.not_1), new List <Expr>() { new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX), 30, 29) }); Expr e3 = new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX), 29, 0); newCmdSeq.Add(new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX)) }, new List <Expr>() { new BvConcatExpr(Token.NoToken, new BvConcatExpr(Token.NoToken, e1, e2), e3) } )); } else if (attribute_cmdtype != null && attribute_cmdtype.Equals("rep_stosb")) { //BAP does not model this either. Model rep stosb as sequence: mem := repstosb(mem, rcx, rdi, al); rdi := rdi + rcx; rcx := 0; //forall i. rdi <= i < rdi + rcx ==> new_mem[i] == al; newCmdSeq.Add(new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem)) }, new List <Expr>() { new NAryExpr(Token.NoToken, new FunctionCall(rep_stosb), new List <Expr>() { new IdentifierExpr(Token.NoToken, this.mem), new IdentifierExpr(Token.NoToken, this.RCX), new IdentifierExpr(Token.NoToken, this.RDI), new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RAX), 8, 0) }) } )); //RDI := RDI + RCX; newCmdSeq.Add(new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RDI)) }, new List <Expr>() { new NAryExpr(Token.NoToken, new FunctionCall(this.plus_64), new List <Expr>() { new IdentifierExpr(Token.NoToken, this.RDI), new IdentifierExpr(Token.NoToken, this.RCX) }) } )); //RCX := 0; newCmdSeq.Add(new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.RCX)) }, new List <Expr>() { new LiteralExpr(Token.NoToken, BigNum.ZERO, 64) })); } } //The assert gets placed prior to the original command newCmdSeq.Add(c); } return(base.VisitCmdSeq(newCmdSeq)); }
public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { List <Cmd> newCmdSeq = new List <Cmd>(); foreach (Cmd c in cmdSeq) { if (c is AssignCmd) { AssignCmd ac = c as AssignCmd; Utils.Assert(ac.Lhss.Count == 1 && ac.Rhss.Count == 1, "Not handling parallel AssignCmd"); List <Tuple <Expr, Expr> > loadAddresses = getNestedLoadAddresses(ac.Rhss[0]); Utils.Assert(loadAddresses.Select(x => x.ToString()).Distinct().Count() < 2, "Found multiple load expressions in " + ac.Rhss[0].ToString()); Tuple <Expr, Expr> load_addr = loadAddresses.Any() ? loadAddresses[0] : null; if (load_addr != null) { Action <NAryExpr, string> RecordAssertion = delegate(NAryExpr assertCondition, string attribute) { AssertCmd assertion = new AssertCmd(Token.NoToken, assertCondition); assertion.Attributes = new QKeyValue(Token.NoToken, "region", new List <object> { attribute }, assertion.Attributes); newCmdSeq.Add(assertion); VCSplitter.Instance.RecordAssertion(this.current_label, ac, assertion, Utils.getSlashVerifyCmdType(ac)); }; Action RecordStackAssertions = delegate() { NAryExpr condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { load_addr.Item2 }); RecordAssertion(condition, "addrInStack"); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { load_addr.Item2 }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInStack"); }; Action RecordBitmapAssertions = delegate() { NAryExpr condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { load_addr.Item2 }); RecordAssertion(condition, "addrInBitmap"); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { load_addr.Item2 }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInBitmap"); }; if (!this.splitProgram) { RecordStackAssertions(); RecordBitmapAssertions(); } else { if (load_addr.Item1 is NAryExpr) { List <IdentifierExpr> referencedMemSpaces = Utils.getSplitMemoryAccessSpace(load_addr.Item1 as NAryExpr); foreach (Variable memSpace in referencedMemSpaces.Select(i => i.Decl)) { if (memSpace.Name.Equals("mem_bitmap")) { RecordBitmapAssertions(); } else if (memSpace.Name.Equals("mem_stack")) { RecordStackAssertions(); } } } } } } //The assert gets placed prior to the original command newCmdSeq.Add(c); } return(base.VisitCmdSeq(newCmdSeq)); }
public override Expr VisitLambdaExpr(LambdaExpr lambda) { var baseResult = base.VisitLambdaExpr(lambda); lambda = baseResult as LambdaExpr; if (lambda == null) { return baseResult; // apparently, the base visitor already turned the lambda into something else } // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "stable" }, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type/*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs)); fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
public override Expr VisitNAryExpr(NAryExpr node) { // Need to duplicate arguments first (doing post order traversal) var newArgs = new List <Expr>(); foreach (var oldExpr in node.Args) { var newExpr = (Expr)this.Visit(oldExpr); newArgs.Add(newExpr); } // Now can finally duplicate this node now we've done our children if (node.Fun is FunctionCall) { var FC = (FunctionCall)node.Fun; string bvbuiltin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "bvbuiltin"); if (bvbuiltin != null) { return(HandleBvBuiltIns(FC, bvbuiltin, newArgs)); } else { string builtin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "builtin"); if (builtin != null) { return(HandleBuiltIns(FC, builtin, newArgs)); } } // Not a builtin so treat as uninterpreted function call return(Builder.UFC(FC, newArgs.ToArray())); } else if (node.Fun is UnaryOperator) { var U = (UnaryOperator)node.Fun; Debug.Assert(newArgs.Count == 1); switch (U.Op) { case UnaryOperator.Opcode.Neg: return(Builder.Neg(newArgs[0])); case UnaryOperator.Opcode.Not: return(Builder.Not(newArgs[0])); default: throw new NotImplementedException("Unary operator not supported"); } } else if (node.Fun is BinaryOperator) { var B = (BinaryOperator)node.Fun; Debug.Assert(newArgs.Count == 2); switch (B.Op) { // Integer or Real number operators case BinaryOperator.Opcode.Add: return(Builder.Add(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Sub: return(Builder.Sub(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Mul: return(Builder.Mul(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Div: return(Builder.Div(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Mod: return(Builder.Mod(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.RealDiv: return(Builder.RealDiv(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Pow: return(Builder.Pow(newArgs[0], newArgs[1])); // Comparision operators case BinaryOperator.Opcode.Eq: return(Builder.Eq(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Neq: return(Builder.NotEq(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Gt: return(Builder.Gt(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Ge: return(Builder.Ge(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Lt: return(Builder.Lt(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Le: return(Builder.Le(newArgs[0], newArgs[1])); // Bool operators case BinaryOperator.Opcode.And: return(Builder.And(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Or: return(Builder.Or(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Imp: return(Builder.Imp(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Iff: return(Builder.Iff(newArgs[0], newArgs[1])); case BinaryOperator.Opcode.Subtype: throw new NotImplementedException("SubType binary operator support not implemented"); default: throw new NotSupportedException("Binary operator" + B.Op.ToString() + "not supported!"); } } else if (node.Fun is MapStore) { Debug.Assert(newArgs.Count >= 3); // FIXME: We're probably making too many lists/arrays here var map = newArgs[0]; var value = newArgs[newArgs.Count - 1]; // Last argument is value to store var indices = new List <Expr>(); for (int index = 1; index < newArgs.Count - 1; ++index) { indices.Add(newArgs[index]); } Debug.Assert(indices.Count + 2 == newArgs.Count); return(Builder.MapStore(map, value, indices.ToArray())); } else if (node.Fun is MapSelect) { // FIXME: We're probably making too many lists/arrays here Debug.Assert(newArgs.Count >= 2); var map = newArgs[0]; var indices = new List <Expr>(); for (int index = 1; index < newArgs.Count; ++index) { indices.Add(newArgs[index]); } Debug.Assert(indices.Count + 1 == newArgs.Count); return(Builder.MapSelect(map, indices.ToArray())); } else if (node.Fun is IfThenElse) { Debug.Assert(newArgs.Count == 3); return(Builder.IfThenElse(newArgs[0], newArgs[1], newArgs[2])); } else if (node.Fun is TypeCoercion) { // FIXME: Add support for this in the builder // I don't want to put this into the IExprBuilder until I know // exactly how this operator works and how it should be type checked var immutableTC = new NAryExpr(Token.NoToken, node.Fun, newArgs, /*immutable=*/ true); immutableTC.Type = node.Type; return(immutableTC); } else if (node.Fun is ArithmeticCoercion) { Debug.Assert(newArgs.Count == 1); var ac = node.Fun as ArithmeticCoercion; return(Builder.ArithmeticCoercion(ac.Coercion, newArgs[0])); } throw new NotSupportedException("Unsupported NAryExpr"); }
protected Expr HandleNAry(NAryExpr e) { if (e.Fun is FunctionCall) { var FC = (FunctionCall)e.Fun; string bvbuiltin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "bvbuiltin"); if (bvbuiltin != null) { return(HandlerBvBuiltIns(e, bvbuiltin)); } else { string builtin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "builtin"); if (builtin != null) { return(HandlerBuiltIns(e, builtin)); } // Not a bvbuiltin so treat as generic function call. return(Visitor.VisitFunctionCall(e)); } } else if (e.Fun is UnaryOperator) { var U = (UnaryOperator)e.Fun; switch (U.Op) { case UnaryOperator.Opcode.Neg: return(Visitor.VisitNeg(e)); case UnaryOperator.Opcode.Not: return(Visitor.VisitNot(e)); default: throw new NotImplementedException("Unary operator not supported"); } } else if (e.Fun is BinaryOperator) { var B = (BinaryOperator)e.Fun; switch (B.Op) { // Integer or Real number operators case BinaryOperator.Opcode.Add: return(Visitor.VisitAdd(e)); case BinaryOperator.Opcode.Sub: return(Visitor.VisitSub(e)); case BinaryOperator.Opcode.Mul: return(Visitor.VisitMul(e)); case BinaryOperator.Opcode.Div: return(Visitor.VisitDiv(e)); case BinaryOperator.Opcode.Mod: return(Visitor.VisitMod(e)); case BinaryOperator.Opcode.RealDiv: return(Visitor.VisitRealDiv(e)); case BinaryOperator.Opcode.Pow: return(Visitor.VisitPow(e)); // Comparision operators case BinaryOperator.Opcode.Eq: return(Visitor.VisitEq(e)); case BinaryOperator.Opcode.Neq: return(Visitor.VisitNeq(e)); case BinaryOperator.Opcode.Gt: return(Visitor.VisitGt(e)); case BinaryOperator.Opcode.Ge: return(Visitor.VisitGe(e)); case BinaryOperator.Opcode.Lt: return(Visitor.VisitLt(e)); case BinaryOperator.Opcode.Le: return(Visitor.VisitLe(e)); // Bool operators case BinaryOperator.Opcode.And: return(Visitor.VisitAnd(e)); case BinaryOperator.Opcode.Or: return(Visitor.VisitOr(e)); case BinaryOperator.Opcode.Imp: return(Visitor.VisitImp(e)); case BinaryOperator.Opcode.Iff: return(Visitor.VisitIff(e)); case BinaryOperator.Opcode.Subtype: return(Visitor.VisitSubType(e)); default: throw new NotImplementedException("Binary operator not supported!"); } } else if (e.Fun is MapStore) { return(Visitor.VisitMapStore(e)); } else if (e.Fun is MapSelect) { return(Visitor.VisitMapSelect(e)); } else if (e.Fun is IfThenElse) { return(Visitor.VisitIfThenElse(e)); } else if (e.Fun is TypeCoercion) { return(Visitor.VisitTypeCoercion(e)); } else if (e.Fun is ArithmeticCoercion) { return(Visitor.VisitArithmeticCoercion(e)); } else if (e.Fun is DistinctOperator) { return(Visitor.VisitDistinct(e)); } throw new NotImplementedException("NAry not handled!"); }
protected Expr HandlerBvBuiltIns(NAryExpr e, string builtin) { Debug.Assert(builtin.Length > 0); // We grab for first word because the bvbuiltin // might be "zeroextend 16", we don't care about the number string firstWord = builtin.Split(' ')[0]; Debug.Assert(firstWord.Length > 0); switch (firstWord) { // arithmetic case "bvadd": return(Visitor.Visit_bvadd(e)); case "bvsub": return(Visitor.Visit_bvsub(e)); case "bvmul": return(Visitor.Visit_bvmul(e)); case "bvudiv": return(Visitor.Visit_bvudiv(e)); case "bvurem": return(Visitor.Visit_bvurem(e)); case "bvsdiv": return(Visitor.Visit_bvsdiv(e)); case "bvsrem": return(Visitor.Visit_bvsrem(e)); case "bvsmod": return(Visitor.Visit_bvsmod(e)); case "sign_extend": return(Visitor.Visit_sign_extend(e)); case "zero_extend": return(Visitor.Visit_zero_extend(e)); // bitwise logical case "bvneg": return(Visitor.Visit_bvneg(e)); case "bvand": return(Visitor.Visit_bvand(e)); case "bvor": return(Visitor.Visit_bvor(e)); case "bvnot": return(Visitor.Visit_bvnot(e)); case "bvxor": return(Visitor.Visit_bvxor(e)); // shift case "bvshl": return(Visitor.Visit_bvshl(e)); case "bvlshr": return(Visitor.Visit_bvlshr(e)); case "bvashr": return(Visitor.Visit_bvashr(e)); // Comparison case "bvult": return(Visitor.Visit_bvult(e)); case "bvule": return(Visitor.Visit_bvule(e)); case "bvugt": return(Visitor.Visit_bvugt(e)); case "bvuge": return(Visitor.Visit_bvuge(e)); case "bvslt": return(Visitor.Visit_bvslt(e)); case "bvsle": return(Visitor.Visit_bvsle(e)); case "bvsgt": return(Visitor.Visit_bvsgt(e)); case "bvsge": return(Visitor.Visit_bvsge(e)); default: throw new NotImplementedException(firstWord + " bvbuiltin not supported!"); } }
public override Expr VisitNAryExpr(NAryExpr node) { // Simplify the children. node = (NAryExpr)base.VisitNAryExpr(node); // Simplify constant Boolean and bitvector expressions that // occur in assertions when not all arrays are being checked // for races. Bitvector expressions are ignored if they were // modelled as mathematical integers. if (node.Fun is BinaryOperator) { var binOp = node.Fun as BinaryOperator; if (binOp.Op == BinaryOperator.Opcode.Imp) { if (node.Args[0] is LiteralExpr) { return(node.Args[0] == Expr.False ? Expr.True : node.Args[1]); } else if (node.Args[1] is LiteralExpr) { return(node.Args[1] == Expr.True ? Expr.True : node.Args[0]); } } else if (binOp.Op == BinaryOperator.Opcode.Neq) { if (node.Args[0] is LiteralExpr && node.Args[1] is LiteralExpr) { return(node.Args[0].Equals(node.Args[1]) ? Expr.False : Expr.True); } } else if (binOp.Op == BinaryOperator.Opcode.Eq) { if (node.Args[0] is LiteralExpr && node.Args[1] is LiteralExpr) { return(node.Args[0].Equals(node.Args[1]) ? Expr.True : Expr.False); } } } else if (ZextPattern.Match(node.Fun.FunctionName).Success&& node.Type is BvType) { if (node.Args[0] is LiteralExpr && node.Type is BvType) { var NewVal = BigNum.FromBigInt(GetBigInt(node.Args[0])); return(new LiteralExpr(Token.NoToken, NewVal, GetBvBits(node))); } } else if (XorPattern.Match(node.Fun.FunctionName).Success&& node.Type is BvType) { if (node.Args[0] is LiteralExpr && node.Args[1] is LiteralExpr) { var NewVal = BigNum.FromBigInt(GetBigInt(node.Args[0]) ^ GetBigInt(node.Args[1])); return(new LiteralExpr(Token.NoToken, NewVal, GetBvBits(node))); } } else if (AndPattern.Match(node.Fun.FunctionName).Success&& node.Type is BvType) { if (node.Args[0] is LiteralExpr && node.Args[1] is LiteralExpr) { var NewVal = BigNum.FromBigInt(GetBigInt(node.Args[0]) & GetBigInt(node.Args[1])); return(new LiteralExpr(Token.NoToken, NewVal, GetBvBits(node))); } } else if (OrPattern.Match(node.Fun.FunctionName).Success&& node.Type is BvType) { if (node.Args[0] is LiteralExpr && node.Args[1] is LiteralExpr) { var NewVal = BigNum.FromBigInt(GetBigInt(node.Args[0]) | GetBigInt(node.Args[1])); return(new LiteralExpr(Token.NoToken, NewVal, GetBvBits(node))); } } else if (node.Fun is IfThenElse) { if (node.Args[0] is LiteralExpr) { return(node.Args[0] == Expr.True ? node.Args[1] : node.Args[2]); } } return(node); }
public static string PrettyPrintBplExpr(Expr e) { Contract.Requires(e != null); Contract.Ensures(Contract.Result <string>() != null); // anything that is unknown will just be printed via ToString // OldExpr and QuantifierExpr, BvExtractExpr, BvConcatExpr are ignored for now // LiteralExpr is printed as itself by ToString if (e is IdentifierExpr) { string s = e.ToString(); return(Helpers.BeautifyBplString(s)); } else if (e is NAryExpr) { NAryExpr ne = (NAryExpr)e; IAppliable fun = ne.Fun; var eSeq = ne.Args; if (fun != null) { if ((fun.FunctionName == "$Length" || fun.FunctionName == "$StringLength") && eSeq.Count == 1) { Expr e0 = eSeq[0]; if (e0 != null) { string s0 = PrettyPrintBplExpr(e0); return(s0 + ".Length"); } //unexpected, just fall outside to the default } else if (fun.FunctionName == "$typeof" && eSeq.Count == 1) { Expr e0 = eSeq[0]; if (e0 != null) { string s0 = PrettyPrintBplExpr(e0); return("(the dynamic type of: " + s0 + ")"); } //unexpected, just fall outside to the default } else if (fun.FunctionName == "IntArrayGet" && eSeq.Count == 2) { Expr e0 = eSeq[0]; Expr e1 = eSeq[1]; if (e0 != null && e1 != null) { string s0 = PrettyPrintBplExpr(e0); string s1 = PrettyPrintBplExpr(e1); return(s0 + "[" + s1 + "]"); } //unexpected, just fall outside to the default } else if (fun.FunctionName == "$Is" && eSeq.Count == 2) { Expr e0 = eSeq[0]; Expr e1 = eSeq[1]; if (e0 != null && e1 != null) { string s0 = PrettyPrintBplExpr(e0); string s1 = PrettyPrintBplExpr(e1); return("(" + s0 + " == null || (" + s0 + " is " + s1 + "))"); } //unexpected, just fall outside to the default } else if (fun.FunctionName == "$IsNotNull" && eSeq.Count == 2) { Expr e0 = eSeq[0]; Expr e1 = eSeq[1]; if (e0 != null && e1 != null) { string s0 = PrettyPrintBplExpr(e0); string s1 = PrettyPrintBplExpr(e1); return("(" + s0 + " is " + s1 + ")"); } //unexpected, just fall outside to the default } else if (fun is MapSelect && eSeq.Count <= 3) { // only maps with up to two arguments are supported right now (here) if (cce.NonNull(eSeq[0]).ToString() == "$Heap") { //print Index0.Index1, unless Index1 is "$elements", then just print Index0 string s0 = PrettyPrintBplExpr(cce.NonNull(eSeq[1])); if (eSeq.Count > 2) { string s1 = PrettyPrintBplExpr(cce.NonNull(eSeq[2])); if (s1 == "$elements") { return(s0); } else { if (eSeq[2] is IdentifierExpr) { // strip the class name out of a fieldname s1 = s1.Substring(s1.LastIndexOf('.') + 1); } return(s0 + "." + s1); } } } //unexpected, just fall outside to the default } else if (fun is Microsoft.Boogie.BinaryOperator && eSeq.Count == 2) { Microsoft.Boogie.BinaryOperator f = (Microsoft.Boogie.BinaryOperator)fun; Expr e0 = eSeq[0]; Expr e1 = eSeq[1]; if (e0 != null && e1 != null) { string s0 = PrettyPrintBplExpr(e0); string s1 = PrettyPrintBplExpr(e1); string op = ""; switch (f.Op) { case Microsoft.Boogie.BinaryOperator.Opcode.Add: op = " + "; break; case Microsoft.Boogie.BinaryOperator.Opcode.And: op = " && "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Div: op = " div "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Eq: op = " == "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Ge: op = " >= "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Gt: op = " > "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Iff: op = " <==> "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Imp: op = " ==> "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Le: op = " <= "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Lt: op = " < "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Mod: op = " mod "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Mul: op = " * "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Neq: op = " != "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Or: op = " || "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Pow: op = " ** "; break; case Microsoft.Boogie.BinaryOperator.Opcode.RealDiv: op = " / "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Sub: op = " - "; break; case Microsoft.Boogie.BinaryOperator.Opcode.Subtype: op = " <: "; break; default: op = " "; break; } return("(" + s0 + op + s1 + ")"); } //unexpected, just fall outside to the default } else { string s = fun.FunctionName + "("; for (int i = 0; i < eSeq.Count; i++) { Expr ex = eSeq[i]; Contract.Assume(ex != null); if (i > 0) { s += ", "; } string t = PrettyPrintBplExpr(ex); if (t.StartsWith("(") && t.EndsWith(")")) { t = t.Substring(1, t.Length - 2); } s += t; } s += ")"; return(s); //unexpected, just fall outside to the default } } } return(e.ToString()); }
public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { List <Cmd> newCmdSeq = new List <Cmd>(); Action <NAryExpr, string, AssignCmd> RecordAssertion = delegate(NAryExpr assertCondition, string attribute, AssignCmd memAssignCmd) { AssertCmd assertion = new AssertCmd(Token.NoToken, assertCondition); //we use the attribute in a separate pass within the split memory modeler assertion.Attributes = new QKeyValue(Token.NoToken, "region", new List <object> { attribute }, assertion.Attributes); newCmdSeq.Add(assertion); //current_label is the current block, ac is the STORE associated with the assertiion VCSplitter.Instance.RecordAssertion(this.current_label, memAssignCmd, assertion, Utils.getSlashVerifyCmdType(memAssignCmd)); }; foreach (Cmd c in cmdSeq) { if (c is AssignCmd) { AssignCmd ac = c as AssignCmd; Utils.Assert(ac.Lhss.Count == 1 && ac.Rhss.Count == 1, "Not handling parallel AssignCmd"); //Console.Write("."); switch (Utils.getSlashVerifyCmdType(ac)) { case SlashVerifyCmdType.Store8: case SlashVerifyCmdType.Store16: case SlashVerifyCmdType.Store32: case SlashVerifyCmdType.Store64: //mem := store(mem, y, e) { Tuple <Variable, Expr, Expr> storeArgs = Utils.getStoreArgs(ac); Expr store_addr = storeArgs.Item2; Expr store_value = storeArgs.Item3; if (splitProgram) { newCmdSeq.Add(c); break; } NAryExpr condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { store_addr }); RecordAssertion(condition, "addrInBitmap", ac); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { store_addr }); RecordAssertion(condition, "addrInStack", ac); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { store_addr }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInBitmap", ac); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { store_addr }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInStack", ac); //Expr addr_in_mem = // Expr.And( // new NAryExpr(Token.NoToken, new FunctionCall(ge_64), // new List<Expr>() { store_addr, new IdentifierExpr(Token.NoToken, this.stack_low) }), // new NAryExpr(Token.NoToken, new FunctionCall(lt_64), // new List<Expr>() { store_addr, new IdentifierExpr(Token.NoToken, this.bitmap_low) })); //RecordAssertion(addr_in_mem, "!addrInStack"); break; } case SlashVerifyCmdType.RepStosB: //x := REP_STOSB(mem, e1, e2, e3) { break; } default: //x:=e { if (ac.Lhss.First().DeepAssignedVariable.Name.Equals("mem_stack")) { Expr address = Utils.getSplitMemoryOperationAddress(ac); if (address == null) { break; } NAryExpr condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { address }); RecordAssertion(condition, "addrInStack", ac); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr> { address }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInStack", ac); } else if (ac.Lhss.First().DeepAssignedVariable.Name.Equals("mem_bitmap")) { Expr address = Utils.getSplitMemoryOperationAddress(ac); if (address == null) { break; } NAryExpr condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { address }); RecordAssertion(condition, "addrInBitmap", ac); condition = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap), new List <Expr> { address }); condition = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List <Expr> { condition }); RecordAssertion(condition, "!addrInBitmap", ac); } break; } } // TODO handle ITE case } //The assert gets placed prior to the original command newCmdSeq.Add(c); } return(base.VisitCmdSeq(newCmdSeq)); }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is FunctionCall && (node.Fun as FunctionCall).FunctionName.StartsWith("AbsHoudiniConstant")) { ahFuncs.Add((node.Fun as FunctionCall).Func); return Expr.True; } return base.VisitNAryExpr(node); }
//private bool isMemAddress(string label, Cmd c, Dictionary<Tuple<string, Cmd, AssertCmd>, bool> db) //{ // return isRegionAddress(label, c, "GE_64", db); //} //takes an expression and substitutes desired mem for each load(mem,..) sub-expression private Expr splitMemoryOnAllLoads(Expr e, AddrType addrType, bool notBitmap, bool notStack) { //takes as input the addr expr of LOAD(mem,addr), and returns the desired expression for mem : ITE(addrInBitmap(.), mem_bitmap, ITE(..)) Func <Tuple <Expr, Expr>, Expr> getDesiredMemExpr = delegate(Tuple <Expr, Expr> load_info) { if (addrType == AddrType.StackAddress) { return(new IdentifierExpr(Token.NoToken, this.mem_stack)); } if (addrType == AddrType.BitmapAddress) { return(new IdentifierExpr(Token.NoToken, this.mem_bitmap)); } Expr addr = load_info.Item2; List <string> targetedMemSpacesNames = this.splitProgram ? Utils.getSplitMemoryAccessSpace(load_info.Item1 as NAryExpr).Select(i => i.Decl.Name).ToList() : new List <string> { "mem", "mem_bitmap", "mem_stack" }; Expr isAddrInBitmap = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInBitmap), new List <Expr> { addr }); Expr isAddrInStack = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInStack), new List <Expr> { addr }); Expr tmp = new IdentifierExpr(Token.NoToken, mem); if (!notBitmap && targetedMemSpacesNames.Contains("mem_bitmap")) //may target the bitmap { tmp = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInBitmap, new IdentifierExpr(Token.NoToken, this.mem_bitmap), tmp }); } if (!notStack && targetedMemSpacesNames.Contains("mem_stack")) //may target the stack { tmp = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInStack, new IdentifierExpr(Token.NoToken, this.mem_stack), tmp }); } return(tmp); }; //if there is no load, no point in recursing if (!(Utils.getNestedFunctions(e).Any(x => x.FunctionName.Contains("LOAD_LE")))) { return(e); } //we have one or more load expressions here. so let's recursively find them and substitute. if (e is NAryExpr) { //this is a load expression if ((e as NAryExpr).Fun.FunctionName.Contains("LOAD_LE")) { Tuple <Expr, Expr> load_args = Utils.getLoadArgs(e); if (this.splitProgram && load_args.Item1 is IdentifierExpr) { return(e); } Expr desired_mem = getDesiredMemExpr(load_args); //even the address expression can have a load return(new NAryExpr(Token.NoToken, (e as NAryExpr).Fun, new List <Expr> { desired_mem, splitMemoryOnAllLoads(load_args.Item2, addrType, notBitmap, notStack) })); } else { //not a load expression, but we need to recurse List <Expr> new_args = new List <Expr>(); foreach (Expr arg in (e as NAryExpr).Args) { new_args.Add(splitMemoryOnAllLoads(arg, addrType, notBitmap, notStack)); } return(new NAryExpr(Token.NoToken, (e as NAryExpr).Fun, new_args)); } } if (e is BvExtractExpr) { return(new BvExtractExpr(Token.NoToken, splitMemoryOnAllLoads((e as BvExtractExpr).Bitvector, addrType, notBitmap, notStack), (e as BvExtractExpr).End, (e as BvExtractExpr).Start)); } if (e is BvConcatExpr) { return(new BvConcatExpr(Token.NoToken, splitMemoryOnAllLoads((e as BvConcatExpr).E0, addrType, notBitmap, notStack), splitMemoryOnAllLoads((e as BvConcatExpr).E1, addrType, notBitmap, notStack))); } if (e is IdentifierExpr) { return(e); //cant } if (e is LiteralExpr) { return(e); } Utils.Assert(false, "Should not get here"); return(null); }
public override Function VisitFunction(Function node) { // FIXME we should factor this test into a utility function // because its needed in many places. // SMTLIBv2 bvbuiltins can't be recursive if (QKeyValue.FindStringAttribute(node.Attributes, "bvbuiltin") != null) { return(node); } if (QKeyValue.FindStringAttribute(node.Attributes, "builtin") != null) { return(node); } // Pop on to stack CallStack.Add(node); if (node.Body != null) { base.Visit(node.Body); } // Explore definition axiom for the form (forall args :: func(args) <==> expr) if (node.DefinitionAxiom != null) { Debug.Assert(node.DefinitionAxiom.Expr is ForallExpr, "Function defintion axiom is not a forall!"); var forall = node.DefinitionAxiom.Expr as ForallExpr; Debug.Assert(forall.Dummies.Count == node.InParams.Count, "Number of arguments do not match"); Debug.Assert(forall.Body is NAryExpr, "forall body is not an NAryExpr"); var equality = forall.Body as NAryExpr; Debug.Assert(equality.Fun is BinaryOperator, "Forall body is not a BinaryOperator"); var binaryOperator = equality.Fun as BinaryOperator; Debug.Assert(binaryOperator.Op == BinaryOperator.Opcode.Iff || binaryOperator.Op == BinaryOperator.Opcode.Eq, "Binary Operator is not == or <==>"); // Check == or <==> applies to this function // We assume the function is on the lhs Debug.Assert(equality.Args[0] is NAryExpr, "lhs is not NAryExpr"); var lhs = equality.Args[0] as NAryExpr; // May need to step through type coercions NAryExpr shouldBeFunctionCall = lhs; while (shouldBeFunctionCall.Fun is TypeCoercion) { Debug.Assert(lhs.Args[0] is NAryExpr, "Hit non NAryExpr whilst traversing TypeCoercion"); shouldBeFunctionCall = lhs.Args[0] as NAryExpr; } Debug.Assert(shouldBeFunctionCall.Fun is FunctionCall, "LHS is not a FunctionCall"); var lhsFuncCall = shouldBeFunctionCall.Fun as FunctionCall; Debug.Assert(lhsFuncCall.Func.Equals(node), "Axiom does not apply to function " + node.Name); // The rhs is the Function Expr base.Visit(equality.Args[1]); } // Pop from stack CallStack.Remove(node); return(node); }
public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { if (!Options.splitMemoryModel) { return(base.VisitCmdSeq(cmdSeq)); } List <Cmd> newCmdSeq = new List <Cmd>(); foreach (Cmd c in cmdSeq) { if (c is AssignCmd) { AssignCmd ac = c as AssignCmd; Utils.Assert(ac.Lhss.Count == 1 && ac.Rhss.Count == 1, "Not handling parallel AssignCmd"); ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { ac.Lhss[0] }, new List <Expr> { transformLoad(this.current_label, c, ac.Rhss[0]) }); switch (Utils.getSlashVerifyCmdType(ac)) { case SlashVerifyCmdType.Store8: case SlashVerifyCmdType.Store16: case SlashVerifyCmdType.Store32: case SlashVerifyCmdType.Store64: //mem := store(mem, y, e) { Tuple <Variable, Expr, Expr> storeArgs = Utils.getStoreArgs(ac); Expr store_addr = storeArgs.Item2; Expr store_value = storeArgs.Item3; AddrType addrType = AddrType.Unknown; if (Options.optimizeStoreITE) { if (isStackAddress(this.current_label, c, this.storeAddressRegionDB)) { addrType = AddrType.StackAddress; } else if (isBitmapAddress(this.current_label, c, this.storeAddressRegionDB)) { addrType = AddrType.BitmapAddress; } //else if (isMemAddress(this.current_label, c, this.storeAddressRegionDB)) { addrType = AddrType.MemAddress; } else { addrType = AddrType.Unknown; } } if (addrType == AddrType.StackAddress) { //adds mem_stack := STORE(mem_stack, addr, value); AssignCmd new_ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_stack)) }, new List <Expr> { new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_stack), store_addr, store_value }) }); newCmdSeq.Add(new_ac); } else if (addrType == AddrType.BitmapAddress) { //adds mem_bitmap := STORE(mem_bitmap, addr, value); AssignCmd new_ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_bitmap)) }, new List <Expr> { new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_bitmap), store_addr, store_value }) }); newCmdSeq.Add(new_ac); } else { if (this.splitProgram) { if (!isBitmapAddress(this.current_label, c, this.storeAddressRegionDB) && !isStackAddress(this.current_label, c, this.storeAddressRegionDB)) { newCmdSeq.Add(ac); } break; } Expr isAddrInBitmap = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInBitmap), new List <Expr> { store_addr }); Expr isAddrInStack = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInStack), new List <Expr> { store_addr }); newCmdSeq.Add(ac); Expr rhs; //may exist an execution such that the stack is written // mem_stack := ITE(isAddrInStack(storeAddr), STORE(mem_stack, addr, value), mem_stack); if (!isNotStackAddress(this.current_label, c, this.storeAddressRegionDB)) { rhs = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInStack, new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_stack), store_addr, store_value }), new IdentifierExpr(Token.NoToken, this.mem_stack) }); AssignCmd stack_ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_stack)) }, new List <Expr> { rhs }); newCmdSeq.Add(stack_ac); } //may exist an execution such that the bitmap is written // mem_bitmap := ITE(isAddrInBitmap(storeAddr), STORE(mem_bitmap, addr, value), mem_bitmap); if (!isNotBitmapAddress(this.current_label, c, this.storeAddressRegionDB)) { rhs = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInBitmap, new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_bitmap), store_addr, store_value }), new IdentifierExpr(Token.NoToken, this.mem_bitmap) }); AssignCmd bitmap_ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_bitmap)) }, new List <Expr> { rhs }); newCmdSeq.Add(bitmap_ac); } } break; } case SlashVerifyCmdType.RepStosB: { Tuple <Variable, Expr, Expr, Expr> repstosArgs = Utils.getRepStosbArgs(ac); Expr base_addr = repstosArgs.Item3; Expr length = repstosArgs.Item2; Expr isAddrInBitmap = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInBitmap), new List <Expr> { base_addr }); Expr isAddrInStack = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInStack), new List <Expr> { base_addr }); Expr rhs = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInStack, new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_stack), repstosArgs.Item2, repstosArgs.Item3, repstosArgs.Item4 }), new IdentifierExpr(Token.NoToken, this.mem_stack) }); AssignCmd stack_ac = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_stack)) }, new List <Expr> { rhs }); rhs = new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { isAddrInBitmap, new NAryExpr(Token.NoToken, (ac.Rhss[0] as NAryExpr).Fun, new List <Expr> { new IdentifierExpr(Token.NoToken, this.mem_bitmap), repstosArgs.Item2, repstosArgs.Item3, repstosArgs.Item4 }), new IdentifierExpr(Token.NoToken, this.mem_bitmap) }); AssignCmd bitmap_ac = new AssignCmd(Token.NoToken, new List <AssignLhs>() { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_bitmap)) }, new List <Expr>() { rhs }); newCmdSeq.Add(ac); newCmdSeq.Add(stack_ac); newCmdSeq.Add(bitmap_ac); break; } default: { if (ac.Lhss.First().DeepAssignedVariable.Name.Equals("mem_stack")) { if (isBitmapAddress(this.current_label, c, this.storeAddressRegionDB) || isNotStackAddress(this.current_label, c, this.storeAddressRegionDB)) { break; } else if (isStackAddress(this.current_label, c, this.storeAddressRegionDB)) { AssignCmd updateStack = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_stack)) }, new List <Expr> { Utils.getSplitMemoryUpdateExpr(ac) }); newCmdSeq.Add(updateStack); break; } } else if (ac.Lhss.First().DeepAssignedVariable.Name.Equals("mem_bitmap")) { if (isStackAddress(this.current_label, c, this.storeAddressRegionDB) || isNotBitmapAddress(this.current_label, c, this.storeAddressRegionDB)) { break; } else if (isBitmapAddress(this.current_label, c, this.storeAddressRegionDB)) { AssignCmd updateBitmap = new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_bitmap)) }, new List <Expr> { Utils.getSplitMemoryUpdateExpr(ac) }); newCmdSeq.Add(updateBitmap); break; } } newCmdSeq.Add(ac); break; } } } else { newCmdSeq.Add(c); } } return(base.VisitCmdSeq(newCmdSeq)); }
public override Expr VisitNAryExpr(NAryExpr node) { BinaryOperator op = node.Fun as BinaryOperator; if (op != null && op.Op == BinaryOperator.Opcode.Subtype) isMonomorphic = false; return base.VisitNAryExpr(node); }
/// <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); #region proofgeneration VCExpr postVC = N; VCExpr exprVC = C; #endregion 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; } { var subsumption = Subsumption(ac); if (subsumption == CommandLineOptions.SubsumptionOption.Always || (subsumption == CommandLineOptions.SubsumptionOption.NotForQuantifiers && !(C is VCExprQuantifier))) { N = gen.ImpliesSimp(C, N, false); } if (isFullyVerified) { throw new NotImplementedException("proof generation does not support this option (caching of verification results)"); 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); #region proofgeneration ProofGeneration.ProofGenerationLayer.NextVcHintForBlock( cmd, b, exprVC, postVC, gen.AndSimp(C, N), subsumption ); #endregion return(gen.AndSimp(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))); return(gen.AndSimp(gen.Implies(assertFailure, C), N)); } } } 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(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)); } #region proofgeneration ProofGeneration.ProofGenerationLayer.NextVcHintForBlock( cmd, b, expr, N, gen.ImpliesSimp(expr, N), CommandLineOptions.SubsumptionOption.Never ); #endregion return(MaybeWrapWithOptimization(ctxt, gen, ac.Attributes, gen.ImpliesSimp(expr, N))); } else { Console.WriteLine(cmd.ToString()); Contract.Assert(false); throw new cce.UnreachableException(); // unexpected command } }
public void Transform() { foreach (var impl in program.Implementations) { Dictionary<string, Variable> domainNameToInputVar = new Dictionary<string, Variable>(); foreach (string domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; Formal f = new Formal( Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true); impl.InParams.Add(f); domainNameToInputVar[domainName] = f; } foreach (Block b in impl.Blocks) { List<Cmd> newCmds = new List<Cmd>(); for (int i = 0; i < b.Cmds.Count; i++) { Cmd cmd = b.Cmds[i]; newCmds.Add(cmd); if (cmd is CallCmd) { CallCmd callCmd = cmd as CallCmd; if (callCmd.IsAsync) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } else { Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>(); foreach (var domainName in linearDomains.Keys) { domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]); } foreach (Variable v in AvailableLinearVars(callCmd)) { var domainName = FindDomainName(v); var domain = linearDomains[domainName]; if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue; Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) }); var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); domainNameToExpr[domainName] = expr; } foreach (var domainName in linearDomains.Keys) { callCmd.Ins.Add(domainNameToExpr[domainName]); } } } else if (cmd is ParCallCmd) { ParCallCmd parCallCmd = (ParCallCmd)cmd; foreach (CallCmd callCmd in parCallCmd.CallCmds) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } } else if (cmd is YieldCmd) { AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar); } } b.Cmds = newCmds; } { // Loops impl.PruneUnreachableBlocks(); impl.ComputePredecessorsForBlocks(); GraphUtil.Graph<Block> g = Program.GraphFromImpl(impl); g.ComputeLoops(); if (g.Reducible) { foreach (Block header in g.Headers) { List<Cmd> newCmds = new List<Cmd>(); AddDisjointnessExpr(newCmds, header, domainNameToInputVar); newCmds.AddRange(header.Cmds); header.Cmds = newCmds; } } } } foreach (var proc in program.Procedures) { Dictionary<string, HashSet<Variable>> domainNameToInputScope = new Dictionary<string, HashSet<Variable>>(); Dictionary<string, HashSet<Variable>> domainNameToOutputScope = new Dictionary<string, HashSet<Variable>>(); foreach (var domainName in linearDomains.Keys) { domainNameToInputScope[domainName] = new HashSet<Variable>(); domainNameToOutputScope[domainName] = new HashSet<Variable>(); } foreach (Variable v in globalVarToDomainName.Keys) { var domainName = globalVarToDomainName[v]; domainNameToInputScope[domainName].Add(v); domainNameToOutputScope[domainName].Add(v); } foreach (Variable v in proc.InParams) { var domainName = FindDomainName(v); if (domainName == null) continue; if (!this.linearDomains.ContainsKey(domainName)) continue; domainNameToInputScope[domainName].Add(v); } foreach (Variable v in proc.OutParams) { var domainName = FindDomainName(v); if (domainName == null) continue; if (!this.linearDomains.ContainsKey(domainName)) continue; domainNameToOutputScope[domainName].Add(v); } foreach (var domainName in linearDomains.Keys) { proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName]))); var domain = linearDomains[domainName]; Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true); proc.InParams.Add(f); proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, f, domainNameToOutputScope[domainName]))); } } foreach (LinearDomain domain in linearDomains.Values) { program.AddTopLevelDeclaration(domain.mapConstBool); program.AddTopLevelDeclaration(domain.mapConstInt); program.AddTopLevelDeclaration(domain.mapEqInt); program.AddTopLevelDeclaration(domain.mapImpBool); program.AddTopLevelDeclaration(domain.mapOrBool); foreach (Axiom axiom in domain.axioms) { program.AddTopLevelDeclaration(axiom); } } //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured; //CommandLineOptions.Clo.PrintUnstructured = 1; //PrintBplFile("lsd.bpl", program, false, false); //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured; }
public void SimpleMap() { int hits = 0; Expr nestedMapStoreintermediate = null; Expr simpleMapStoreIntermediate = null; p = LoadProgramFrom("programs/SimpleMap.bpl"); e = GetExecutor(p); var builderDuplicator = new BuilderDuplicator(new SimpleExprBuilder(/*immutable=*/ true)); e.BreakPointReached += delegate(object executor, Executor.BreakPointEventArgs data) { if (data.Name == "check_read_map") { var a = e.CurrentState.GetInScopeVariableAndExprByName("a"); // a := symbolic_0[0bv8] Assert.IsInstanceOf <NAryExpr>(a.Value); NAryExpr mapSelect = a.Value as NAryExpr; Assert.IsInstanceOf <MapSelect>(mapSelect.Fun); Assert.AreEqual(2, mapSelect.Args.Count); // [0] should be map Identifier CheckIsSymbolicIdentifier(mapSelect.Args[0], e.CurrentState); // [1] should be offset CheckIsLiteralBVConstWithValue(mapSelect.Args[1], BigNum.FromInt(0)); } else if (data.Name == "check_write_literal") { var m = e.CurrentState.GetInScopeVariableAndExprByName("m"); // m := symbolic_0[3bv8 := 12bv32] simpleMapStoreIntermediate = (Expr)builderDuplicator.Visit(m.Value); // Save a copy of the expression for later. Assert.IsInstanceOf <NAryExpr>(m.Value); NAryExpr mapStore = m.Value as NAryExpr; Assert.IsInstanceOf <MapStore>(mapStore.Fun); Assert.AreEqual(3, mapStore.Args.Count); // [0] should be map Identifier CheckIsSymbolicIdentifier(mapStore.Args[0], e.CurrentState); // [1] should be write offset CheckIsLiteralBVConstWithValue(mapStore.Args[1], BigNum.FromInt(3)); // [2] should be value written to location in Map CheckIsLiteralBVConstWithValue(mapStore.Args[2], BigNum.FromInt(12)); } else if (data.Name == "check_write_from_map") { var m = e.CurrentState.GetInScopeVariableAndExprByName("m"); nestedMapStoreintermediate = (Expr)builderDuplicator.Visit(m.Value); // Save a copy of the expression for later. Assert.IsInstanceOf <NAryExpr>(m.Value); NAryExpr mapStore = m.Value as NAryExpr; Assert.IsInstanceOf <MapStore>(mapStore.Fun); // symbolic_0[3bv8:= 12bv32][1bv8 := symbolic_0[0bv8]] Assert.AreEqual(3, mapStore.Args.Count); // [0] Is Map written to which should we wrote to earlier so should also be MapStore Assert.IsTrue(mapStore.Args[0].Equals(simpleMapStoreIntermediate)); // [1] is write offset CheckIsLiteralBVConstWithValue(mapStore.Args[1], BigNum.FromInt(1)); // 1bv8 // [2] is value to write which is actually a value inside own map Assert.IsInstanceOf <NAryExpr>(mapStore.Args[2]); NAryExpr WrittenValue = mapStore.Args[2] as NAryExpr; // symbolic_0[0bv8] Assert.IsInstanceOf <MapSelect>(WrittenValue.Fun); { // [0] should be map Identifier CheckIsSymbolicIdentifier(WrittenValue.Args[0], e.CurrentState); // [1] should be offset CheckIsLiteralBVConstWithValue(WrittenValue.Args[1], BigNum.FromInt(0)); } } else if (data.Name == "check_write_symbolic_index") { // Expecting m := symbolic_0[3bv8 := 12bv32][1bv8 := symbolic_0[0bv8]][symbolic_2 := 7bv32] var m = e.CurrentState.GetInScopeVariableAndExprByName("m"); Assert.IsInstanceOf <NAryExpr>(m.Value); NAryExpr mapStore = m.Value as NAryExpr; Assert.IsInstanceOf <MapStore>(mapStore.Fun); // symbolic_0[3bv8:= 12bv32][1bv8 := symbolic_0[0bv8]] Assert.AreEqual(3, mapStore.Args.Count); // [0] Should be the map written to which should be equivalent to the expression recorded in "intermediate" Assert.IsNotNull(nestedMapStoreintermediate); Assert.IsTrue(nestedMapStoreintermediate.Equals(mapStore.Args[0])); // [1] Write offset which should be symbolic (symbolic_2) CheckIsSymbolicIdentifier(mapStore.Args[1], e.CurrentState); // [2] Value to write (7bv32) CheckIsLiteralBVConstWithValue(mapStore.Args[2], BigNum.FromInt(7)); } else { Assert.Fail("Unsupported break point"); } ++hits; }; e.Run(GetMain(p)); Assert.AreEqual(4, hits); }
private void AddInitialBlock(Implementation impl, List<Variable> oldPcs, List<Variable> oldOks, Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap) { // Add initial block List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); if (pc != null) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc))); rhss.Add(Expr.False); foreach (Variable oldPc in oldPcs) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc))); rhss.Add(Expr.False); } lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))); rhss.Add(Expr.False); foreach (Variable oldOk in oldOks) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk))); rhss.Add(Expr.False); } } Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>(); foreach (var domainName in linearTypeChecker.linearDomains.Keys) { domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]); } for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++) { Variable v = impl.InParams[i]; var domainName = linearTypeChecker.FindDomainName(v); if (domainName == null) continue; if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue; var domain = linearTypeChecker.linearDomains[domainName]; if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue; Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) }); domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] }); } foreach (string domainName in linearTypeChecker.linearDomains.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName]))); rhss.Add(domainNameToExpr[domainName]); } foreach (Variable g in ogOldGlobalMap.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g]))); rhss.Add(Expr.Ident(g)); } if (lhss.Count > 0) { Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] })); impl.Blocks.Insert(0, initBlock); } }
/// <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 } }
public override Expr VisitNAryExpr(NAryExpr node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Expr>() != null); return base.VisitNAryExpr((NAryExpr)node.Clone()); }
/// <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)); } } } //return gen.ImpliesSimp(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 { return(gen.ImpliesSimp(ctxt.Ctxt.BoogieExprTranslator.Translate(ac.Expr), N)); /*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 } }
public StratifiedInliningInfo(Implementation implementation, StratifiedVCGenBase stratifiedVcGen, Action<Implementation> PassiveImplInstrumentation) { vcgen = stratifiedVcGen; impl = implementation; this.PassiveImplInstrumentation = PassiveImplInstrumentation; List<Variable> functionInterfaceVars = new List<Variable>(); foreach (Variable v in vcgen.program.GlobalVariables) { functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true)); } foreach (Variable v in impl.InParams) { functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true)); } foreach (Variable v in impl.OutParams) { functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", v.TypedIdent.Type), true)); } foreach (IdentifierExpr e in impl.Proc.Modifies) { if (e.Decl == null) continue; functionInterfaceVars.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", e.Decl.TypedIdent.Type), true)); } Formal returnVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "", Bpl.Type.Bool), false); function = new Function(Token.NoToken, impl.Name, functionInterfaceVars, returnVar); vcgen.prover.Context.DeclareFunction(function, ""); List<Expr> exprs = new List<Expr>(); foreach (Variable v in vcgen.program.GlobalVariables) { Contract.Assert(v != null); exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); } foreach (Variable v in impl.Proc.InParams) { Contract.Assert(v != null); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (Variable v in impl.Proc.OutParams) { Contract.Assert(v != null); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (IdentifierExpr ie in impl.Proc.Modifies) { Contract.Assert(ie != null); if (ie.Decl == null) continue; exprs.Add(ie); } Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs); impl.Proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null))); initialized = false; }
// NAryExpr public static int GetNumberOfChildren(this NAryExpr e) { return(e.Args.Count); }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is UnaryOperator) { var op = (UnaryOperator)node.Fun; Contract.Assert(node.Args.Count == 1); if (op.Op == UnaryOperator.Opcode.Neg) { BigInteger? lo, hi; VisitExpr(node.Args[0]); lo = Lo; hi = Hi; if (hi != null) { Lo = node.Type.IsReal ? -hi : 1 - hi; } else { Lo = null; } if (lo != null) { Hi = node.Type.IsReal ? -lo : 1 - lo; } else { Hi = null; } } else if (op.Op == UnaryOperator.Opcode.Not) { VisitExpr(node.Args[0]); Contract.Assert((Lo == null && Hi == null) || (Lo == null && (BigInteger)Hi == 1) || (Hi == null && (BigInteger)Lo == 1)); var tmp = Lo; Lo = Hi; Hi = tmp; } } else if (node.Fun is BinaryOperator) { var op = (BinaryOperator)node.Fun; Contract.Assert(node.Args.Count == 2); BigInteger? lo0, hi0, lo1, hi1; VisitExpr(node.Args[0]); lo0 = Lo; hi0 = Hi; VisitExpr(node.Args[1]); lo1 = Lo; hi1 = Hi; Lo = Hi = null; var isReal = node.Args[0].Type.IsReal; switch (op.Op) { case BinaryOperator.Opcode.And: if (hi0 != null || hi1 != null) { // one operand is definitely false, thus so is the result Lo = null; Hi = one; } else if (lo0 != null && lo1 != null) { // both operands are definitely true, thus so is the result Lo = one; Hi = null; } break; case BinaryOperator.Opcode.Or: if (lo0 != null || lo1 != null) { // one operand is definitely true, thus so is the result Lo = one; Hi = null; } else if (hi0 != null && hi1 != null) { // both operands are definitely false, thus so is the result Lo = null; Hi = one; } break; case BinaryOperator.Opcode.Imp: if (hi0 != null || lo1 != null) { // either arg0 false or arg1 is true, so the result is true Lo = one; Hi = null; } else if (lo0 != null && hi1 != null) { // arg0 is true and arg1 is false, so the result is false Lo = null; Hi = one; } break; case BinaryOperator.Opcode.Iff: if (lo0 != null && lo1 != null) { Lo = one; Hi = null; } else if (hi0 != null && hi1 != null) { Lo = one; Hi = null; } else if (lo0 != null && hi1 != null) { Lo = null; Hi = one; } else if (hi0 != null && lo1 != null) { Lo = null; Hi = one; } if (op.Op == BinaryOperator.Opcode.Neq) { var tmp = Lo; Lo = Hi; Hi = tmp; } break; case BinaryOperator.Opcode.Eq: case BinaryOperator.Opcode.Neq: if (node.Args[0].Type.IsBool) { goto case BinaryOperator.Opcode.Iff; } // For Eq: // If the (lo0,hi0) and (lo1,hi1) ranges do not overlap, the answer is false. // If both ranges are the same unit range, then the answer is true. if (hi0 != null && lo1 != null && (isReal ? hi0 < lo1 : hi0 <= lo1)) { // no overlap Lo = null; Hi = one; } else if (lo0 != null && hi1 != null && (isReal ? hi1 < lo0 : hi1 <= lo0)) { Lo = null; Hi = one; // no overlaop } else if (lo0 != null && hi0 != null && lo1 != null && hi1 != null && lo0 == lo1 && hi0 == hi1 && // ranges are the same (isReal ? lo0 == hi0 : lo0 + 1 == hi0)) { // unit range // both ranges are the same unit range Lo = one; Hi = null; } if (op.Op == BinaryOperator.Opcode.Neq) { var tmp = Lo; Lo = Hi; Hi = tmp; } break; case BinaryOperator.Opcode.Le: if (isReal) { // If hi0 <= lo1, then the answer is true. // If hi1 < lo0, then the answer is false. if (hi0 != null && lo1 != null && hi0 <= lo1) { Lo = one; Hi = null; } else if (hi1 != null && lo0 != null && hi1 < lo0) { Lo = null; Hi = one; } } else { // If hi0 - 1 <= lo1, then the answer is true. // If hi1 <= lo0, then the answer is false. if (hi0 != null && lo1 != null && hi0 - 1 <= lo1) { Lo = one; Hi = null; } else if (lo0 != null && hi1 != null && hi1 <= lo0) { Lo = null; Hi = one; } } break; case BinaryOperator.Opcode.Lt: if (isReal) { // If hi0 < lo1, then the answer is true. // If hi1 <= lo0, then the answer is false. if (hi0 != null && lo1 != null && hi0 < lo1) { Lo = one; Hi = null; } else if (hi1 != null && lo0 != null && hi1 <= lo0) { Lo = null; Hi = one; } } else { // If hi0 <= lo1, then the answer is true. // If hi1 - 1 <= lo0, then the answer is false. if (hi0 != null && lo1 != null && hi0 <= lo1) { Lo = one; Hi = null; } else if (lo0 != null && hi1 != null && hi1 - 1 <= lo0) { Lo = null; Hi = one; } } break; case BinaryOperator.Opcode.Gt: // swap the operands and then continue as Lt { var tmp = lo0; lo0 = lo1; lo1 = tmp; tmp = hi0; hi0 = hi1; hi1 = tmp; } goto case BinaryOperator.Opcode.Lt; case BinaryOperator.Opcode.Ge: // swap the operands and then continue as Le { var tmp = lo0; lo0 = lo1; lo1 = tmp; tmp = hi0; hi0 = hi1; hi1 = tmp; } goto case BinaryOperator.Opcode.Le; case BinaryOperator.Opcode.Add: if (lo0 != null && lo1 != null) { Lo = lo0 + lo1; } if (hi0 != null && hi1 != null) { Hi = isReal ? hi0 + hi1 : hi0 + hi1 - 1; } break; case BinaryOperator.Opcode.Sub: if (lo0 != null && hi1 != null) { Lo = isReal ? lo0 - hi1 : lo0 - hi1 + 1; } if (hi0 != null && lo1 != null) { Hi = hi0 - lo1; } break; case BinaryOperator.Opcode.Mul: // this uses an incomplete approximation that could be tightened up if (lo0 != null && lo1 != null) { if (0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) { Lo = lo0 * lo1; Hi = hi0 == null || hi1 == null ? null : isReal ? hi0 * hi1 : (hi0 - 1) * (hi1 - 1) + 1; } else if ((BigInteger)lo0 < 0 && (BigInteger)lo1 < 0) { Lo = null; // approximation Hi = isReal ? lo0 * lo1 : lo0 * lo1 + 1; } } break; case BinaryOperator.Opcode.Div: // this uses an incomplete approximation that could be tightened up if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) { Lo = BigInteger.Zero; Hi = hi0; } break; case BinaryOperator.Opcode.Mod: // this uses an incomplete approximation that could be tightened up if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) { Lo = BigInteger.Zero; Hi = hi1; if (lo0 < lo1 && hi0 != null && hi0 < lo1) { Lo = lo0; Hi = hi0; } } break; case BinaryOperator.Opcode.RealDiv: // this uses an incomplete approximation that could be tightened up if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) { Lo = BigInteger.Zero; Hi = 1 <= (BigInteger)lo1 ? hi0 : null; } break; case BinaryOperator.Opcode.Pow: // this uses an incomplete approximation that could be tightened up if (lo0 != null && lo1 != null && 0 <= (BigInteger)lo0 && 0 <= (BigInteger)lo1) { Lo = 1 <= (BigInteger)lo1 ? BigInteger.One : BigInteger.Zero; Hi = hi1; } break; default: break; } } else if (node.Fun is IfThenElse) { var op = (IfThenElse)node.Fun; Contract.Assert(node.Args.Count == 3); BigInteger? guardLo, guardHi, lo0, hi0, lo1, hi1; VisitExpr(node.Args[0]); guardLo = Lo; guardHi = Hi; VisitExpr(node.Args[1]); lo0 = Lo; hi0 = Hi; VisitExpr(node.Args[2]); lo1 = Lo; hi1 = Hi; Contract.Assert(guardLo == null || guardHi == null); // this is a consequence of the guard being boolean if (guardLo != null) { // guard is always true Lo = lo0; Hi = hi0; } else if (guardHi != null) { // guard is always false Lo = lo1; Hi = hi1; } else { // we don't know which branch will be taken, so join the information from the two branches Lo = Node.Min(lo0, lo1, false); Hi = Node.Max(hi0, hi1, false); } } else if (node.Fun is FunctionCall) { var call = (FunctionCall)node.Fun; // See if this is an identity function, which we do by checking: that the function has // exactly one argument and the function has been marked by the user with the attribute {:identity} bool claimsToBeIdentity = false; if (call.ArgumentCount == 1 && call.Func.CheckBooleanAttribute("identity", ref claimsToBeIdentity) && claimsToBeIdentity && node.Args[0].Type.Equals(node.Type)) { VisitExpr(node.Args[0]); } } return node; }
public static void SetChild(this NAryExpr e, int number, Expr NewChild) { e.Args[number] = NewChild; }
public override Expr VisitNAryExpr(NAryExpr node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Expr>() != null); FunctionCall fn = node.Fun as FunctionCall; if (fn != null && cce.NonNull(fn.Func).NeverTrigger) { parent.Triggers = new Trigger(fn.Func.tok, false, new List<Expr> { node} , parent.Triggers); } return base.VisitNAryExpr(node); }
void ArrayExpression(out Expr/*!*/ e) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; Expr/*!*/ index0 = dummyExpr; Expr/*!*/ e1; bool store; bool bvExtract; List<Expr>/*!*/ allArgs = dummyExprSeq; AtomExpression(out e); while (la.kind == 18) { Get(); x = t; allArgs = new List<Expr> (); allArgs.Add(e); store = false; bvExtract = false; if (StartOf(15)) { if (StartOf(9)) { Expression(out index0); if (index0 is BvBounds) bvExtract = true; else allArgs.Add(index0); while (la.kind == 13) { Get(); Expression(out e1); if (bvExtract || e1 is BvBounds) this.SemErr("bitvectors only have one dimension"); allArgs.Add(e1); } if (la.kind == 51) { Get(); Expression(out e1); if (bvExtract || e1 is BvBounds) this.SemErr("assignment to bitvectors is not possible"); allArgs.Add(e1); store = true; } } else { Get(); Expression(out e1); allArgs.Add(e1); store = true; } } Expect(19); if (store) e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs); else if (bvExtract) e = new BvExtractExpr(x, e, ((BvBounds)index0).Upper.ToIntSafe, ((BvBounds)index0).Lower.ToIntSafe); else e = new NAryExpr(x, new MapSelect(x, allArgs.Count - 1), allArgs); } }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is FunctionCall) { var collector = new VariableCollector(); collector.Visit(node); if(existentialExpr != null && existentialExpr.Dummies.Intersect(collector.usedVars).Any()) functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).Func, existentialExpr)); else functionsUsed.Add(Tuple.Create<Function, ExistsExpr>((node.Fun as FunctionCall).Func, null)); } return base.VisitNAryExpr(node); }
void IfThenElseExpression(out Expr/*!*/ e) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ tok; Expr/*!*/ e0, e1, e2; e = dummyExpr; Expect(41); tok = t; Expression(out e0); Expect(88); Expression(out e1); Expect(42); Expression(out e2); e = new NAryExpr(tok, new IfThenElse(tok), new List<Expr>{ e0, e1, e2 }); }
public static Expr GetChild(this NAryExpr e, int number) { return(e.Args[number]); }
public static Expr Extract(Expr expr, Program program, List <Axiom> axioms) { Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null); if (expr is LiteralExpr) { return(expr); } var extractor = new FunctionExtractor(); var body = extractor.VisitExpr(expr); var name = program.FreshExtractedFunctionName(); var originalVars = extractor.Substitutions.Keys.ToList(); var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList <Variable>(); var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false); var func = new Function(Token.NoToken, name, formalInArgs, formalOutArg); func.AddAttribute("never_pattern"); var boundVars = originalVars.Select(k => extractor.Substitutions[k]); var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList <Expr>()); axiomCall.Type = expr.Type; axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY; var eq = LiteralExpr.Eq(axiomCall, body); eq.Type = body.Type; eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY; if (0 < formalInArgs.Count) { var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList <Variable>(), new Trigger(Token.NoToken, true, new List <Expr> { axiomCall }), eq); body = forallExpr; forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List <object> { new LiteralExpr(Token.NoToken, BaseTypes.BigNum.FromInt(30)) }, null); body.Type = Type.Bool; } else { body = eq; } var axiom = new Axiom(Token.NoToken, body); func.DefinitionAxiom = axiom; program.AddTopLevelDeclaration(func); program.AddTopLevelDeclaration(axiom); axioms.Add(axiom); var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList <Expr>()); call.Type = expr.Type; call.TypeParameters = SimpleTypeParamInstantiation.EMPTY; return(call); }
void AtomExpression(out Expr/*!*/ e) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; BigFloat bf; List<Expr>/*!*/ es; List<Variable>/*!*/ ds; Trigger trig; List<TypeVariable>/*!*/ typeParams; IdentifierExpr/*!*/ id; QKeyValue kv; e = dummyExpr; List<Variable>/*!*/ locals; List<Block/*!*/>/*!*/ blocks; switch (la.kind) { case 83: { Get(); e = new LiteralExpr(t, false); break; } case 84: { Get(); e = new LiteralExpr(t, true); break; } case 3: { Nat(out bn); e = new LiteralExpr(t, bn); break; } case 5: case 6: { Dec(out bd); e = new LiteralExpr(t, bd); break; } case 7: { Float(out bf); e = new LiteralExpr(t, bf); break; } case 2: { BvLit(out bn, out n); e = new LiteralExpr(t, bn, n); break; } case 1: { Ident(out x); id = new IdentifierExpr(x, x.val); e = id; if (la.kind == 10) { Get(); if (StartOf(9)) { Expressions(out es); e = new NAryExpr(x, new FunctionCall(id), es); } else if (la.kind == 11) { e = new NAryExpr(x, new FunctionCall(id), new List<Expr>()); } else SynErr(124); Expect(11); } break; } case 85: { Get(); x = t; Expect(10); Expression(out e); Expect(11); e = new OldExpr(x, e); break; } case 15: { Get(); x = t; Expect(10); Expression(out e); Expect(11); e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List<Expr>{ e }); break; } case 16: { Get(); x = t; Expect(10); Expression(out e); Expect(11); e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List<Expr>{ e }); break; } case 10: { Get(); if (StartOf(9)) { Expression(out e); if (e is BvBounds) this.SemErr("parentheses around bitvector bounds " + "are not allowed"); } else if (la.kind == 89 || la.kind == 90) { Forall(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); if (typeParams.Count + ds.Count > 0) e = new ForallExpr(x, typeParams, ds, kv, trig, e); } else if (la.kind == 91 || la.kind == 92) { Exists(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); if (typeParams.Count + ds.Count > 0) e = new ExistsExpr(x, typeParams, ds, kv, trig, e); } else if (la.kind == 93 || la.kind == 94) { Lambda(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); if (trig != null) SemErr("triggers not allowed in lambda expressions"); if (typeParams.Count + ds.Count > 0) e = new LambdaExpr(x, typeParams, ds, kv, e); } else SynErr(125); Expect(11); break; } case 41: { IfThenElseExpression(out e); break; } case 86: { CodeExpression(out locals, out blocks); e = new CodeExpr(locals, blocks); break; } default: SynErr(126); break; } }
public void Transform() { foreach (var decl in program.TopLevelDeclarations) { Implementation impl = decl as Implementation; if (impl == null) { continue; } Dictionary <string, Variable> domainNameToInputVar = new Dictionary <string, Variable>(); foreach (string domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; Formal f = new Formal( Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { domain.elementType }, Type.Bool)), true); impl.InParams.Add(f); domainNameToInputVar[domainName] = f; } foreach (Block b in impl.Blocks) { List <Cmd> newCmds = new List <Cmd>(); for (int i = 0; i < b.Cmds.Count; i++) { Cmd cmd = b.Cmds[i]; newCmds.Add(cmd); if (cmd is CallCmd) { CallCmd callCmd = cmd as CallCmd; if (callCmd.IsAsync) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } else { Dictionary <string, Expr> domainNameToExpr = new Dictionary <string, Expr>(); foreach (var domainName in linearDomains.Keys) { domainNameToExpr[domainName] = new IdentifierExpr(Token.NoToken, domainNameToInputVar[domainName]); } foreach (Variable v in availableLinearVars[callCmd]) { var domainName = FindDomainName(v); var domain = linearDomains[domainName]; IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v); var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List <Expr> { v.TypedIdent.Type is MapType ? ie : Singleton(ie, domainName), domainNameToExpr[domainName] }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); domainNameToExpr[domainName] = expr; } foreach (var domainName in linearDomains.Keys) { callCmd.Ins.Add(domainNameToExpr[domainName]); } } } else if (cmd is ParCallCmd) { ParCallCmd parCallCmd = (ParCallCmd)cmd; foreach (CallCmd callCmd in parCallCmd.CallCmds) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } } else if (cmd is YieldCmd) { AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar); } } b.Cmds = newCmds; } { // Loops impl.PruneUnreachableBlocks(); impl.ComputePredecessorsForBlocks(); GraphUtil.Graph <Block> g = Program.GraphFromImpl(impl); g.ComputeLoops(); if (g.Reducible) { foreach (Block header in g.Headers) { List <Cmd> newCmds = new List <Cmd>(); AddDisjointnessExpr(newCmds, header, domainNameToInputVar); newCmds.AddRange(header.Cmds); header.Cmds = newCmds; } } } } foreach (var decl in program.TopLevelDeclarations) { Procedure proc = decl as Procedure; if (proc == null) { continue; } Dictionary <string, HashSet <Variable> > domainNameToInputScope = new Dictionary <string, HashSet <Variable> >(); Dictionary <string, HashSet <Variable> > domainNameToOutputScope = new Dictionary <string, HashSet <Variable> >(); foreach (var domainName in linearDomains.Keys) { domainNameToInputScope[domainName] = new HashSet <Variable>(); domainNameToOutputScope[domainName] = new HashSet <Variable>(); } foreach (Variable v in globalVarToDomainName.Keys) { var domainName = globalVarToDomainName[v]; domainNameToInputScope[domainName].Add(v); domainNameToOutputScope[domainName].Add(v); } foreach (Variable v in proc.InParams) { var domainName = FindDomainName(v); if (domainName == null) { continue; } domainNameToInputScope[domainName].Add(v); } foreach (Variable v in proc.OutParams) { var domainName = FindDomainName(v); if (domainName == null) { continue; } domainNameToOutputScope[domainName].Add(v); } foreach (var domainName in linearDomains.Keys) { proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName]))); var domain = linearDomains[domainName]; Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { domain.elementType }, Type.Bool)), true); proc.InParams.Add(f); domainNameToOutputScope[domainName].Add(f); proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, domainNameToOutputScope[domainName]))); } } foreach (LinearDomain domain in linearDomains.Values) { program.TopLevelDeclarations.Add(domain.mapConstBool); program.TopLevelDeclarations.Add(domain.mapConstInt); program.TopLevelDeclarations.Add(domain.mapEqInt); program.TopLevelDeclarations.Add(domain.mapImpBool); program.TopLevelDeclarations.Add(domain.mapOrBool); foreach (Axiom axiom in domain.axioms) { program.TopLevelDeclarations.Add(axiom); } } //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured; //CommandLineOptions.Clo.PrintUnstructured = 1; //PrintBplFile("lsd.bpl", program, false, false); //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured; }
public override Expr VisitNAryExpr(NAryExpr node) { var funCall = node.Fun as FunctionCall; if (funCall != null) { var visited = dependencies.Contains(funCall.Func); if (!visited) { funCall.Func = VisitFunction(funCall.Func); } } return base.VisitNAryExpr(node); }
public LinearDomain(Program program, string domainName, Type elementType) { this.elementType = elementType; this.axioms = new List <Axiom>(); MapType mapTypeBool = new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { this.elementType }, Type.Bool); MapType mapTypeInt = new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { this.elementType }, Type.Int); this.mapOrBool = new Function(Token.NoToken, "linear_" + domainName + "_MapOr", new List <Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapOrBool.AddAttribute("builtin", "MapOr"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool)); IdentifierExpr aie = new IdentifierExpr(Token.NoToken, a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool)); IdentifierExpr bie = new IdentifierExpr(Token.NoToken, b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = new IdentifierExpr(Token.NoToken, x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapOrBool), new List <Expr> { aie, bie }); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { mapApplTerm, xie }); var rhsTerm = Expr.Binary(BinaryOperator.Opcode.Or, new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { aie, xie }), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { bie, xie })); var axiomExpr = new ForallExpr(Token.NoToken, new List <TypeVariable>(), new List <Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List <Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List <Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapImpBool = new Function(Token.NoToken, "linear_" + domainName + "_MapImp", new List <Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapImpBool.AddAttribute("builtin", "MapImp"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool)); IdentifierExpr aie = new IdentifierExpr(Token.NoToken, a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool)); IdentifierExpr bie = new IdentifierExpr(Token.NoToken, b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = new IdentifierExpr(Token.NoToken, x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapImpBool), new List <Expr> { aie, bie }); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { mapApplTerm, xie }); var rhsTerm = Expr.Binary(BinaryOperator.Opcode.Imp, new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { aie, xie }), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { bie, xie })); var axiomExpr = new ForallExpr(Token.NoToken, new List <TypeVariable>(), new List <Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List <Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List <Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapConstBool = new Function(Token.NoToken, "linear_" + domainName + "_MapConstBool", new List <Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Bool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapConstBool.AddAttribute("builtin", "MapConst"); } else { BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = new IdentifierExpr(Token.NoToken, x); var trueTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List <Expr> { Expr.True }), xie }); var trueAxiomExpr = new ForallExpr(Token.NoToken, new List <Variable> { x }, trueTerm); trueAxiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, trueAxiomExpr)); var falseTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List <Expr> { Expr.False }), xie }); var falseAxiomExpr = new ForallExpr(Token.NoToken, new List <Variable> { x }, Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, falseTerm)); falseAxiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, falseAxiomExpr)); } this.mapEqInt = new Function(Token.NoToken, "linear_" + domainName + "_MapEq", new List <Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapEqInt.AddAttribute("builtin", "MapEq"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt)); IdentifierExpr aie = new IdentifierExpr(Token.NoToken, a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt)); IdentifierExpr bie = new IdentifierExpr(Token.NoToken, b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = new IdentifierExpr(Token.NoToken, x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapEqInt), new List <Expr> { aie, bie }); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { mapApplTerm, xie }); var rhsTerm = Expr.Binary(BinaryOperator.Opcode.Eq, new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { aie, xie }), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { bie, xie })); var axiomExpr = new ForallExpr(Token.NoToken, new List <TypeVariable>(), new List <Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List <Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List <Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapConstInt = new Function(Token.NoToken, "linear_" + domainName + "_MapConstInt", new List <Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Int), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeInt), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapConstInt.AddAttribute("builtin", "MapConst"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", Type.Int)); IdentifierExpr aie = new IdentifierExpr(Token.NoToken, a); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = new IdentifierExpr(Token.NoToken, x); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List <Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstInt), new List <Expr> { aie }), xie }); var axiomExpr = new ForallExpr(Token.NoToken, new List <Variable> { a, x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, aie)); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } foreach (var axiom in axioms) { axiom.Expr.Resolve(new ResolutionContext(null)); axiom.Expr.Typecheck(new TypecheckingContext(null)); } }
public override Expr VisitNAryExpr(NAryExpr node) { Contract.Ensures(Contract.Result<Expr>() == node); this.VisitExprSeq(node.Args); return node; }
public void GenerateVCsForStratifiedInlining() { Contract.Requires(program != null); foreach (Declaration decl in program.TopLevelDeclarations) { Contract.Assert(decl != null); Implementation impl = decl as Implementation; if (impl == null) continue; Contract.Assert(!impl.Name.StartsWith(recordProcName), "Not allowed to have an implementation for this guy"); Procedure proc = cce.NonNull(impl.Proc); { StratifiedInliningInfo info = new StratifiedInliningInfo(impl, program, boogieContext, QuantifierExpr.GetNextSkolemId()); implName2StratifiedInliningInfo[impl.Name] = info; // We don't need controlFlowVariable for stratified Inlining //impl.LocVars.Add(info.controlFlowVariable); List<Expr> exprs = new List<Expr>(); if (mode != Mode.Boogie && QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint")) { proc.Ensures.Add(new Ensures(Token.NoToken, true, Microsoft.Boogie.Expr.False, "", null)); info.assertExpr = Microsoft.Boogie.Expr.False; // info.isMain = true; } else if (mode == Mode.Corral || proc.FindExprAttribute("inline") != null || proc is LoopProcedure) { foreach (Variable v in program.GlobalVariables()) { Contract.Assert(v != null); exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); } foreach (Variable v in proc.InParams) { Contract.Assert(v != null); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (Variable v in proc.OutParams) { Contract.Assert(v != null); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (IdentifierExpr ie in proc.Modifies) { Contract.Assert(ie != null); if (ie.Decl == null) continue; exprs.Add(ie); } Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs); #if true if(mode == Mode.Corral || mode == Mode.OldCorral) proc.Ensures.Add(new Ensures(Token.NoToken, true, freePostExpr, "", new QKeyValue(Token.NoToken, "si_fcall", new List<object>(), null))); #endif } else // not marked "inline" must be main { Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(info.function), exprs); info.isMain = true; } } } if (mode == Mode.Boogie) return; foreach (var decl in program.TopLevelDeclarations) { var proc = decl as Procedure; if (proc == null) continue; if (!proc.Name.StartsWith(recordProcName)) continue; Contract.Assert(proc.InParams.Count == 1); // Make a new function TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool); Contract.Assert(ti != null); Formal returnVar = new Formal(Token.NoToken, ti, false); Contract.Assert(returnVar != null); // Get record type var argtype = proc.InParams[0].TypedIdent.Type; var ins = new List<Variable>(); ins.Add(new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", argtype), true)); var recordFunc = new Function(Token.NoToken, proc.Name, ins, returnVar); boogieContext.DeclareFunction(recordFunc, ""); var exprs = new List<Expr>(); exprs.Add(new IdentifierExpr(Token.NoToken, proc.InParams[0])); Expr freePostExpr = new NAryExpr(Token.NoToken, new FunctionCall(recordFunc), exprs); proc.Ensures.Add(new Ensures(true, freePostExpr)); } }
public static Expr Extract(Expr expr, Program program, List<Axiom> axioms) { Contract.Requires(expr != null && program != null && !program.TopLevelDeclarationsAreFrozen && axioms != null); if (expr is LiteralExpr) { return expr; } var extractor = new FunctionExtractor(); var body = extractor.VisitExpr(expr); var name = program.FreshExtractedFunctionName(); var originalVars = extractor.Substitutions.Keys.ToList(); var formalInArgs = originalVars.Select(v => new Formal(Token.NoToken, new TypedIdent(Token.NoToken, extractor.Substitutions[v].Name, extractor.Substitutions[v].TypedIdent.Type), true)).ToList<Variable>(); var formalOutArg = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, name + "$result$", expr.Type), false); var func = new Function(Token.NoToken, name, formalInArgs, formalOutArg); func.AddAttribute("never_pattern"); var boundVars = originalVars.Select(k => extractor.Substitutions[k]); var axiomCall = new NAryExpr(Token.NoToken, new FunctionCall(func), boundVars.Select(b => new IdentifierExpr(Token.NoToken, b)).ToList<Expr>()); axiomCall.Type = expr.Type; axiomCall.TypeParameters = SimpleTypeParamInstantiation.EMPTY; var eq = LiteralExpr.Eq(axiomCall, body); eq.Type = body.Type; eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY; if (0 < formalInArgs.Count) { var forallExpr = new ForallExpr(Token.NoToken, boundVars.ToList<Variable>(), new Trigger(Token.NoToken, true, new List<Expr> { axiomCall }), eq); body = forallExpr; forallExpr.Attributes = new QKeyValue(Token.NoToken, "weight", new List<object> { new LiteralExpr(Token.NoToken, Basetypes.BigNum.FromInt(30)) }, null); body.Type = Type.Bool; } else { body = eq; } var axiom = new Axiom(Token.NoToken, body); func.DefinitionAxiom = axiom; program.AddTopLevelDeclaration(func); program.AddTopLevelDeclaration(axiom); axioms.Add(axiom); var call = new NAryExpr(Token.NoToken, new FunctionCall(func), originalVars.Select(v => new IdentifierExpr(Token.NoToken, v)).ToList<Expr>()); call.Type = expr.Type; call.TypeParameters = SimpleTypeParamInstantiation.EMPTY; return call; }
private void AnnotateBlock(Implementation impl, ProverContext ctxt, Block header) { Contract.Assert(header != null); string name = impl.Name + "_" + header.Label + "_invar"; if (annotationInfo.ContainsKey(name)) return; // collect the variables needed in the invariant List<Expr> exprs = new List<Expr>(); List<Variable> vars = new List<Variable>(); List<string> names = new List<string>(); if (style == AnnotationStyle.Flat) { // in flat mode, all live globals should be in live set #if false foreach (Variable v in program.GlobalVariables()) { vars.Add(v); names.Add(v.ToString()); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } #endif foreach (Variable v in /* impl.LocVars */ header.liveVarsBefore) { if (!(v is BoundVariable)) { vars.Add(v); names.Add(v.ToString()); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } } } else { foreach (Variable v in program.GlobalVariables()) { vars.Add(v); names.Add("@old_" + v.ToString()); exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); } foreach (IdentifierExpr ie in impl.Proc.Modifies) { if (ie.Decl == null) continue; vars.Add(ie.Decl); names.Add(ie.Decl.ToString()); exprs.Add(ie); } foreach (Variable v in impl.Proc.InParams) { Contract.Assert(v != null); vars.Add(v); names.Add("@old_" + v.ToString()); exprs.Add(new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); } foreach (Variable v in impl.LocVars) { vars.Add(v); names.Add(v.ToString()); exprs.Add(new IdentifierExpr(Token.NoToken, v)); } } TypedIdent ti = new TypedIdent(Token.NoToken, "", Microsoft.Boogie.Type.Bool); Contract.Assert(ti != null); Formal returnVar = new Formal(Token.NoToken, ti, false); Contract.Assert(returnVar != null); var function = new Function(Token.NoToken, name, vars, returnVar); ctxt.DeclareFunction(function, ""); Expr invarExpr = new NAryExpr(Token.NoToken, new FunctionCall(function), exprs); var invarAssertion = new AssertCmd(Token.NoToken, invarExpr); List<Cmd> newCmds = new List<Cmd>(); newCmds.Add(invarAssertion); // make a record in annotationInfo; var info = new AnnotationInfo(); info.filename = header.tok.filename; info.lineno = header.Line; info.argnames = names.ToArray(); info.type = AnnotationInfo.AnnotationType.LoopInvariant; annotationInfo.Add(name, info); // get file and line info from havoc, if there is... if (header.Cmds.Count > 0) { PredicateCmd bif = header.Cmds[0] as PredicateCmd; if (bif != null) { string foo = QKeyValue.FindStringAttribute(bif.Attributes, "sourcefile"); if (foo != null) info.filename = foo; int bar = QKeyValue.FindIntAttribute(bif.Attributes, "sourceline", -1); if (bar != -1) info.lineno = bar; } } var thing = header; foreach (Cmd c in header.Cmds) { newCmds.Add(c); } header.Cmds = newCmds; }
public override Expr VisitNAryExpr(NAryExpr node) { var funCall = node.Fun as FunctionCall; if (funCall != null) { if (currentDeclaration != null) { currentDeclaration.AddFunctionDependency(funCall.Func); } if (currentAxiom != null) { currentAxiom.AddFunctionDependency(funCall.Func); } } return base.VisitNAryExpr(node); }
/// <summary> /// Compute $pa(p, i, s) == p + i * s); /// </summary> /// <returns>The root pointer.</returns> /// <param name="impl">Implementation</param> /// <param name="label">Root block label</param> /// <param name="id">Identifier expression</param> public static Expr ComputeRootPointer(Implementation impl, string label, Expr id) { if (id is LiteralExpr) { return(id); } if (id is NAryExpr && (id as NAryExpr).Args.Count == 1 && (id as NAryExpr).Fun.FunctionName.Equals("-")) { return(id); } NAryExpr root = PointerArithmeticAnalyser.GetPointerArithmeticExpr(impl, id) as NAryExpr; if (root == null) { return(id); } Expr result = root; Expr resolution = result; int ixs = 0; var alreadyVisited = new HashSet <Tuple <string, Expr> >(); do { if (result is NAryExpr) { if (((result as NAryExpr).Args[0] is IdentifierExpr) && ((result as NAryExpr).Args[0] as IdentifierExpr).Name.StartsWith("$M.")) { return(id); } if (PointerArithmeticAnalyser.TryPerformCast(ref result)) { continue; } if (PointerArithmeticAnalyser.ShouldSkipFromAnalysis(result as NAryExpr)) { return(id); } if (alreadyVisited.Any(v => v.Item1.Equals(label) && v.Item2.Equals(result))) { return(id); } alreadyVisited.Add(new Tuple <string, Expr>(label, result)); if (PointerArithmeticAnalyser.IsArithmeticExpression(result as NAryExpr)) { return(id); } Expr p = (result as NAryExpr).Args[0]; Expr i = (result as NAryExpr).Args[1]; Expr s = (result as NAryExpr).Args[2]; if ((i is LiteralExpr) && (s is LiteralExpr)) { ixs += (i as LiteralExpr).asBigNum.ToInt * (s as LiteralExpr).asBigNum.ToInt; } else { return(id); } result = p; } else { resolution = PointerArithmeticAnalyser.GetPointerArithmeticExpr(impl, result); if (resolution != null) { result = resolution; } } }while (resolution != null); return(Expr.Add(result, new LiteralExpr(Token.NoToken, BigNum.FromInt(ixs)))); }
private Expr SubsetExpr(LinearDomain domain, Expr ie, Variable partition, int partitionCount) { Expr e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstInt), new List<Expr> { new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(partitionCount)) }); e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapEqInt), new List<Expr> { Expr.Ident(partition), e }); e = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapImpBool), new List<Expr> { ie, e }); e = Expr.Eq(e, new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List<Expr> { Expr.True })); return e; }
public override Expr VisitNAryExpr(NAryExpr node) { add(node); return(base.VisitNAryExpr(node)); }
public LinearDomain(Program program, string domainName, Dictionary<Type, Function> collectors) { this.axioms = new List<Axiom>(); this.collectors = collectors; MapType setType = (MapType)collectors.First().Value.OutParams[0].TypedIdent.Type; this.elementType = setType.Arguments[0]; MapType mapTypeBool = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Bool); MapType mapTypeInt = new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { this.elementType }, Type.Int); this.mapOrBool = new Function(Token.NoToken, "linear_" + domainName + "_MapOr", new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapOrBool.AddAttribute("builtin", "MapOr"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool)); IdentifierExpr aie = Expr.Ident(a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool)); IdentifierExpr bie = Expr.Ident(b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = Expr.Ident(x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapOrBool), new List<Expr> { aie, bie } ); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie } ); var rhsTerm = Expr.Or(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie } ), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie} )); var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapImpBool = new Function(Token.NoToken, "linear_" + domainName + "_MapImp", new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapImpBool.AddAttribute("builtin", "MapImp"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeBool)); IdentifierExpr aie = Expr.Ident(a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeBool)); IdentifierExpr bie = Expr.Ident(b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = Expr.Ident(x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapImpBool), new List<Expr> { aie, bie }); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie }); var rhsTerm = Expr.Imp(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie })); var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapConstBool = new Function(Token.NoToken, "linear_" + domainName + "_MapConstBool", new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Bool), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapConstBool.AddAttribute("builtin", "MapConst"); } else { BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = Expr.Ident(x); var trueTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.True }), xie }); var trueAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, trueTerm); trueAxiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, trueAxiomExpr)); var falseTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstBool), new List<Expr> { Expr.False }), xie }); var falseAxiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Unary(Token.NoToken, UnaryOperator.Opcode.Not, falseTerm)); falseAxiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, falseAxiomExpr)); } this.mapEqInt = new Function(Token.NoToken, "linear_" + domainName + "_MapEq", new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt), true), new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeBool), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapEqInt.AddAttribute("builtin", "MapEq"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", mapTypeInt)); IdentifierExpr aie = Expr.Ident(a); BoundVariable b = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "b", mapTypeInt)); IdentifierExpr bie = Expr.Ident(b); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = Expr.Ident(x); var mapApplTerm = new NAryExpr(Token.NoToken, new FunctionCall(mapEqInt), new List<Expr> { aie, bie }); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { mapApplTerm, xie }); var rhsTerm = Expr.Eq(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { aie, xie }), new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { bie, xie })); var axiomExpr = new ForallExpr(Token.NoToken, new List<TypeVariable>(), new List<Variable> { a, b }, null, new Trigger(Token.NoToken, true, new List<Expr> { mapApplTerm }), new ForallExpr(Token.NoToken, new List<Variable> { x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, rhsTerm))); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } this.mapConstInt = new Function(Token.NoToken, "linear_" + domainName + "_MapConstInt", new List<Variable> { new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "b", Type.Int), true) }, new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "c", mapTypeInt), false)); if (CommandLineOptions.Clo.UseArrayTheory) { this.mapConstInt.AddAttribute("builtin", "MapConst"); } else { BoundVariable a = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "a", Type.Int)); IdentifierExpr aie = Expr.Ident(a); BoundVariable x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", elementType)); IdentifierExpr xie = Expr.Ident(x); var lhsTerm = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1), new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(mapConstInt), new List<Expr> { aie }), xie }); var axiomExpr = new ForallExpr(Token.NoToken, new List<Variable> { a, x }, Expr.Binary(BinaryOperator.Opcode.Eq, lhsTerm, aie)); axiomExpr.Typecheck(new TypecheckingContext(null)); axioms.Add(new Axiom(Token.NoToken, axiomExpr)); } foreach (var axiom in axioms) { axiom.Expr.Resolve(new ResolutionContext(null)); axiom.Expr.Typecheck(new TypecheckingContext(null)); } }
public override Expr VisitNAryExpr(NAryExpr node) { //start with some negative cases if (!Matches || _toConsume.Count == 0) { Matches = false; return(base.VisitNAryExpr(node)); } //idea: if in anyExprMode, toConsume does not change --> we eat up any NaryExpr // if any of the arguments matches, the whole thing matches // nothing fancier now, because we only need IdentifierExpr and LiteralExpr if (_anyExprMode) { var anyMatches = false; var dispatched = new List <Expr>(); foreach (var a in node.Args) { Matches = true; dispatched.Add(VisitExpr(a)); anyMatches |= Matches; } Matches = anyMatches; return(new NAryExpr(node.tok, node.Fun, dispatched)); } // check if we need to switch to anyExprMode if (_toConsume.Peek() is NAryExpr && (((NAryExpr)_toConsume.Peek()).Fun) is FunctionCall && ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func != null && BoogieUtil.checkAttrExists(BoogieKeyWords.AnyExpr, ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func.Attributes)) { _anyExprMode = true; _toConsume.Pop(); ((NAryExpr)_toConsume.Peek()).Args.Reverse().Iter(arg => _toConsume.Push(arg)); var result = VisitNAryExpr(node); _anyExprMode = false; return(result); } if (!(_toConsume.Peek() is NAryExpr)) { //may still be an IdentifierExp intended to match any exp if (_toConsume.First() is IdentifierExpr && ((IdentifierExpr)_toConsume.Peek()).Decl != null && !BoogieUtil.checkAttrExists(BoogieKeyWords.IdExpr, ((IdentifierExpr)_toConsume.Peek()).Decl.Attributes)) { Substitution.Add(((IdentifierExpr)_toConsume.Peek()).Decl, node); _toConsume.Pop(); return(node); } Matches = false; return(base.VisitNAryExpr(node)); } var naeToConsume = (NAryExpr)_toConsume.Peek(); if (((NAryExpr)_toConsume.Peek()).Args.Count != node.Args.Count) { Matches = false; return(base.VisitNAryExpr(node)); } // now the positive cases // the same function is used if (naeToConsume.Fun.FunctionName == node.Fun.FunctionName) { _toConsume.Pop(); naeToConsume.Args.Reverse().Iter(arg => _toConsume.Push(arg)); return(base.VisitNAryExpr(node)); } // the function in toConsume has a declaration in TemplateVariables if (naeToConsume.Fun is FunctionCall && ((FunctionCall)naeToConsume.Fun).Func != null && naeToConsume.Fun.ArgumentCount == node.Fun.ArgumentCount && ((FunctionCall)naeToConsume.Fun).Func.InParams.Count == ((FunctionCall)node.Fun).Func.InParams.Count && ((FunctionCall)naeToConsume.Fun).Func.OutParams.Count == ((FunctionCall)node.Fun).Func.OutParams.Count && node.Fun is FunctionCall && AreAttributesASubset( ((FunctionCall)naeToConsume.Fun).Func.Attributes, ((FunctionCall)node.Fun).Func.Attributes)) { // do the argument types match? var tcFunc = ((FunctionCall)naeToConsume.Fun).Func; var nodeFunc = ((FunctionCall)node.Fun).Func; for (var i = 0; i < tcFunc.InParams.Count; i++) { if (!Equals(tcFunc.InParams[i].TypedIdent.Type, nodeFunc.InParams[i].TypedIdent.Type)) { Matches = false; return(base.VisitNAryExpr(node)); } } for (var i = 0; i < tcFunc.OutParams.Count; i++) { if (!Equals(tcFunc.OutParams[i].TypedIdent.Type, nodeFunc.OutParams[i].TypedIdent.Type)) { Matches = false; return(base.VisitNAryExpr(node)); } } FunctionSubstitution.Add(naeToConsume.Fun.FunctionName, node.Fun); _toConsume.Pop(); naeToConsume.Args.Reverse().Iter(arg => _toConsume.Push(arg)); return(base.VisitNAryExpr(node)); } Matches = false; return(base.VisitNAryExpr(node)); }
private Dictionary<string, Expr> ComputeAvailableExprs(IEnumerable<Variable> availableLinearVars, Dictionary<string, Variable> domainNameToInputVar) { Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>(); foreach (var domainName in linearTypeChecker.linearDomains.Keys) { var expr = Expr.Ident(domainNameToInputVar[domainName]); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); domainNameToExpr[domainName] = expr; } foreach (Variable v in availableLinearVars) { var domainName = linearTypeChecker.FindDomainName(v); if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue; var domain = linearTypeChecker.linearDomains[domainName]; if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue; Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) }); var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); domainNameToExpr[domainName] = expr; } return domainNameToExpr; }
public override Expr VisitNAryExpr(NAryExpr node) { funcsUsed.Add(node.Fun.FunctionName); return(base.VisitNAryExpr(node)); }
public void CachedHashCodeNAryExpr() { var nary = new NAryExpr(Token.NoToken, new UnaryOperator(Token.NoToken, UnaryOperator.Opcode.Not), new List<Expr>() { Expr.True }, /*immutable=*/true); Assert.AreEqual(nary.ComputeHashCode(), nary.GetHashCode()); }
public override Expr VisitNAryExpr(NAryExpr node) { // Try to do direct map indexing // FIXME: If there are nested mapselects but they don't end on a variable // then we'll do a lot of unnecessary work every time we traverse into a map select down. var asMapSelect = ExprUtil.AsMapSelect(node); if (asMapSelect != null) { // Gather the indices. They will be backwards as we traversing top down so have to // reverse at the end. // // Here's an example showing this: // // var m:[int][int]bool; // y:= m[0][1] // // The indicies we want are [0][1], but when traverse we will visit them backwards as // we start at the root of the expression tree. // // The structure of this is // // mapselect // / \ // mapselect 1 // / \ // m 0 var indices = new List <Expr>(); Expr firstArg = null; do { // Traverse multi-arity arguments in reverse because later on we reverse them. for (int index = asMapSelect.Args.Count - 1; index >= 1; --index) { // Don't do index variable mapping here because we might // need to throw away what we've done indices.Add(asMapSelect.Args[index]); } firstArg = asMapSelect.Args[0]; asMapSelect = ExprUtil.AsMapSelect(firstArg); } while (asMapSelect != null); // Hopefully a map variable we can write to var asId = ExprUtil.AsIdentifer(firstArg); if (asId != null && asId.Decl.TypedIdent.Type.IsMap) { // Do a remapping if necessary // FIXME: This sucks. Fix boogie instead! Variable V = null; if (preReplacementReMap.ContainsKey(asId.Decl)) { V = preReplacementReMap[asId.Decl]; } else { V = asId.Decl; } // We need to make sure that the map variable isn't bound and that // Note: that map is being fully indexed into and not partially if ((!BoundVariables.Contains(V)) && indices.Count == MapProxy.ComputeIndicesRequireToDirectlyIndex(asId.Decl.TypedIdent.Type)) { // Put indices in correct order indices.Reverse(); // Expand the indices so variables are mapped var expandedIndices = new List <Expr>(); foreach (var index in indices) { expandedIndices.Add((Expr)this.Visit(index)); } var valueFromMap = State.ReadMapVariableInScopeAt(V, expandedIndices); return(valueFromMap); } } } // Handle all other NAryExpr and fall back when we encounter a mapselect we can't support // (e.g. the map variable being used is not known). return(base.VisitNAryExpr(node)); }
public override Expr VisitNAryExpr(NAryExpr node) { var result = base.VisitNAryExpr(node); var nAryExpr = result as NAryExpr; if (nAryExpr != null) { var funCall = nAryExpr.Fun as FunctionCall; if (funCall != null) { funCall.Func = Program.FindFunction(funCall.FunctionName); } } return result; }
public override Expr VisitNAryExpr(NAryExpr node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result <Expr>() != null); return(base.VisitNAryExpr((NAryExpr)node.Clone())); }