示例#1
0
        // Always safe to return Top
        public static Value Evaluate(Expr expr, Dictionary <string, Value> subst)
        {
            var vused = new VarsUsed();

            vused.Visit(expr);

            // Make sure we have values of all variables except in-formals
            var informals = vused.Vars.Where(v => !subst.ContainsKey(v.Name));

            if (informals.All(v => (v is Formal) && ((v as Formal).InComing)))
            {
            }
            else
            {
                return(Value.GetTop());
            }

            if (vused.Vars.Any(v => subst.ContainsKey(v.Name) && subst[v.Name].ToSingletonVar() == null))
            {
                return(GetTop());
            }

            var vsubst = new Dictionary <string, Variable>();

            subst.Keys.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar()));

            var dup = new FixedDuplicator();
            var ne  = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(expr));

            return(Value.GetSingleton(ne));
        }
示例#2
0
        private Implementation processImplementation(Implementation node)
        {
            varsRead = new VarsUsed();

            // Gather the set of vars used
            foreach (var b in node.Blocks)
            {
                base.VisitBlock(b);
            }

            globalsRead.UnionWith(varsRead.globalsUsed);

            // Get rid of declarations (before variable slice adds new variables)
            var newvars = new List <Variable>();

            foreach (Variable v in node.LocVars)
            {
                if (varsRead.localsUsed.Contains(v.Name))
                {
                    newvars.Add(v);
                }
            }
            node.LocVars = newvars;

            // Do VariableSlicing
            VariableSlicing slice = new VariableSlicing(new VarSet(new HashSet <string>(varsRead.localsUsed), node.Name), ltinfo, node);

            for (int i = 0; i < node.Blocks.Count; i++)
            {
                node.Blocks[i] = slice.VisitBlock(node.Blocks[i]);
            }

            varsRead = null;
            return(node);
        }
示例#3
0
        static HashSet <string> GetReadVars(Cmd cmd)
        {
            if (cmd is PredicateCmd)
            {
                var expr = (cmd as PredicateCmd).Expr;
                var vu   = new VarsUsed();
                vu.VisitExpr(expr);
                return(vu.localsUsed);
            }
            else if (cmd is AssignCmd)
            {
                var ret  = new HashSet <string>();
                var acmd = cmd as AssignCmd;

                foreach (var expr in acmd.Rhss)
                {
                    var vu = new VarsUsed();
                    vu.VisitExpr(expr);
                    vu.localsUsed.Iter(v => ret.Add(v));
                }

                foreach (var lhs in acmd.Lhss)
                {
                    if (lhs is MapAssignLhs)
                    {
                        var mlhs = lhs as MapAssignLhs;

                        foreach (var expr in mlhs.Indexes)
                        {
                            var vu = new VarsUsed();
                            vu.VisitExpr(expr);
                            vu.localsUsed.Iter(v => ret.Add(v));
                        }
                    }
                }

                return(ret);
            }
            else if (cmd is CallCmd)
            {
                var ret  = new HashSet <string>();
                var ccmd = cmd as CallCmd;

                foreach (var expr in ccmd.Ins)
                {
                    var vu = new VarsUsed();
                    vu.VisitExpr(expr);
                    vu.localsUsed.Iter(v => ret.Add(v));
                }

                return(ret);
            }
            else
            {
                Console.WriteLine("Unable to process cmd - neither predicate, nor assign or call");
                throw new NotImplementedException();
            }
        }
