Esempio n. 1
0
        public override Expr VisitForallExpr(ForallExpr node)
        {
            Contract.Requires(node != null);
            if (_templates.ContainsKey(node))
            {
                return(node);
            }
            _nestedBoundVariables.AddRange(node.Dummies);
            base.VisitForallExpr(node);
            var body            = node.Body;
            var bodyTemplate    = _templates[body];
            var trigger         = node.Triggers;
            var triggerNoBounds = trigger == null || !_templates[trigger].ContainsBoundVariables();

            if (bodyTemplate is TemplateNoBoundVariables bt && triggerNoBounds)
            {
                var newBody    = bt.GetReplacement();
                var newTrigger = ReplacementTrigger(trigger);
                _templates[node] = new TemplateNoBoundVariables(
                    new ForallExpr(node.tok, node.TypeParameters, node.Dummies, node.Attributes, newTrigger,
                                   newBody, node.Immutable)
                {
                    Type = node.Type
                });
            }
Esempio n. 2
0
        public QuantifierExpr RewriteMatchingLoops(QuantifierWithTriggers q)
        {
            // rewrite quantifier to avoid mathing loops
            // before:
            //    assert forall i :: 0 <= i < a.Length-1 ==> a[i] <= a[i+1];
            // after:
            //    assert forall i,j :: j == i+1 ==> 0 <= i < a.Length-1 ==> a[i] <= a[i+1];
            substMap = new Dictionary <Expression, IdentifierExpr>();
            usedMap  = new Dictionary <Expression, IdentifierExpr>();
            foreach (var m in q.LoopingMatches)
            {
                var e = m.OriginalExpr;
                if (TriggersCollector.IsPotentialTriggerCandidate(e) && triggersCollector.IsTriggerKiller(e))
                {
                    foreach (var sub in e.SubExpressions)
                    {
                        if (triggersCollector.IsTriggerKiller(sub) && (!TriggersCollector.IsPotentialTriggerCandidate(sub)))
                        {
                            IdentifierExpr ie;
                            if (!substMap.TryGetValue(sub, out ie))
                            {
                                var newBv = new BoundVar(sub.tok, "_t#" + substMap.Count, sub.Type);
                                ie            = new IdentifierExpr(sub.tok, newBv.Name);
                                ie.Var        = newBv;
                                ie.Type       = newBv.Type;
                                substMap[sub] = ie;
                            }
                        }
                    }
                }
            }

            var expr = (QuantifierExpr)q.quantifier;

            if (substMap.Count > 0)
            {
                var s = new Translator.ExprSubstituter(substMap);
                expr = s.Substitute(q.quantifier) as QuantifierExpr;
            }
            else
            {
                // make a copy of the expr
                if (expr is ForallExpr)
                {
                    expr = new ForallExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type
                    };
                }
                else
                {
                    expr = new ExistsExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type
                    };
                }
            }
            return(expr);
        }
 public override Expr VisitForallExpr(ForallExpr node)
 {
     if (GetReplacementVariable(node, out var variable))
     {
         return(new IdentifierExpr(variable.tok, variable));
     }
     return(base.VisitForallExpr(node));
 }
Esempio n. 4
0
        // To support forall and exists we need to keep to track of their quantified
        // variables so we don't try to substitute them in VisitIdentifierExpr()
        public override Expr VisitForallExpr(ForallExpr node)
        {
            BoundVariables.UnionWith(node.Dummies);
            var toReturn = base.VisitForallExpr(node);

            BoundVariables.RemoveWhere(e => node.Dummies.Contains(e));
            return(toReturn);
        }
Esempio n. 5
0
        public QuantifierExpr RewriteMatchingLoops(QuantifierWithTriggers q)
        {
            // rewrite quantifier to avoid matching loops
            // before:
            //    assert forall i :: 0 <= i < a.Length-1 ==> a[i] <= a[i+1];
            // after:
            //    assert forall i,j :: j == i+1 ==> 0 <= i < a.Length-1 ==> a[i] <= a[j];
            substMap = new List <Tuple <Expression, IdentifierExpr> >();
            foreach (var m in q.LoopingMatches)
            {
                var e = m.OriginalExpr;
                if (TriggersCollector.IsPotentialTriggerCandidate(e) && triggersCollector.IsTriggerKiller(e))
                {
                    foreach (var sub in e.SubExpressions)
                    {
                        if (triggersCollector.IsTriggerKiller(sub) && (!TriggersCollector.IsPotentialTriggerCandidate(sub)))
                        {
                            var entry = substMap.Find(x => ExprExtensions.ExpressionEq(sub, x.Item1));
                            if (entry == null)
                            {
                                var newBv = new BoundVar(sub.tok, "_t#" + substMap.Count, sub.Type);
                                var ie    = new IdentifierExpr(sub.tok, newBv.Name);
                                ie.Var  = newBv;
                                ie.Type = newBv.Type;
                                substMap.Add(new Tuple <Expression, IdentifierExpr>(sub, ie));
                            }
                        }
                    }
                }
            }

            var expr = (QuantifierExpr)q.quantifier;

            if (substMap.Count > 0)
            {
                var s = new ExprSubstituter(substMap);
                expr = s.Substitute(q.quantifier) as QuantifierExpr;
            }
            else
            {
                // make a copy of the expr
                if (expr is ForallExpr)
                {
                    expr = new ForallExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type, Bounds = expr.Bounds
                    };
                }
                else
                {
                    expr = new ExistsExpr(expr.tok, expr.TypeArgs, expr.BoundVars, expr.Range, expr.Term, TriggerUtils.CopyAttributes(expr.Attributes))
                    {
                        Type = expr.Type, Bounds = expr.Bounds
                    };
                }
            }
            return(expr);
        }
Esempio n. 6
0
 public void CachedHashCodeForAllExpr()
 {
   var x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", BasicType.Int));
   var y = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", BasicType.Int));
   var body = Expr.Gt(new IdentifierExpr(Token.NoToken, x, /*immutable=*/true),
     new IdentifierExpr(Token.NoToken, y, /*immutable=*/true));
   var forAll = new ForallExpr(Token.NoToken, new List<Variable>() {x, y}, body, /*immutable=*/ true);
   Assert.AreEqual(forAll.ComputeHashCode(), forAll.GetHashCode());
 }
Esempio n. 7
0
 public void ProtectedForAllExprBody()
 {
   var x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", BasicType.Int));
   var y = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "x", BasicType.Int));
   var xId = new IdentifierExpr(Token.NoToken, x, /*immutable=*/true);
   var yId = new IdentifierExpr(Token.NoToken, y, /*immutable=*/true);
   var body = Expr.Gt(xId, yId);
   var forAll = new ForallExpr(Token.NoToken, new List<Variable>() {x, y}, body, /*immutable=*/true);
   // Changing the body of an immutable ForAllExpr should fail
   Assert.Throws(typeof(InvalidOperationException), () => forAll.Body = Expr.Lt(xId, yId));
 }
Esempio n. 8
0
        public static Expr GetChild(this ForallExpr e, int number)
        {
            switch (number)
            {
            case 0:
                return(e.Body);

            default:
                throw new InvalidOperationException("ForallExpr only has one child");
            }
        }
Esempio n. 9
0
        public static void SetChild(this ForallExpr e, int number, Expr NewChild)
        {
            switch (number)
            {
            case 0:
                e.Body = NewChild;
                return;

            default:
                throw new InvalidOperationException("ForallExpr only has one child");
            }
        }
Esempio n. 10
0
        public override Expr VisitForallExpr(ForallExpr node)
        {
            var bodyCopy = this.Visit(node.Body) as Expr;

            Debug.Assert(bodyCopy != null);
            var freeVars    = new List <Variable>(node.Dummies);
            var newTriggers = this.VisitTrigger(node.Triggers);
            var newNode     = Builder.ForAll(freeVars, bodyCopy, newTriggers);

            Debug.Assert(newNode != null);
            return(newNode);
        }
        public string GenerateConditionString(ForallExpr expression, IDictionary <string, string> rename)
        {
            StringBuilder bob = new StringBuilder();

            bob.Append(expression.tok.val);
            bob.Append(" ");

            var boundVars = expression.BoundVars.Select(v => v.tok.val);

            bob.Append(String.Join(", ", boundVars));

            bob.Append(" :: ");

            bob.Append(GenerateConditionString(expression.Term, rename));

            return(bob.ToString());
        }
        public string GenerateString(ForallExpr expression)
        {
            StringBuilder bob = new StringBuilder();

            bob.Append(expression.tok.val);
            bob.Append(" ");

            var boundVars = expression.BoundVars.Select(v => v.tok.val);

            bob.Append(String.Join(", ", boundVars));

            bob.Append(" :: ");

            bob.Append(GenerateString(expression.Term));

            return(bob.ToString());
        }
Esempio n. 13
0
        public void SimpleForAll()
        {
            var boundVar = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "foo", Microsoft.Boogie.Type.Bool));
            var id       = new IdentifierExpr(Token.NoToken, boundVar);
            var forall   = new ForallExpr(Token.NoToken, new List <Variable>()
            {
                boundVar
            }, id);

            var id2     = new IdentifierExpr(Token.NoToken, boundVar);
            var forall2 = new ForallExpr(Token.NoToken, new List <Variable>()
            {
                boundVar
            }, id2);

            Assert.AreNotSame(forall, forall2);                           // These are different references

            Assert.IsTrue(forall.Equals(forall2));                        // These are "structurally equal"
            Assert.AreEqual(forall.GetHashCode(), forall2.GetHashCode()); // If the .Equals() is true then hash codes must be the same
        }
Esempio n. 14
0
        public Expr ForAll(IList <Variable> freeVars, Expr body, Trigger triggers = null)
        {
            if (!body.Type.IsBool)
            {
                throw new ExprTypeCheckException("body must be of type bool");
            }

            if (freeVars.Count < 1)
            {
                throw new ArgumentException("ForAllExpr must have at least one free variable");
            }

            TypeCheckTriggers(freeVars, body, triggers);

            // Should we check the free variables are actually used? This could be quite expensive to do!
            var result = new ForallExpr(Token.NoToken, new List <Variable>(freeVars), triggers, body, Immutable);

            result.Type = BasicType.Bool;
            return(result);
        }
Esempio n. 15
0
 public override Expr VisitForallExpr(ForallExpr node)
 {
     return(node);
 }
Esempio n. 16
0
        public static Node CreateFromExpr(Expr expr)
        {
            if (expr is NAryExpr)
            {
                NAryExpr nary = expr as NAryExpr;
                if (nary.Fun is IfThenElse)
                {
                    Node one    = CreateFromExpr(nary.Args[0]);
                    Node two    = CreateFromExpr(nary.Args[1]);
                    Node three  = CreateFromExpr(nary.Args[2]);
                    Node parent = new TernaryNode(nary.Fun.FunctionName, one, two, three);
                    one.parent   = parent;
                    two.parent   = parent;
                    three.parent = parent;
                    return(parent);
                }
                else if (nary.Fun is BinaryOperator)
                {
                    Node one    = CreateFromExpr(nary.Args[0]);
                    Node two    = CreateFromExpr(nary.Args[1]);
                    Node parent = new BinaryNode(nary.Fun.FunctionName, one, two);
                    one.parent = parent;
                    two.parent = parent;
                    return(parent);
                }
                else if (nary.Fun is UnaryOperator)
                {
                    Node      one    = CreateFromExpr(nary.Args[0]);
                    UnaryNode parent = new UnaryNode(nary.Fun.FunctionName, one);
                    one.parent = parent;
                    return(parent);
                }
                else if (nary.Fun is FunctionCall)
                {
                    FunctionCall call = nary.Fun as FunctionCall;
                    if (nary.Args.Count == 1)
                    {
                        Node      one    = CreateFromExpr(nary.Args[0]);
                        UnaryNode parent = new UnaryNode(nary.Fun.FunctionName, one);
                        one.parent = parent;
                        return(parent);
                    }
                    else if (nary.Args.Count == 2)
                    {
                        Node one    = CreateFromExpr(nary.Args[0]);
                        Node two    = CreateFromExpr(nary.Args[1]);
                        Node parent = new BinaryNode(call.FunctionName, one, two);
                        one.parent = parent;
                        two.parent = parent;
                        return(parent);
                    }
                    else
                    {
                        Print.ExitMessage("Unhandled number of arguments in Boogie function call with function: " + nary.Fun.FunctionName);
                    }
                }
                else if (nary.Fun is MapSelect)
                {
                    List <Expr> indices = new List <Expr>();
                    while (true)
                    {
                        NAryExpr nary2 = nary.Args[0] as NAryExpr;
                        Print.ConditionalExitMessage(nary.Args.Count == 2, "Map select has more than two arguments");
                        indices.Insert(0, nary.Args[1]);
                        if (nary2 == null)
                        {
                            break;
                        }
                        else
                        {
                            nary = nary2;
                        }
                    }

                    IdentifierExpr identifier = nary.Args[0] as IdentifierExpr;
                    Node           parent     = new MapSymbolNode(identifier.Name);
                    foreach (Expr index in indices)
                    {
                        Node child = CreateFromExpr(index);
                        parent.Children.Add(child);
                        child.parent = parent;
                    }

                    return(parent);
                }
                else
                {
                    Print.ExitMessage("Unhandled Nary expression: " + nary.Fun.GetType().ToString());
                }
            }
            else if (expr is IdentifierExpr)
            {
                IdentifierExpr identifier = expr as IdentifierExpr;
                return(new ScalarSymbolNode(identifier.Name, identifier.Type));
            }
            else if (expr is LiteralExpr)
            {
                LiteralExpr literal = expr as LiteralExpr;
                if (literal.Val is BvConst)
                {
                    BvConst bv = (BvConst)literal.Val;
                    return(new LiteralNode(new BitVector(bv)));
                }
                else if (literal.Val is BigNum)
                {
                    BigNum num = (BigNum)literal.Val;
                    return(new LiteralNode(new BitVector(num.ToInt)));
                }
                else if (literal.Val is bool)
                {
                    bool boolean = (bool)literal.Val;
                    if (boolean)
                    {
                        return(new LiteralNode(BitVector.True));
                    }
                    else
                    {
                        return(new LiteralNode(BitVector.False));
                    }
                }
                else
                {
                    Print.ExitMessage("Unhandled literal expression: " + literal.ToString());
                }
            }
            else if (expr is BvExtractExpr)
            {
                BvExtractExpr bvExtract = expr as BvExtractExpr;
                Node          child     = CreateFromExpr(bvExtract.Bitvector);
                Node          parent    = new BVExtractNode(child, bvExtract.End, bvExtract.Start);
                child.parent = parent;
                return(parent);
            }
            else if (expr is BvConcatExpr)
            {
                BvConcatExpr bvConcat = expr as BvConcatExpr;
                Node         one      = CreateFromExpr(bvConcat.E0);
                Node         two      = CreateFromExpr(bvConcat.E1);
                Node         parent   = new BVConcatenationNode(one, two);
                one.parent = parent;
                two.parent = parent;
                return(parent);
            }
            else if (expr is ForallExpr)
            {
                ForallExpr forall = expr as ForallExpr;
                Node       one    = CreateFromExpr(forall._Body);
                Node       parent = new ForAllNode(one);
                one.parent = parent;
                return(parent);
            }

            Print.ExitMessage("Unhandled expression tree: " + expr.ToString() + " " + expr.Type.ToString());
            return(null);
        }
Esempio n. 17
0
 private static bool ShallowEq(ForallExpr expr1, ForallExpr expr2)
 {
     return(true);
 }