示例#4
0
        public Value Subst(Dictionary <string, Value> subst)
        {
            if (isTrue)
            {
                return(this);
            }
            var newc = new HashSet <int>(constants);
            var newv = new HashSet <Variable>();
            var newe = new HashSet <Expr>();

            foreach (var v in vars)
            {
                Debug.Assert(subst.ContainsKey(v.Name));
                if (subst[v.Name].isTrue)
                {
                    return(GetTop());
                }
                newc.UnionWith(subst[v.Name].constants);
                newv.UnionWith(subst[v.Name].vars);
                newe.UnionWith(subst[v.Name].constExprs);
            }

            foreach (var e in constExprs)
            {
                var vused = new VarsUsed();
                vused.VisitExpr(e);

                Debug.Assert(vused.varsUsed.All(v => subst.ContainsKey(v)));

                if (vused.varsUsed.Any(v => subst[v].ToSingletonVar() == null))
                {
                    return(GetTop());
                }

                var vsubst = new Dictionary <string, Variable>();
                vused.varsUsed.Iter(v => vsubst.Add(v, subst[v].ToSingletonVar()));

                var dup = new FixedDuplicator();
                var ne  = (new VarSubstituter(vsubst, new Dictionary <string, Variable>())).VisitExpr(dup.VisitExpr(e));
                newe.Add(ne);
            }

            newe = removeDuplicates(newe);
            if (newe.Count > maxExprsToTrack)
            {
                return(GetTop());
            }

            var ret = new Value();

            ret.vars       = newv;
            ret.constants  = newc;
            ret.constExprs = newe;
            ret.isTrue     = false;

            return(ret);
        }
示例#5
0
 public UnReadVarEliminator(bool onlyLocals)
 {
     this.onlyLocals = onlyLocals;
     varsRead        = null;
     globalsRead     = null;
     ltinfo          = new ModifyTrans();
     gtinfo          = new ModifyTrans();
     sliceGlobals    = null;
 }
        public void compile(Implementation impl)
        {
            var ensures  = impl.Proc.Ensures;
            var requires = impl.Proc.Requires;

            impl.Proc.Ensures  = new List <Ensures>();
            impl.Proc.Requires = new List <Requires>();

            var reqCmds = new List <Cmd>();
            var ensCmds = new List <Cmd>();
            var newLocs = new List <Variable>();

            var substOld = new SubstOldVars();

            foreach (Ensures e in ensures)
            {
                Debug.Assert(e.Free);
                var expr = substOld.VisitExpr(e.Condition);
                ensCmds.Add(new AssumeCmd(Token.NoToken, expr, e.Attributes));
            }

            foreach (Requires r in requires)
            {
                Debug.Assert(r.Free);
                var vu = new VarsUsed();
                vu.VisitRequires(r);
                Debug.Assert(vu.oldVarsUsed.Count == 0);
                reqCmds.Add(new AssumeCmd(Token.NoToken, r.Condition, r.Attributes));
            }

            reqCmds.AddRange(substOld.initLocVars);

            substOld.varMap.Values.Iter(lv => newLocs.Add(lv));

            impl.LocVars.AddRange(newLocs);

            reqCmds.AddRange(impl.Blocks[0].Cmds);
            impl.Blocks[0].Cmds = reqCmds;

            foreach (var blk in impl.Blocks)
            {
                var rc = blk.TransferCmd as ReturnCmd;
                if (rc == null)
                {
                    continue;
                }
                blk.Cmds.AddRange(ensCmds);
            }
        }
示例#7
0
        // onlyGlobals is true means assume all locals are tracked
        // onlyGlobals is false means assume all globals are tracked
        private bool isTracked(Absy exp, string name)
        {
            VarsUsed uses = new VarsUsed();

            uses.Visit(exp);

            if (onlyGlobals)
            {
                return(trackedVars.Contains(new VarSet(uses.globalsUsed, name)));
            }
            else
            {
                return(trackedVars.Contains(new VarSet(uses.localsUsed, name)));
            }
        }
示例#8
0
        // Globals may also be read in procedures (without implementation)
        private void processProcedure(Procedure node)
        {
            varsRead = new VarsUsed();
            foreach (Requires re in node.Requires)
            {
                varsRead.Visit(re.Condition);
            }

            foreach (Ensures en in node.Ensures)
            {
                varsRead.Visit(en.Condition);
            }

            globalsRead.UnionWith(varsRead.globalsUsed);
        }
示例#9
0
        // One cannot use "old" versions of shared globals
        private static void checkOld(Implementation impl)
        {
            VarsUsed used = new VarsUsed();

            foreach (var blk in impl.Blocks)
            {
                foreach (Cmd cmd in blk.Cmds)
                {
                    used.reset();
                    used.Visit(cmd);
                    if (used.oldVarsUsed.Any())
                    {
                        cmd.Emit(new TokenTextWriter(Console.Out), 0);
                        throw new InvalidInput("Command has an \"old\" variable");
                    }
                }
            }
        }
示例#10
0
        public static Value GetSingleton(Expr e)
        {
            var vused = new VarsUsed();

            vused.Visit(e);

            // An expr can only mention in-formals (TODO: and Constants)
            if (vused.Vars.Any(v => !(v is Formal)))
            {
                return(GetTop());
            }
            if (vused.Vars.OfType <Formal>().Any(f => !f.InComing))
            {
                return(GetTop());
            }

            var ret = new Value();

            ret.constExprs.Add(e);
            return(ret);
        }
示例#11
0
        // Mark "slic" assume statements
        // Mark "indirect" call assume statements
        public static void sdvAnnotateDefectTrace(Program trace, HashSet <string> slicVars, bool addSlicAnnotations = true)
        {
            //var slicVars = new HashSet<string>(config.trackedVars);
            //slicVars.Remove("alloc");

            var isSlicExpr = new Predicate <Expr>(expr =>
            {
                var vused = new VarsUsed();
                vused.VisitExpr(expr);
                if (vused.varsUsed.Any(v => slicVars.Contains(v)))
                {
                    return(true);
                }
                return(false);
            });
            var isSlicAssume = new Func <AssumeCmd, Implementation, bool>((ac, impl) =>
            {
                if (impl.Name.Contains("SLIC_") || impl.Name.Contains("sdv_"))
                {
                    return(true);
                }
                if (isSlicExpr(ac.Expr))
                {
                    return(true);
                }
                return(false);
            });
            var tagAssume = new Action <AssumeCmd, Implementation>((ac, impl) =>
            {
                if (isSlicAssume(ac, impl))
                {
                    ac.Attributes =
                        new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes);
                }
            });

            foreach (var impl in trace.TopLevelDeclarations
                     .OfType <Implementation>())
            {
                if (addSlicAnnotations)
                {
                    // Insert "slic" annotation
                    impl.Blocks.Iter(blk =>
                                     blk.Cmds.OfType <AssumeCmd>()
                                     .Iter(cmd => tagAssume(cmd, impl)));
                }

                // Insert "indirect" annotation
                foreach (var blk in impl.Blocks)
                {
                    for (int i = 0; i < blk.Cmds.Count - 1; i++)
                    {
                        var c1 = blk.Cmds[i] as AssumeCmd;
                        var c2 = blk.Cmds[i + 1] as AssumeCmd;
                        if (c1 == null || c2 == null)
                        {
                            continue;
                        }
                        if (!QKeyValue.FindBoolAttribute(c1.Attributes, "IndirectCall"))
                        {
                            continue;
                        }
                        c2.Attributes = new QKeyValue(Token.NoToken, "indirect", new List <object>(), c2.Attributes);
                    }
                }
            }

            // Mark malloc
            foreach (var impl in trace.TopLevelDeclarations
                     .OfType <Implementation>())
            {
                foreach (var blk in impl.Blocks)
                {
                    var ncmds = new List <Cmd>();
                    foreach (Cmd cmd in blk.Cmds)
                    {
                        ncmds.Add(cmd);

                        var ccmd = cmd as CallCmd;
                        if (ccmd == null || !ccmd.callee.Contains("HAVOC_malloc"))
                        {
                            continue;
                        }
                        var ac = new AssertCmd(Token.NoToken, Expr.True);
                        ac.Attributes = new QKeyValue(Token.NoToken, "malloc", new List <object>(), null);
                        ncmds.Add(ac);
                    }
                    blk.Cmds = ncmds;
                }
            }
        }