Esempio n. 18
0
 // group split quantifier by what triggers they got, and merged them back into one quantifier.
 private void CombineSplitQuantifier()
 {
     if (quantifiers.Count > 1)
     {
         List <QuantifierGroup> groups = new List <QuantifierGroup>();
         groups.Add(new QuantifierGroup(quantifiers[0], new List <ComprehensionExpr> {
             quantifiers[0].quantifier
         }));
         for (int i = 1; i < quantifiers.Count; i++)
         {
             bool found = false;
             for (int j = 0; j < groups.Count; j++)
             {
                 if (HasSameTriggers(quantifiers[i], groups[j].quantifier))
                 {
                     // belong to the same group
                     groups[j].expressions.Add(quantifiers[i].quantifier);
                     found = true;
                     break;
                 }
             }
             if (!found)
             {
                 // start a new group
                 groups.Add(new QuantifierGroup(quantifiers[i], new List <ComprehensionExpr> {
                     quantifiers[i].quantifier
                 }));
             }
         }
         if (groups.Count == quantifiers.Count)
         {
             // have the same number of splits, so no splits are combined.
             return;
         }
         // merge expressions in each group back to one quantifier.
         List <QuantifierWithTriggers> list   = new List <QuantifierWithTriggers>();
         List <Expression>             splits = new List <Expression>();
         foreach (var group in groups)
         {
             QuantifierWithTriggers q = group.quantifier;
             if (q.quantifier is ForallExpr)
             {
                 ForallExpr quantifier = (ForallExpr)q.quantifier;
                 Expression expr       = QuantifiersToExpression(quantifier.tok, BinaryExpr.ResolvedOpcode.And, group.expressions);
                 q.quantifier = new ForallExpr(quantifier.tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, expr, TriggerUtils.CopyAttributes(quantifier.Attributes))
                 {
                     Type = quantifier.Type, Bounds = quantifier.Bounds
                 };
             }
             else if (q.quantifier is ExistsExpr)
             {
                 ExistsExpr quantifier = (ExistsExpr)q.quantifier;
                 Expression expr       = QuantifiersToExpression(quantifier.tok, BinaryExpr.ResolvedOpcode.Or, group.expressions);
                 q.quantifier = new ExistsExpr(quantifier.tok, quantifier.TypeArgs, quantifier.BoundVars, quantifier.Range, expr, TriggerUtils.CopyAttributes(quantifier.Attributes))
                 {
                     Type = quantifier.Type, Bounds = quantifier.Bounds
                 };
             }
             list.Add(q);
             splits.Add(q.quantifier);
         }
         this.quantifiers = list;
         Contract.Assert(this.expr is QuantifierExpr); // only QuantifierExpr has SplitQuantifier
         ((QuantifierExpr)this.expr).SplitQuantifier = splits;
     }
 }
        public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq)
        {
            List <Cmd> newCmdSeq = new List <Cmd>();

            foreach (Cmd c in cmdSeq)
            {
                switch (Utils.getSlashVerifyCmdType(c))
                {
                case SlashVerifyCmdType.Store8:
                case SlashVerifyCmdType.Store16:
                case SlashVerifyCmdType.Store32:
                case SlashVerifyCmdType.Store64:     //mem := store(mem, y, e)
                {
                    Tuple <Variable, Expr, Expr> storeArgs = Utils.getStoreArgs(c as AssignCmd);
                    Expr      store_addr  = storeArgs.Item2;
                    Expr      store_value = storeArgs.Item3;
                    Expr      old_RSP     = new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP));
                    AssertCmd assertion;

                    Func <int, Expr> OffsetExpr = delegate(int n)
                    {
                        LiteralExpr x = new LiteralExpr(Token.NoToken, BigNum.FromInt(Math.Abs(n)), 64);
                        return(new NAryExpr(Token.NoToken,
                                            (n >= 0) ? new FunctionCall(plus_64) : new FunctionCall(minus_64),
                                            new List <Expr>()
                            {
                                storeArgs.Item2, x
                            }));
                    };

                    //Console.WriteLine("store to {0} at addr {1} with value {2}", storeArgs.Item1, storeArgs.Item2, storeArgs.Item3);
                    int iterations =
                        Utils.getSlashVerifyCmdType(c) == SlashVerifyCmdType.Store8 ? 1 :
                        Utils.getSlashVerifyCmdType(c) == SlashVerifyCmdType.Store16 ? 2 :
                        Utils.getSlashVerifyCmdType(c) == SlashVerifyCmdType.Store32 ? 4 : 8;

                    //instrument assert ((addrInStack(PLUS_64(t_a, 0bv64)) && GE_64(PLUS_64(t_a, 0bv64), old(RSP))) ==>
                    //    writable(mem,PLUS_64(t_a, 0bv64)) || writable(mem,MINUS_64(t_a, 8bv64))) && (addrInBitmap(PLUS_64(t_a, 0bv64)) ==>
                    //    LT_64(largestAddrAffected_8(mem, PLUS_64(t_a, 0bv64), t_v[8:0]), old(RSP - 8)));
                    Expr is_checkworthy_store = Expr.False;
                    foreach (int iter in new List <int>()
                        {
                            0, iterations - 1
                        }.Distinct())                                                              //disjunction over a, a+n-1
                    {
                        Expr addr_in_stack = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack),
                                                          new List <Expr>()
                            {
                                OffsetExpr(iter)
                            });
                        Expr addr_in_parent_frame = new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                                 new List <Expr>()
                            {
                                OffsetExpr(iter), old_RSP
                            });
                        Expr addr_not_in_backing_space = Expr.Not(Expr.And(
                                                                      new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                                                   new List <Expr>()
                            {
                                OffsetExpr(iter),
                                new NAryExpr(Token.NoToken,
                                             new FunctionCall(plus_64),
                                             new List <Expr>()
                                {
                                    old_RSP, new LiteralExpr(Token.NoToken, BigNum.FromInt(8), 64)
                                })
                            }),
                                                                      new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                                                   new List <Expr>()
                            {
                                OffsetExpr(iter),
                                new NAryExpr(Token.NoToken,
                                             new FunctionCall(plus_64),
                                             new List <Expr>()
                                {
                                    old_RSP, new LiteralExpr(Token.NoToken, BigNum.FromInt(40), 64)
                                })
                            })));
                        is_checkworthy_store = Expr.Or(is_checkworthy_store, Expr.And(addr_in_stack, Expr.And(addr_not_in_backing_space, addr_in_parent_frame)));
                    }
                    //Fix for the padding issue. Enough to check writability of (addr + 0). It's an invariant that /guard:cfw maintains
                    Expr is_writable = new NAryExpr(Token.NoToken, new FunctionCall(writable),
                                                    new List <Expr>()
                        {
                            new IdentifierExpr(Token.NoToken, mem_bitmap), OffsetExpr(0)
                        });
                    Expr check_for_stack_store = Expr.Imp(is_checkworthy_store, is_writable);
                    assertion = new AssertCmd(Token.NoToken, check_for_stack_store);
                    newCmdSeq.Add(assertion);
                    VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, Utils.getSlashVerifyCmdType(c));

                    for (int iter = 0; iter < iterations; iter++)
                    {
                        Expr addr_in_bitmap = new NAryExpr(Token.NoToken, new FunctionCall(addrInBitmap),
                                                           new List <Expr>()
                            {
                                OffsetExpr(iter)
                            });
                        Expr largest_addr_affected = new NAryExpr(Token.NoToken, new FunctionCall(largestAddrAffected_8),
                                                                  new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, mem_bitmap), OffsetExpr(iter),
                                new BvExtractExpr(Token.NoToken, store_value, 8 * (iter + 1), 8 * iter)
                            });
                        //Expr addr_in_own_frame = new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                        //    new List<Expr>() { largest_addr_affected, old_RSP }); //Not using this because of padding issue
                        Expr largest_allowed_address = new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                                                    new List <Expr>()
                            {
                                old_RSP, new LiteralExpr(Token.NoToken, BigNum.FromInt(8), 64)
                            });
                        Expr addr_in_own_frame = new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                              new List <Expr>()
                            {
                                largest_addr_affected, largest_allowed_address
                            });
                        if (this.bound_stacksize_option)
                        {
                            Utils.Assert(this.bound_stacksize_offset % 8 == 0, "Need stack size estimate to be a multiple of 8");
                            Expr smallest_addr_affected = new NAryExpr(Token.NoToken, new FunctionCall(smallestAddrAffected_8),
                                                                       new List <Expr>()
                                {
                                    new IdentifierExpr(Token.NoToken, mem_bitmap), OffsetExpr(iter),
                                    new BvExtractExpr(Token.NoToken, store_value, 8 * (iter + 1), 8 * iter)
                                });
                            Expr smallest_allowed_address = new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                                                         new List <Expr>()
                                {
                                    old_RSP, new LiteralExpr(Token.NoToken, BigNum.FromInt(this.bound_stacksize_offset), 64)
                                });
                            addr_in_own_frame = Expr.And(addr_in_own_frame,
                                                         new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                                      new List <Expr>()
                                {
                                    smallest_addr_affected, smallest_allowed_address
                                }));
                        }

                        Expr any_addr_affected = new NAryExpr(Token.NoToken, new FunctionCall(anyAddrAffected_8),
                                                              new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, mem_bitmap), OffsetExpr(iter),
                                new BvExtractExpr(Token.NoToken, store_value, 8 * (iter + 1), 8 * iter)
                            });
                        Expr value_not_zero = Expr.Neq(new BvExtractExpr(Token.NoToken, store_value, 8 * (iter + 1), 8 * iter),
                                                       new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 8));

                        Expr check_for_bitmap_store = Expr.Imp(Expr.And(Expr.And(addr_in_bitmap, any_addr_affected), value_not_zero), addr_in_own_frame);

                        assertion = new AssertCmd(Token.NoToken, check_for_bitmap_store);
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, Utils.getSlashVerifyCmdType(c));
                    }

                    if (Options.confidentiality)
                    {
                        Expr addr_in_U =
                            Expr.And(
                                Expr.And(
                                    new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(0), new IdentifierExpr(Token.NoToken, this.stack_low)
                            }),
                                    new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(0), new IdentifierExpr(Token.NoToken, this.bitmap_high)
                            })),
                                Expr.And(
                                    new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(iterations - 1), new IdentifierExpr(Token.NoToken, this.stack_low)
                            }),
                                    new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(iterations - 1), new IdentifierExpr(Token.NoToken, this.bitmap_high)
                            }))
                                );

                        Expr _data_low    = new LiteralExpr(Token.NoToken, BigNum.FromInt(Int32.Parse(Options.dataLow.ToUpper(), System.Globalization.NumberStyles.HexNumber)), 64);
                        Expr _data_high   = new LiteralExpr(Token.NoToken, BigNum.FromInt(Int32.Parse(Options.dataHigh.ToUpper(), System.Globalization.NumberStyles.HexNumber)), 64);
                        Expr addr_in_Data =
                            Expr.And(
                                Expr.And(
                                    new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(0), _data_low
                            }),
                                    new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(0), _data_high
                            })),
                                Expr.And(
                                    new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(iterations - 1), _data_low
                            }),
                                    new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                 new List <Expr>()
                            {
                                OffsetExpr(iterations - 1), _data_high
                            }))
                                );

                        assertion = new AssertCmd(Token.NoToken, Expr.Or(addr_in_U, addr_in_Data));
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, Utils.getSlashVerifyCmdType(c));
                    }

                    break;
                }

                case SlashVerifyCmdType.RepStosB:     //x := REP_STOSB(mem, e1, e2, e3)
                {
                    //TODO: might want to assert that it writes to the bitmap
                    //if its writing zeros to bitmap, we dont need to assert anything
                    break;
                }

                case SlashVerifyCmdType.SetRSP:
                {
                    Expr alignment = Expr.Eq(new BvExtractExpr(Token.NoToken, (c as AssignCmd).Rhss[0], 3, 0),
                                             new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 3));
                    Expr le_old_RSP = new NAryExpr(Token.NoToken, new FunctionCall(le_64),
                                                   new List <Expr>()
                        {
                            (c as AssignCmd).Rhss[0], new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP))
                        });
                    AssertCmd assertion = new AssertCmd(Token.NoToken, Expr.And(alignment, le_old_RSP));
                    newCmdSeq.Add(assertion);
                    VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.SetRSP);

                    break;
                }

                case SlashVerifyCmdType.Ret:
                {
                    foreach (AssertCmd a in RemoteTransferAssertions())
                    {
                        newCmdSeq.Add(a);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, a, SlashVerifyCmdType.Ret);
                    }
                    break;
                }

                case SlashVerifyCmdType.Call:
                {
                    AssertCmd assertion;

                    string attribute_calltarget = QKeyValue.FindStringAttribute((c as AssertCmd).Attributes, "SlashVerifyCallTarget");
                    Utils.Assert(attribute_calltarget != null, "Expected SlashVerifyCallTarget attribute on call");

                    //assert policy(target);
                    Expr is_policy;
                    if (attribute_calltarget.Substring(0, 2).Equals("0x"))
                    {
                        int target = Int32.Parse(attribute_calltarget.ToUpper().Substring(2), System.Globalization.NumberStyles.HexNumber);
                        is_policy = new NAryExpr(Token.NoToken, new FunctionCall(policy),
                                                 new List <Expr>()
                            {
                                new LiteralExpr(Token.NoToken, BigNum.FromInt(target), 64)
                            });
                    }
                    else
                    {
                        //indirect call e.g. call rax
                        //first find which register
                        GlobalVariable target = this.globals.FirstOrDefault(v => v.Name.Equals(attribute_calltarget));
                        Utils.Assert(target != null, "Could not find " + attribute_calltarget);
                        is_policy = new NAryExpr(Token.NoToken, new FunctionCall(policy),
                                                 new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, target)
                            });
                    }

                    if (!Options.disablePolicyChecking)
                    {
                        assertion = new AssertCmd(Token.NoToken, is_policy);
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.Call);
                    }

                    if (!this.bound_stacksize_option)
                    {
                        //forall i. i < (rsp - 8) ==> ¬writable(mem,i) //rsp - 8 holds return address, and everything below that must start off as non writable
                        BoundVariable i = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "i", this.mem.TypedIdent.Type.AsMap.Arguments[0]));
                        NAryExpr      in_local_frame = new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                                    new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, i),
                                new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                             new List <Expr>()
                                {
                                    new IdentifierExpr(Token.NoToken, RSP),
                                    new LiteralExpr(Token.NoToken, BigNum.FromInt(8), 64)
                                })
                            });
                        NAryExpr in_stack = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, i)
                            });
                        Expr not_writable = Expr.Not(new NAryExpr(Token.NoToken, new FunctionCall(writable),
                                                                  new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, this.mem_bitmap), new IdentifierExpr(Token.NoToken, i)
                            }));
                        Expr assert_mem_false_expr = new ForallExpr(Token.NoToken, new List <Variable>()
                            {
                                i
                            }, Expr.Imp(Expr.And(in_stack, in_local_frame), not_writable));
                        assertion = new AssertCmd(Token.NoToken, assert_mem_false_expr);
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.Call);

                        //assert !writable(mem, rsp-8)
                        not_writable = Expr.Not(new NAryExpr(Token.NoToken, new FunctionCall(writable),
                                                             new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, this.mem_bitmap),
                                new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                             new List <Expr>()
                                {
                                    new IdentifierExpr(Token.NoToken, RSP),
                                    new LiteralExpr(Token.NoToken, BigNum.FromInt(8), 64)
                                })
                            }));
                        assertion = new AssertCmd(Token.NoToken, not_writable);
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.Call);
                    }
                    else
                    {
                        //assert that RSP is not lower than bound_stacksize_offset. if RSP has not gotten lower, than we know everything is writable below
                        Expr smallest_allowed_address = new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                                                     new List <Expr>()
                            {
                                new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP)),
                                new LiteralExpr(Token.NoToken, BigNum.FromInt(this.bound_stacksize_offset), 64)
                            });

                        NAryExpr rsp_in_local_frame = new NAryExpr(Token.NoToken, new FunctionCall(le_64),
                                                                   new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, RSP), smallest_allowed_address
                            });
                        assertion = new AssertCmd(Token.NoToken, rsp_in_local_frame);
                        newCmdSeq.Add(assertion);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.Call);
                    }

                    //assert RSP <= (old(RSP) - 32)
                    NAryExpr stack_backing_space = new NAryExpr(Token.NoToken, new FunctionCall(le_64),
                                                                new List <Expr>()
                        {
                            new IdentifierExpr(Token.NoToken, RSP),
                            new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                         new List <Expr>()
                            {
                                new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP)),
                                new LiteralExpr(Token.NoToken, BigNum.FromInt(32), 64)
                            })
                        });
                    assertion = new AssertCmd(Token.NoToken, stack_backing_space);
                    newCmdSeq.Add(assertion);
                    VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.Call);

                    break;
                }

                case SlashVerifyCmdType.RemoteJmp:
                case SlashVerifyCmdType.RemoteIndirectJmp:
                {
                    //assert policy(target);
                    Expr is_policy = Expr.False;
                    if (Utils.getSlashVerifyCmdType(c) == SlashVerifyCmdType.RemoteJmp)
                    {
                        string attribute_jmptarget = QKeyValue.FindStringAttribute((c as AssertCmd).Attributes, "SlashVerifyJmpTarget");
                        Utils.Assert(attribute_jmptarget != null, "Expected SlashVerifyJmpTarget attribute on jmp");

                        int target = Int32.Parse(attribute_jmptarget.ToUpper().Substring(2), System.Globalization.NumberStyles.HexNumber);
                        is_policy = new NAryExpr(Token.NoToken, new FunctionCall(policy),
                                                 new List <Expr>()
                            {
                                new LiteralExpr(Token.NoToken, BigNum.FromInt(target), 64)
                            });
                    }
                    else if (Utils.getSlashVerifyCmdType(c) == SlashVerifyCmdType.RemoteIndirectJmp)
                    {
                        string attribute_jmpregister = QKeyValue.FindStringAttribute((c as AssertCmd).Attributes, "SlashVerifyJmpRegister");
                        Utils.Assert(attribute_jmpregister != null, "Exprected jmp register annotation on indirect jump");
                        GlobalVariable global_register = this.globals.FirstOrDefault(x => x.Name.Equals(attribute_jmpregister));
                        Utils.Assert(global_register != null, "Could not find global variable " + attribute_jmpregister);

                        is_policy = new NAryExpr(Token.NoToken, new FunctionCall(policy),
                                                 new List <Expr>()
                            {
                                new IdentifierExpr(Token.NoToken, global_register)
                            });
                    }

                    AssertCmd assertion = new AssertCmd(Token.NoToken, is_policy);
                    newCmdSeq.Add(assertion);
                    VCSplitter.Instance.RecordAssertion(this.current_label, c, assertion, SlashVerifyCmdType.RemoteJmp);

                    foreach (AssertCmd a in RemoteTransferAssertions())
                    {
                        newCmdSeq.Add(a);
                        VCSplitter.Instance.RecordAssertion(this.current_label, c, a, SlashVerifyCmdType.RemoteJmp);
                    }

                    break;
                }
                }

                //The assert gets placed prior to the original command
                newCmdSeq.Add(c);
            }

            return(base.VisitCmdSeq(newCmdSeq));
        }
 public virtual void Visit(ForallExpr forAllExpression)
 {
     VisitNullableAttributes(forAllExpression.Attributes);
     VisitNullableExpression(forAllExpression.Range);
     Visit(forAllExpression.Term);
 }
        //assertions for remote jumps and return instructions
        public List <AssertCmd> RemoteTransferAssertions()
        {
            List <AssertCmd> assertions = new List <AssertCmd>();

            if (this.bound_stacksize_option && Options.instantiateQuantifiers) //can only instantiate quantifiers on bounded
            {
                Expr instantiation = Expr.True;
                int  addr_offset   = 8;
                while (addr_offset <= (this.bound_stacksize_offset))
                {
                    Expr addr = new NAryExpr(Token.NoToken, new FunctionCall(this.minus_64),
                                             new List <Expr>()
                    {
                        new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP)),
                        new LiteralExpr(Token.NoToken, BigNum.FromInt(addr_offset), 64)
                    });
                    Expr addr_not_writable = Expr.Not(new NAryExpr(Token.NoToken, new FunctionCall(writable),
                                                                   new List <Expr>()
                    {
                        new IdentifierExpr(Token.NoToken, mem_bitmap), addr
                    }));
                    //instantiation = Expr.And(instantiation, addr_not_writable);
                    Expr precondition =
                        Expr.And(Expr.Eq(new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP), 3, 0), new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 3)),
                                 Expr.Eq(new IdentifierExpr(Token.NoToken, RSP), new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP))));
                    assertions.Add(new AssertCmd(Token.NoToken,
                                                 Expr.Imp(precondition, addr_not_writable),
                                                 new QKeyValue(Token.NoToken, "return_instrumentation", new List <object> {
                        addr
                    }, null)));

                    addr_offset += 8;
                }
            }
            else
            {
                //forall i. i < old(rsp) && i[3:0] == 0bv3 ==> ¬writable(mem,i)
                BoundVariable i = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "i", this.mem.TypedIdent.Type.AsMap.Arguments[0]));
                Expr          in_local_frame = new NAryExpr(Token.NoToken, new FunctionCall(lt_64),
                                                            new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, i), new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP))
                });
                if (this.bound_stacksize_option)
                {
                    Expr smallest_allowed_address = new NAryExpr(Token.NoToken, new FunctionCall(minus_64),
                                                                 new List <Expr>()
                    {
                        new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP)),
                        new LiteralExpr(Token.NoToken, BigNum.FromInt(this.bound_stacksize_offset), 64)
                    });
                    in_local_frame = Expr.And(in_local_frame,
                                              new NAryExpr(Token.NoToken, new FunctionCall(ge_64),
                                                           new List <Expr>()
                    {
                        new IdentifierExpr(Token.NoToken, i), smallest_allowed_address
                    }));
                }
                NAryExpr in_stack = new NAryExpr(Token.NoToken, new FunctionCall(addrInStack), new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, i)
                });
                Expr aligned = Expr.Eq(new BvExtractExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, i), 3, 0),
                                       new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 3));
                Expr not_writable = Expr.Not(new NAryExpr(Token.NoToken, new FunctionCall(writable),
                                                          new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, this.mem_bitmap), new IdentifierExpr(Token.NoToken, i)
                }));
                Expr assert_mem_false_expr = new ForallExpr(Token.NoToken, new List <Variable>()
                {
                    i
                },
                                                            Expr.Imp(Expr.And(Expr.And(in_local_frame, in_stack), aligned), not_writable));
                assertions.Add(new AssertCmd(Token.NoToken, assert_mem_false_expr));
            }


            //rsp == old(rsp)
            assertions.Add(new AssertCmd(Token.NoToken, Expr.Eq(new IdentifierExpr(Token.NoToken, RSP),
                                                                new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, RSP)))));

            return(assertions);
        }
Esempio n. 22
0
 public Expr VisitForallExpr(ForallExpr e)
 {
     return(PrintQuantifierExpr(e));
 }
Esempio n. 23
0
 public override Expr VisitForallExpr(ForallExpr node)
 {
     add(node);
     return(base.VisitForallExpr(node));
 }
Esempio n. 24
0
        public static Expr EmitEq(IdentifierExpr leftVar, IdentifierExpr rightVar, HashSet <Variable> ignoreSet)
        {
            // just blocking poly map for now - hemr
            if (!(leftVar.Decl.TypedIdent.Type is MapType || leftVar.Decl.TypedIdent.Type is TypeSynonymAnnotation))
            {
                return(Expr.Eq(leftVar, rightVar));
            }

            if (leftVar.Decl.TypedIdent.Type is TypeSynonymAnnotation)
            {
                var l = leftVar.Decl.TypedIdent.Type as TypeSynonymAnnotation;
                System.Diagnostics.Debug.Assert(!l.IsMap, "only handle non map typesynonymAnnotations, found " + l);
                return(Expr.Eq(leftVar, rightVar));
            }


            List <Variable> bound = null;

            BoundVariable[] bvs         = new BoundVariable[leftVar.Decl.TypedIdent.Type.AsMap.Arguments.Count];
            int             i           = 0;
            string          polyMapName = "";

            foreach (Microsoft.Boogie.Type ts in leftVar.Decl.TypedIdent.Type.AsMap.Arguments)
            {
                if (leftVar.Decl.TypedIdent.Type is TypeSynonymAnnotation)
                {
                    int index = 0;
                    index = ts.ToString().IndexOf(" ");
                    if (index >= 0)
                    {
                        polyMapName = ts.ToString().Substring(index + 1);
                    }
                }
                bound = new List <Variable>();
                var x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_x" + i, ts));
                // bound.Add(x);
                bvs[i] = x;
                i++;
            }

            //var bound = new List<Variable>();
            //var x = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_x", leftVar.Decl.TypedIdent.Type.AsMap.Arguments[0]));
            //bound.Add(x);

            //var lhs = SelectExpr(leftVar, Expr.Ident(x).);
            //var rhs = SelectExpr(rightVar, Expr.Ident(x));
            IdentifierExpr[] idenExprs = new IdentifierExpr[bvs.Length];
            for (int j = 0; j < bvs.Length; j++)
            {
                BoundVariable bv = bvs[j];
                idenExprs[j] = Expr.Ident(bv);
            }

            var lhs = SelectExpr(leftVar, idenExprs);
            var rhs = SelectExpr(rightVar, idenExprs);

            bound = new List <Variable>(bvs);
            if (!polyMapName.Equals(""))
            {
                var forall = new ForallExpr(Token.NoToken, new List <TypeVariable>(new TypeVariable[] { new TypeVariable(Token.NoToken, polyMapName) }), bound, Expr.Eq(lhs, rhs));
                //var forall2 = new ForallExpr(Token.NoToken, new List<TypeVariable>(new TypeVariable(Token.NoToken, polyMapName)), bound, Expr.Eq(lhs, rhs));
                //return Expr.Or(Expr.Eq(leftVar, rightVar), forall);
                // as mentioned... blocking poly maps for now - hemr
                return(Expr.Eq(leftVar, rightVar));
            }
            else
            {
                return(Expr.Or(Expr.Eq(leftVar, rightVar), new ForallExpr(Token.NoToken, bound, Expr.Eq(lhs, rhs))));
            }
            //bound = new List<Variable>(bvs);
            //return Expr.Or(Expr.Eq(leftVar, rightVar), new ForallExpr(Token.NoToken, bound, Expr.Eq(lhs, rhs)));
            //return Expr.True;
        }