示例#12
0
        // -- There should be no ensures and requires on shared globals
        // -- For ensures and requires on non-shared globals, they should be "free"
        // -- One cannot use "old" versions of shared globals
        private static void checkProc(Procedure proc, HashSet <string> procsWithImpl, HashSet <string> procsNotCalled)
        {
            VarsUsed used = new VarsUsed();

            foreach (Requires re in proc.Requires)
            {
                used.reset();
                used.Visit(re.Condition);

                if (used.globalsUsed.Any(v => LanguageSemantics.isShared(v)))
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("Requires has a shared global");
                }

                if (used.oldVarsUsed.Any(v => LanguageSemantics.isShared(v)))
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("Requires has an \"old\" shared global");
                }

                if (used.globalsUsed.Count == 0)
                {
                    continue;
                }

                // We dont care about requires on pros that are not called
                if (procsNotCalled.Contains(proc.Name))
                {
                    continue;
                }

                if (re.Free == false)
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("A non-free requires has a non-shared global (not yet supported)");
                }
            }

            foreach (Ensures re in proc.Ensures)
            {
                used.reset();
                used.Visit(re.Condition);

                if (used.globalsUsed.Any(v => LanguageSemantics.isShared(v)))
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("Ensures has a shared global");
                }

                if (used.oldVarsUsed.Any(v => LanguageSemantics.isShared(v)))
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("Ensures has an \"old\" shared global");
                }

                /*
                 * if (used.globalsUsed.Count == 0)
                 * {
                 *  continue;
                 * }
                 */

                // "Ensures" in procs without implementation are considered free
                if (re.Free == false && procsWithImpl.Contains(proc.Name))
                {
                    re.Emit(new TokenTextWriter(Console.Out), 0);
                    throw new InvalidInput("A non-free ensures is not yet supported");
                }
            }
        }
示例#13
0
        // deprecated
        public static string FindAnnotationsOld(string predicate)
        {
            var expr = ToExpr(predicate);
            var ret  = "";

            // Get variables used in the expr
            var variables = new HashSet <Variable>();
            var vu        = new VarsUsed();

            vu.VisitExpr(expr);
            variables = vu.Vars;

            // yogi_error variable present?
            var  err = variables.Where(v => v.Name == "yogi_error").FirstOrDefault();
            Expr pre = Expr.True;

            if (err != null)
            {
                pre = Expr.Eq(new OldExpr(Token.NoToken, Expr.Ident(err)), Expr.Literal(0));
            }

            foreach (var v in variables)
            {
                Expr nmod = Expr.Eq(new OldExpr(Token.NoToken, Expr.Ident(v)), Expr.Ident(v));
                nmod = Expr.And(nmod, pre);
                var check = Expr.And(nmod, Expr.Not(expr));
                if (CheckIfUnsat(check))
                {
                    ret += string.Format(" {{:mustmod \"{0}\" }}", v);
                    continue;
                }
                if (err != null && v.Name == err.Name)
                {
                    continue;
                }

                var rand    = new System.Random();
                var rvalues = new HashSet <int>();
                for (int i = 0; i < 3; i++)
                {
                    rvalues.Add(rand.Next(0, 10));
                }
                for (int i = 0; i < 3; i++)
                {
                    rvalues.Add(rand.Next(-10, 0));
                }

                foreach (var val in rvalues)
                {
                    //Console.WriteLine("Trying {0}", val);
                    check = Expr.And(nmod, Expr.Eq(new OldExpr(Token.NoToken, Expr.Ident(v)), Expr.Literal(val)));
                    check = Expr.And(check, expr);
                    if (CheckIfUnsat(check))
                    {
                        ret += string.Format(" {{:mustmod \"{0}\" }}", v);
                        break;
                    }
                }
            }

            return(ret);
        }