Esempio n. 25
0
        public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq)
        {
            List <Cmd> newCmdSeq = new List <Cmd>();

            if (this.currentLabel == this.memCheckpointLabel)
            {
                //mem_oldbitmap := mem
                AssignCmd ac = new AssignCmd(Token.NoToken, new List <AssignLhs>()
                {
                    new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, this.mem_oldbitmap))
                },
                                             new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, this.mem_bitmap)
                });
                newCmdSeq.Add(ac);
            }
            else if (this.loopHeaderLabels.Contains(this.currentLabel))
            {
                //assert (forall i: bv64 :: addrInBitmap(i) ==> mem[i] == mem_oldbitmap[i]);
                BoundVariable i         = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "i", this.mem.TypedIdent.Type.AsMap.Arguments[0]));
                Expr          in_bitmap = new NAryExpr(Token.NoToken, new FunctionCall(this.addrInBitmap), new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, i)
                });

                Expr assert_expr;
                Expr mem_bitmap_of_i = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
                                                    new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, this.mem_bitmap),
                    new IdentifierExpr(Token.NoToken, i)
                });
                Expr mem_oldbitmap_of_i = new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
                                                       new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, this.mem_oldbitmap),
                    new IdentifierExpr(Token.NoToken, i)
                });
                assert_expr = new ForallExpr(Token.NoToken, new List <Variable>()
                {
                    i
                }, Expr.Imp(in_bitmap, Expr.Eq(mem_bitmap_of_i, mem_oldbitmap_of_i)));
                //for Houdini
                Constant existential = this.existentials.Dequeue();
                assert_expr = Expr.Imp(new IdentifierExpr(Token.NoToken, existential), assert_expr);
                newCmdSeq.Add(new AssertCmd(Token.NoToken, assert_expr));

                //assert (LOAD_LE_64(mem, _guard_writeTable_ptr) == _bitmap_low);
                Expr load_mem_guardptr = new NAryExpr(Token.NoToken, new FunctionCall(this.load_64), new List <Expr>()
                {
                    new IdentifierExpr(Token.NoToken, this.mem),
                    new IdentifierExpr(Token.NoToken, this._guard_writeTable_ptr)
                });
                assert_expr = Expr.Eq(load_mem_guardptr, new IdentifierExpr(Token.NoToken, _bitmap_low));
                //for Houdini
                existential = this.existentials.Dequeue();
                assert_expr = Expr.Imp(new IdentifierExpr(Token.NoToken, existential), assert_expr);
                newCmdSeq.Add(new AssertCmd(Token.NoToken, assert_expr));
            }
            newCmdSeq.AddRange(cmdSeq);
            return(base.VisitCmdSeq(newCmdSeq));
        }
Esempio n. 26
0
 public override Expr VisitForallExpr(ForallExpr node)
 {
     return(base.VisitForallExpr((ForallExpr)node.Clone()));
 }
Esempio n. 27
0
        public override Expression Substitute(Expression expr)
        {
            if (TryGetExprSubst(expr, out var ie))
            {
                Contract.Assert(ie != null);
                return(ie);
            }
            if (expr is QuantifierExpr e)
            {
                var newAttrs  = SubstAttributes(e.Attributes);
                var newRange  = e.Range == null ? null : Substitute(e.Range);
                var newTerm   = Substitute(e.Term);
                var newBounds = SubstituteBoundedPoolList(e.Bounds);
                if (newAttrs == e.Attributes && newRange == e.Range && newTerm == e.Term && newBounds == e.Bounds)
                {
                    return(e);
                }

                var newBoundVars = new List <BoundVar>(e.BoundVars);
                if (newBounds == null)
                {
                    newBounds = new List <ComprehensionExpr.BoundedPool>();
                }
                else if (newBounds == e.Bounds)
                {
                    // create a new list with the same elements, since the .Add operations below would otherwise add elements to the original e.Bounds
                    newBounds = new List <ComprehensionExpr.BoundedPool>(newBounds);
                }

                // conjoin all the new equalities to the range of the quantifier
                foreach (var entry in usedSubstMap)
                {
                    var eq = new BinaryExpr(e.tok, BinaryExpr.ResolvedOpcode.EqCommon, entry.Item2, entry.Item1);
                    newRange = newRange == null ? eq : new BinaryExpr(e.tok, BinaryExpr.ResolvedOpcode.And, eq, newRange);
                    newBoundVars.Add((BoundVar)entry.Item2.Var);
                    newBounds.Add(new ComprehensionExpr.ExactBoundedPool(entry.Item1));
                }

                QuantifierExpr newExpr;
                if (expr is ForallExpr)
                {
                    newExpr = new ForallExpr(e.tok, e.TypeArgs, newBoundVars, newRange, newTerm, newAttrs)
                    {
                        Bounds = newBounds
                    };
                }
                else
                {
                    Contract.Assert(expr is ExistsExpr);
                    newExpr = new ExistsExpr(e.tok, e.TypeArgs, newBoundVars, newRange, newTerm, newAttrs)
                    {
                        Bounds = newBounds
                    };
                }
                usedSubstMap.Clear();

                newExpr.Type = expr.Type;
                return(newExpr);
            }
            return(base.Substitute(expr));
        }
Esempio n. 28
0
    public RtlExp GhostExpressionRec(Expression exp, bool inRecSpec = false, bool inRequiresOrOld = false)
    {
        Util.Assert(!isPrinting);
        exp = GetExp(exp);
        StmtExpr         stmtExpr    = exp as StmtExpr;
        IdentifierExpr   idExp       = exp as IdentifierExpr;
        LiteralExpr      literal     = exp as LiteralExpr;
        BinaryExpr       binary      = exp as BinaryExpr;
        UnaryExpr        unary       = exp as UnaryExpr;
        ITEExpr          ite         = exp as ITEExpr;
        ExistsExpr       existsExp   = exp as ExistsExpr;
        ForallExpr       forallExp   = exp as ForallExpr;
        LetExpr          letExp      = exp as LetExpr;
        MatchExpr        matchExp    = exp as MatchExpr;
        OldExpr          oldExp      = exp as OldExpr;
        FreshExpr        freshExp    = exp as FreshExpr;
        FunctionCallExpr funCall     = exp as FunctionCallExpr;
        DatatypeValue    dataVal     = exp as DatatypeValue;
        FieldSelectExpr  fieldSelect = exp as FieldSelectExpr;
        SeqSelectExpr    seqSelect   = exp as SeqSelectExpr;
        SeqUpdateExpr    seqUpdate   = exp as SeqUpdateExpr;
        SeqDisplayExpr   seqDisplay  = exp as SeqDisplayExpr;

        Func <Expression, RtlExp> G = e => GhostExpression(e, inRecSpec, inRequiresOrOld);

        if (stmtExpr != null)
        {
            if (stmtExprEnabled)
            {
                if (ignoreStmtExpr == 0)
                {
                    AddGhostStatement(stmtExpr.S);
                }
                return(G(stmtExpr.E));
            }
            else
            {
                throw new Exception("not implemented: cannot handle statement expression here");
            }
        }
        else if (idExp != null)
        {
            return(AsVar(idExp));
        }
        else if (literal != null && literal.Value is BigInteger)
        {
            return(new RtlInt((BigInteger)(literal.Value)));
        }
        else if (literal != null && literal.Value is bool)
        {
            return(new RtlLiteral((bool)(literal.Value) ? "true" : "false"));
        }
        else if (literal != null && literal.Value == null)
        {
            return(new RtlLiteral("ArrayOfInt(0 - 1, NO_ABS)"));
        }
        else if (literal != null && literal.Value is Microsoft.Basetypes.BigDec)
        {
            return(new RtlLiteral(((Microsoft.Basetypes.BigDec)literal.Value).ToDecimalString()));
        }
        else if (binary != null)
        {
            string          op              = null;
            string          internalOp      = null;
            CompileFunction compileFunction = this as CompileFunction;
            string          thisFuncName    = (compileFunction == null) ? null : compileFunction.function.Name;
            switch (binary.ResolvedOp)
            {
            case BinaryExpr.ResolvedOpcode.SeqEq:
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"),
                                    new RtlExp[] { G(binary.E0), G(binary.E1) }));

            case BinaryExpr.ResolvedOpcode.SeqNeq:
                return(new RtlLiteral("(!" +
                                      new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"),
                                                   new RtlExp[] { G(binary.E0), G(binary.E1) }) + ")"));

            case BinaryExpr.ResolvedOpcode.Concat:
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.Type), "Seq_Append"),
                                    new RtlExp[] { G(binary.E0), G(binary.E1) }));
            }
            if (binary.Op == BinaryExpr.Opcode.Exp)
            {
                binary = new BinaryExpr(binary.tok, BinaryExpr.Opcode.Imp, binary.E0, binary.E1);
            }
            switch (binary.Op)
            {
            case BinaryExpr.Opcode.Disjoint:
            case BinaryExpr.Opcode.In:
            case BinaryExpr.Opcode.NotIn:
                throw new Exception("not implemented: binary operator '" + BinaryExpr.OpcodeString(binary.Op) + "'");
            }
            if (AppType(binary.E0.Type) is IntType && AppType(binary.E1.Type) is IntType)
            {
                switch (binary.Op)
                {
                case BinaryExpr.Opcode.Le: internalOp = "INTERNAL_le_boogie"; break;

                case BinaryExpr.Opcode.Lt: internalOp = "INTERNAL_lt_boogie"; break;

                case BinaryExpr.Opcode.Ge: internalOp = "INTERNAL_ge_boogie"; break;

                case BinaryExpr.Opcode.Gt: internalOp = "INTERNAL_gt_boogie"; break;

                case BinaryExpr.Opcode.Add: internalOp = "INTERNAL_add_boogie"; break;

                case BinaryExpr.Opcode.Sub: internalOp = "INTERNAL_sub_boogie"; break;

                case BinaryExpr.Opcode.Mul:
                    op = "*";
                    if (thisFuncName != "INTERNAL_mul")
                    {
                        internalOp = FunName("INTERNAL__mul");
                    }
                    break;

                case BinaryExpr.Opcode.Div:
                    op = "div";
                    if (thisFuncName != "INTERNAL_div")
                    {
                        internalOp = FunName("INTERNAL__div");
                    }
                    break;

                case BinaryExpr.Opcode.Mod:
                    op = "mod";
                    if (thisFuncName != "INTERNAL_mod")
                    {
                        internalOp = FunName("INTERNAL__mod");
                    }
                    break;

                default:
                    op = BinaryExpr.OpcodeString(binary.Op);
                    break;
                }
            }
            else
            {
                op = BinaryExpr.OpcodeString(binary.Op);
            }
            if (internalOp == null)
            {
                return(new RtlBinary(op, G(binary.E0), G(binary.E1)));
            }
            else
            {
                return(new RtlApply(internalOp, new RtlExp[]
                                    { G(binary.E0), G(binary.E1) }));
            }
        }
        else if (unary != null && unary.Op == UnaryExpr.Opcode.Not)
        {
            return(new RtlLiteral("(!(" + G(unary.E) + "))"));
        }
        else if (unary != null && unary.Op == UnaryExpr.Opcode.SeqLength)
        {
            return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(unary.E.Type), "Seq_Length"),
                                new RtlExp[] { G(unary.E) }));
        }
        else if (ite != null)
        {
            return(GhostIfThenElse(G(ite.Test), () => G(ite.Thn), () => G(ite.Els)));
        }
        else if (funCall != null)
        {
            switch (funCall.Function.Name)
            {
            case "left":
            case "right":
            case "relation":
            case "public":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply(funCall.Function.Name, new RtlExp[] { G(funCall.Args[0]) }));

            case "sizeof":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply(funCall.Function.Name + "##" + TypeString(AppType(funCall.Args[0].Type)),
                                    new RtlExp[] { G(funCall.Args[0]) }));

            case "INTERNAL_add_raw":
                Util.Assert(funCall.Args.Count == 2);
                return(new RtlBinary("+", G(funCall.Args[0]), G(funCall.Args[1])));

            case "INTERNAL_sub_raw":
                Util.Assert(funCall.Args.Count == 2);
                return(new RtlBinary("-", G(funCall.Args[0]), G(funCall.Args[1])));

            case "IntToReal":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply("real", new RtlExp[] { G(funCall.Args[0]) }));

            case "RealToInt":
                Util.Assert(funCall.Args.Count == 1);
                return(new RtlApply("int", new RtlExp[] { G(funCall.Args[0]) }));
            }
            TypeApply app = dafnySpec.Compile_Function(funCall.Function,
                                                       funCall.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value)));
            string        name     = FunName(SimpleName(app.AppName()));
            string        fullName = FunName(SimpleName(app.AppFullName()));
            List <RtlExp> rtlArgs  = funCall.Args.Select(G).ToList();
            List <RtlExp> rtlReads = funCall.Function.Reads.Where(e => e.Field != null).ToList()
                                     .ConvertAll(e => (RtlExp) new RtlVar(
                                                     GhostVar(e.FieldName), e.Field.IsGhost, AppType(e.Field.Type)));
            rtlArgs = rtlReads.Concat(rtlArgs).ToList();
            if (name.EndsWith("__INTERNAL__HEAP"))
            {
                name = name.Substring(0, name.Length - "__INTERNAL__HEAP".Length);
            }
            else if (DafnySpec.IsHeapFunction(funCall.Function))
            {
                rtlArgs.Insert(0, new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"));
            }
            if (Attributes.Contains(funCall.Function.Attributes, "opaque") &&
                funCall.Function.Formals.Count + rtlReads.Count == 0)
            {
                rtlArgs.Insert(0, new RtlLiteral("true"));
            }
            if (fullName == recFunName)
            {
                name = fullName;
            }
            if (name == recFunName)
            {
                recCalls.Add(new List <RtlExp>(rtlArgs));
                rtlArgs.Insert(0, new RtlApply("decreases_" + name, new List <RtlExp>(rtlArgs)));
                rtlArgs.Insert(1, new RtlLiteral(inRecSpec ? "__unroll" : "__unroll + 1"));
                name = "rec_" + name;
            }
            return(new RtlApply(name, rtlArgs));
        }
        else if (dataVal != null)
        {
            bool isSeq = dataVal.Type.TypeName(null).StartsWith("Seq<");
            return(new RtlApply((isSeq ? "_" : "") + dafnySpec.Compile_Constructor(
                                    dataVal.Type, dataVal.Ctor.Name, dataVal.InferredTypeArgs, typeApply.typeArgs).AppName(),
                                dataVal.Arguments.Select(G)));
        }
        else if (existsExp != null || forallExp != null)
        {
            QuantifierExpr qExp               = (QuantifierExpr)exp;
            bool           isForall           = forallExp != null;
            var            varTuples          = qExp.BoundVars.Select(v => Tuple.Create(GhostVar(v.Name), v.IsGhost, v.Type));
            var            oldRenamer         = PushRename(qExp.BoundVars.Select(v => v.Name));
            var            oldStmtExprEnabled = stmtExprEnabled;
            stmtExprEnabled = false;
            RtlExp rExp = new RtlLiteral((isForall ? "(forall " : "(exists ")
                                         + string.Join(", ", qExp.BoundVars.Select(v => GhostVar(v.Name) + ":" + TypeString(AppType(v.Type))))
                                         + " :: " + Triggers(qExp.Attributes, G) + " "
                                         + GetTypeWellFormedExp(varTuples.ToList(), isForall ? "==>" : "&&", G(qExp.Term)) + ")");
            stmtExprEnabled = oldStmtExprEnabled;
            PopRename(oldRenamer);
            return(rExp);
        }
        else if (letExp != null)
        {
            List <RtlExp> rhss;
            if (letExp.Exact)
            {
                rhss = letExp.RHSs.ConvertAll(e => G(e));
            }
            else if (letExp.LHSs.Count == 1 && LiteralExpr.IsTrue(letExp.RHSs[0]) && AppType(letExp.LHSs[0].Var.Type) is IntType)
            {
                rhss = new List <RtlExp> {
                    new RtlLiteral("0")
                };
            }
            else
            {
                throw new Exception("not implemented: LetExpr: " + letExp);
            }
            return(GhostLet(exp.tok, letExp.LHSs.ConvertAll(lhs => lhs.Var), rhss, () => G(letExp.Body)));
        }
        else if (matchExp != null)
        {
            if (matchExp.MissingCases.Count != 0)
            {
                throw new Exception("not implemented: MatchExpr with missing cases: " + matchExp);
            }
            //- match src case c1(ps1) => e1 ... cn(psn) => en
            //-   -->
            //- let x := src in
            //-   if x is c1 then let ps1 := ...x.f1... in e1 else
            //-   if x is c2 then let ps2 := ...x.f2... in e2 else
            //-                   let ps3 := ...x.f3... in e3
            var           src   = G(matchExp.Source);
            var           cases = matchExp.Cases;
            string        x     = TempName();
            Func <RtlExp> body  = null;
            for (int i = cases.Count; i > 0;)
            {
                i--;
                MatchCaseExpr         c     = cases[i];
                Func <List <RtlExp> > cRhss = () => c.Ctor.Formals.ConvertAll(f => (RtlExp) new RtlLiteral("("
                                                                                                           + f.Name + "#" + c.Ctor.Name + "(" + GhostVar(x) + "))"));
                Func <RtlExp> ec = () => GhostLet(exp.tok, c.Arguments, cRhss(), () => G(c.Body));
                if (body == null)
                {
                    body = ec;
                }
                else
                {
                    var prevBody = body;
                    body = () => GhostIfThenElse(new RtlLiteral("(" + GhostVar(x) + " is " + c.Ctor.Name + ")"),
                                                 ec, prevBody);
                }
            }
            return(GhostLet(exp.tok, new List <BoundVar> {
                new BoundVar(exp.tok, x, matchExp.Source.Type)
            },
                            new List <RtlExp> {
                src
            }, body));
        }
        else if (oldExp != null)
        {
            return(new RtlLiteral("old(" + GhostExpression(oldExp.E, inRecSpec, true) + ")"));
        }
        else if (freshExp != null)
        {
            Util.Assert(DafnySpec.IsArrayType(freshExp.E.Type));
            string abs = G(freshExp.E) + ".arrAbs";
            return(new RtlLiteral("(heap_old.absData[" + abs + "] is AbsNone)"));
        }
        else if (fieldSelect != null && fieldSelect.FieldName.EndsWith("?"))
        {
            string constructor = fieldSelect.FieldName.Substring(0, fieldSelect.FieldName.Length - 1);
            constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type, constructor, null, typeApply.typeArgs).AppName();
            bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<");
            return(isSeq
                ? new RtlLiteral("is_" + constructor + "(" + G(fieldSelect.Obj) + ")")
                : new RtlLiteral("((" + G(fieldSelect.Obj) + ") is " + constructor + ")"));
        }
        else if (fieldSelect != null && !fieldSelect.Field.IsStatic && AppType(fieldSelect.Obj.Type) is UserDefinedType &&
                 fieldSelect.Field is DatatypeDestructor)
        {
            DatatypeDestructor field       = (DatatypeDestructor)fieldSelect.Field;
            string             constructor = dafnySpec.Compile_Constructor(fieldSelect.Obj.Type,
                                                                           field.EnclosingCtor.Name, null, typeApply.typeArgs).AppName();
            bool isSeq = fieldSelect.Obj.Type.TypeName(null).StartsWith("Seq<");
            return(new RtlLiteral("(" + fieldSelect.FieldName + (isSeq ? "_" : "#") + constructor
                                  + "(" + G(fieldSelect.Obj) + "))"));
        }
        else if (fieldSelect != null && DafnySpec.IsArrayType(AppType(fieldSelect.Obj.Type)) &&
                 fieldSelect.FieldName == "Length")
        {
            return(new RtlLiteral("(Arr_Length(" + G(fieldSelect.Obj) + "))"));
        }
        else if (fieldSelect != null && fieldSelect.Obj is ImplicitThisExpr)
        {
            //- we don't support objects yet, so interpret this as a global variable
            return(new RtlVar(GhostVar(fieldSelect.FieldName), true, fieldSelect.Type));
        }
        else if (seqSelect != null)
        {
            if (seqSelect.SelectOne && DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type)))
            {
                return(new RtlExpComputed(e => "fun_INTERNAL__array__elems__index("
                                          + (inRequiresOrOld ? "$absMem_old" : "$absMem") + "[" + e.args[0] + ".arrAbs], ("
                                          + e.args[1] + "))", new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }));
            }
            else if (seqSelect.SelectOne)
            {
                return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Seq.Type), "Seq_Index"),
                                    new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }));
            }
            else
            {
                RtlExp seq = G(seqSelect.Seq);
                if (DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type)))
                {
                    seq = new RtlApply(FunName("Seq__FromArray"), new RtlExp[] {
                        new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"), seq
                    });
                }
                if (seqSelect.E1 != null)
                {
                    seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Take"),
                                       new RtlExp[] { seq, G(seqSelect.E1) });
                }
                if (seqSelect.E0 != null)
                {
                    seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Drop"),
                                       new RtlExp[] { seq, G(seqSelect.E0) });
                }
                return(seq);
            }
        }
        else if (seqUpdate != null)
        {
            if (seqUpdate.ResolvedUpdateExpr != null)
            {
                return(GhostExpressionRec(seqUpdate.ResolvedUpdateExpr, inRecSpec, inRequiresOrOld));
            }
            return(new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqUpdate.Seq.Type), "Seq_Update"),
                                new RtlExp[] { G(seqUpdate.Seq), G(seqUpdate.Index), G(seqUpdate.Value) }));
        }
        else if (seqDisplay != null)
        {
            RtlExp seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Empty"), new RtlExp[0]);
            foreach (Expression ei in seqDisplay.Elements)
            {
                seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Build"),
                                   new RtlExp[] { seq, G(ei) });
            }
            return(seq);
        }
        else
        {
            throw new Exception("not implemented: " + exp);
        }
    }
Esempio n. 29
0
 // ForallExpr
 public static int GetNumberOfChildren(this ForallExpr e)
 {
     return(1);
 }