Ejemplo n.º 1
0
        // Rename basic blocks, local variables
        // Add "havoc locals" at the beginning
        // block return
        private static void RenameImpl(Implementation impl, Dictionary <string, Tuple <Block, Implementation> > origProg)
        {
            var origImpl   = (new FixedDuplicator(true)).VisitImplementation(impl);
            var origBlocks = BoogieUtil.labelBlockMapping(origImpl);

            // create new locals
            var newLocals = new Dictionary <string, Variable>();

            foreach (var l in impl.LocVars.Concat(impl.InParams).Concat(impl.OutParams))
            {
                // substitute even formal variables with LocalVariables. This is fine
                // because we finally just merge all implemnetations together
                var nl = BoogieAstFactory.MkLocal(l.Name + "_" + impl.Name + "_copy", l.TypedIdent.Type);
                newLocals.Add(l.Name, nl);
            }

            // rename locals
            var subst = new VarSubstituter(newLocals, new Dictionary <string, Variable>());

            subst.VisitImplementation(impl);

            // Rename blocks
            foreach (var blk in impl.Blocks)
            {
                var newName = impl.Name + "_" + blk.Label;
                origProg.Add(newName, Tuple.Create(origBlocks[blk.Label], origImpl));
                blk.Label = newName;

                if (blk.TransferCmd is GotoCmd)
                {
                    var gc = blk.TransferCmd as GotoCmd;
                    gc.labelNames = new List <string>(
                        gc.labelNames.Select(lab => impl.Name + "_" + lab));
                }

                if (blk.TransferCmd is ReturnCmd)
                {
                    // block return
                    blk.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
                }
            }

            /*
             * // havoc locals -- not necessary
             * if (newLocals.Count > 0)
             * {
             *  var ies = new List<IdentifierExpr>();
             *  newLocals.Values.Iter(v => ies.Add(Expr.Ident(v)));
             *  impl.Blocks[0].Cmds.Insert(0, new HavocCmd(Token.NoToken, ies));
             * }
             */
        }
Ejemplo n.º 2
0
        public static void Instrument(Program program, HashSet <string> scalars)
        {
            memAccess     = BoogieAstFactory.MkLocal("memAccess", Microsoft.Boogie.Type.Int) as LocalVariable;
            scalarGlobals = new HashSet <string>();
            program.TopLevelDeclarations
            .OfType <GlobalVariable>()
            .Where(g => scalars.Contains(g.Name))
            .Iter(g => scalarGlobals.Add(g.Name));

            program.TopLevelDeclarations
            .OfType <Implementation>()
            .Iter(Instrument);

            var decl = BoogieAstFactory.MkProc(recordProc, new List <Variable>(new Variable[] { BoogieAstFactory.MkFormal("address", Microsoft.Boogie.Type.Int, true) }), new List <Variable>());

            program.AddTopLevelDeclaration(decl);
        }
Ejemplo n.º 3
0
            private void CreateMainProcedure(Function reach)
            {
                //blocks
                List <Block>    mainBlocks = new List <Block>();
                List <Variable> locals     = new List <Variable>();

                HashSet <Constant> blockCallConsts = new HashSet <Constant>();

                foreach (Implementation impl in prog.TopLevelDeclarations.Where(x => x is Implementation))
                {
                    // skip this impl if it is not marked as an entrypoint
                    if (useProvidedEntryPoints && !QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "entrypoint"))
                    {
                        continue;
                    }

                    impl.Attributes      = BoogieUtil.removeAttr("entrypoint", impl.Attributes);
                    impl.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Proc.Attributes);

                    // skip initialization procedure
                    if (QKeyValue.FindBoolAttribute(impl.Attributes, AvnAnnotations.InitialializationProcAttr) ||
                        QKeyValue.FindBoolAttribute(impl.Proc.Attributes, AvnAnnotations.InitialializationProcAttr))
                    {
                        continue;
                    }

                    entrypoints.Add(impl.Name);

                    //allocate params
                    var args = new List <Variable>();
                    var rets = new List <Variable>();


                    impl.OutParams.ForEach(v => rets.Add(BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type)));
                    if (Options.allocateParameters)
                    {
                        // use impl.Proc here to pickup scalar/pointer attributes
                        impl.Proc.InParams.ForEach(v =>
                        {
                            var l = BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type);
                            // We are delibrately dropping the attributes so that
                            // all parameters are initialized by allocation
                            //l.Attributes = v.Attributes;
                            args.Add(l);
                        });
                        locals.AddRange(args);
                    }
                    else
                    {
                        impl.Proc.InParams.ForEach(v =>
                        {
                            var g = BoogieAstFactory.MkGlobal(v.Name + "_" + impl.Name, v.TypedIdent.Type);
                            //g.Attributes = v.Attributes;
                            args.Add(g);
                        });
                        globalParams.AddRange(args);
                    }


                    locals.AddRange(rets);

                    //call
                    var blockCallConst = new Constant(Token.NoToken,
                                                      new TypedIdent(Token.NoToken, "__block_call_" + impl.Name, btype.Bool), false);
                    blockCallConsts.Add(blockCallConst);
                    blockEntryPointConstants[blockCallConst.Name] = impl.Name;
                    impl2BlockingConstant[impl.Name] = blockCallConst;
                    var blockCallAssumeCmd = new AssumeCmd(Token.NoToken, IdentifierExpr.Ident(blockCallConst));

                    var cmds = new List <Cmd>();
                    cmds.Add(blockCallAssumeCmd);
                    if (Options.allocateParameters) // allocate parameters if option is enabled
                    {
                        var argMallocCmds = AllocatePointersAsUnknowns(args);
                        cmds.AddRange(argMallocCmds);
                    }

                    // The beginning of an entry point must be reachable: assume reach(true);
                    cmds.Add(new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken,
                                                                       new FunctionCall(reach), new List <Expr> {
                        Expr.True
                    })));

                    var callCmd = new CallCmd(Token.NoToken, impl.Name, args.ConvertAll(x => (Expr)IdentifierExpr.Ident(x)),
                                              rets.ConvertAll(x => IdentifierExpr.Ident(x)));
                    callCmd.Attributes = new QKeyValue(Token.NoToken, AvUtil.AvnAnnotations.AvhEntryPointAttr, new List <object>(), callCmd.Attributes);

                    cmds.Add(callCmd);
                    //succ
                    var txCmd = new ReturnCmd(Token.NoToken);
                    var blk   = BoogieAstFactory.MkBlock(cmds, txCmd);
                    mainBlocks.Add(blk);
                }
                foreach (Procedure proc in prog.TopLevelDeclarations.OfType <Procedure>())
                {
                    proc.Attributes = BoogieUtil.removeAttr("entrypoint", proc.Attributes);
                }
                // add global variables to prog
                // globals.Iter(x => prog.AddTopLevelDeclaration(x));
                //add the constants to the prog
                blockCallConsts.Iter(x => prog.AddTopLevelDeclaration(x));
                //TODO: get globals of type refs/pointers and maps
                var initCmd = (AssumeCmd)BoogieAstFactory.MkAssume(Expr.True);

                var globalCmds = new List <Cmd>()
                {
                    initCmd
                };
                //add call to corralExtraInit
                var init = Instrumentations.GetEnvironmentAssumptionsProc(prog);

                if (init != null && !Options.DelayInitialization)
                {
                    globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>()));
                }

                // Dont initialize Boogie instrumentation variables
                prog.GlobalVariables
                .Where(g => g.Name == "alloc" || BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes))
                .Where(g => !BoogieUtil.checkAttrExists("scalar", g.Attributes))
                .Iter(g => g.AddAttribute("scalar"));

                // initialize globals
                prog.GlobalVariables
                .Where(g => g.Name != "alloc" && !BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes))
                .Iter(g => g.Attributes = BoogieUtil.removeAttrs(new HashSet <string> {
                    "scalar", "pointer"
                }, g.Attributes));

                globalCmds.AddRange(AllocatePointersAsUnknowns(prog.GlobalVariables.Select(x => (Variable)x).ToList()));

                if (init != null && Options.DelayInitialization)
                {
                    globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>()));
                }

                // globals for parameters
                prog.AddTopLevelDeclarations(globalParams);

                //first block
                var transferCmd =
                    mainBlocks.Count > 0 ? (TransferCmd)(new GotoCmd(Token.NoToken, mainBlocks)) : (TransferCmd)(new ReturnCmd(Token.NoToken));
                Block blkStart = new Block(Token.NoToken, "CorralMainStart", globalCmds, transferCmd);
                var   blocks   = new List <Block>();

                blocks.Add(blkStart);
                blocks.AddRange(mainBlocks);
                var mainProcImpl = BoogieAstFactory.MkImpl(AvnAnnotations.CORRAL_MAIN_PROC, new List <Variable>(), new List <Variable>(), locals, blocks);

                mainProcImpl[0].AddAttribute("entrypoint");
                prog.AddTopLevelDeclarations(mainProcImpl);
            }
Ejemplo n.º 4
0
            //Change the body of any stub that returns a pointer into calling unknown()
            //TODO: only do this for procedures with a single return with a pointer type
            private void MkStubImplementation(List <Implementation> stubImpls, Procedure p)
            {
                List <Cmd>      cmds      = new List <Cmd>();
                List <Variable> localVars = new List <Variable>();

                stubs.Add(p.Name);
                foreach (var op in p.OutParams)
                {
                    if (IsPointerVariable(op))
                    {
                        cmds.Add(AllocatePointerAsUnknown(op));
                    }
                    else
                    {
                        // Avoid using Havoc -- we'll let this fall on the floor as an
                        // uninitialized variable. AVN will take care of concretizing it
                        //cmds.Add(BoogieAstFactory.MkHavocVar(op));
                    }
                }
                foreach (var v in p.Modifies.Select(ie => ie.Decl))
                {
                    if (IsPointerVariable(v))
                    {
                        cmds.Add(AllocatePointerAsUnknown(v));
                    }
                    else
                    {
                        // unsupported
                        Console.WriteLine("Warning: demonic havoc of global {0} in {1}", v.Name, p.Name);
                    }
                }
                foreach (var ip in p.InParams)
                {
                    if (!BoogieUtil.checkAttrExists("ref", ip.Attributes))
                    {
                        continue;
                    }
                    string mapName = QKeyValue.FindStringAttribute(ip.Attributes, "ref");
                    if (mapName == null)
                    {
                        Utils.Print(String.Format("Expecting a map <name> with {:ref <name>} annotation on procedure {0}", p.Name),
                                    Utils.PRINT_TAG.AV_WARNING);
                        continue;
                    }
                    var mapVars = prog.TopLevelDeclarations.OfType <Variable>().Where(x => x.Name == mapName && x.TypedIdent.Type.IsMap);
                    if (mapVars.Count() != 1)
                    {
                        Utils.Print(String.Format("Mapname {0} provided in {{:ref}} for parameter {1} for procedure {2} has {3} matches, expecting exactly 1 match",
                                                  mapName, ip.Name, p.Name, mapVars.Count()),
                                    Utils.PRINT_TAG.AV_WARNING);
                        continue;
                    }
                    var tmpVar = BoogieAstFactory.MkLocal("__tmp_" + ip.Name, ip.TypedIdent.Type);
                    localVars.Add(tmpVar);
                    cmds.Add(AllocatePointerAsUnknown(tmpVar));
                    cmds.Add(BoogieAstFactory.MkMapAssign(mapVars.First(), IdentifierExpr.Ident(ip), IdentifierExpr.Ident(tmpVar)));
                }
                if (cmds.Count == 0)
                {
                    return;                  //don't create a body if no statements
                }
                var blk  = BoogieAstFactory.MkBlock(cmds, new ReturnCmd(Token.NoToken));
                var blks = new List <Block>()
                {
                    blk
                };
                //don't insert the proc as it already exists
                var impl = BoogieAstFactory.MkImpl(p.Name,
                                                   DropAnnotations(p.InParams),
                                                   DropAnnotations(p.OutParams),
                                                   new List <Variable>(), blks);

                ((Implementation)impl[1]).LocVars.AddRange(localVars);
                stubImpls.Add((Implementation)impl[1]);
            }
Ejemplo n.º 5
0
        private static Program PrepareQuery(IEnumerable <Implementation> loopImpls, Program program)
        {
            // Sometimes loops have multiple backedges, hence multiple recursive calls: merge them
            loopImpls.Iter(impl => mergeRecCalls(impl));

            var dup = new FixedDuplicator(true);
            // Make copies of loopImpl procs
            var loopProcsCopy = new Dictionary <string, Procedure>();

            loopImpls
            .Iter(impl => loopProcsCopy.Add(impl.Name, dup.VisitProcedure(impl.Proc)));

            loopProcsCopy.Values.Iter(proc => proc.Name += "_PassiveCopy");

            // Make copies of the caller implementations
            var loopCallerImplCopy = new Dictionary <string, Implementation>();
            var loopCallerProcCopy = new Dictionary <string, Procedure>();

            loopImpls
            .Iter(impl => loopCallerImplCopy.Add(impl.Name, dup.VisitImplementation(loopCaller[impl.Name])));

            loopImpls
            .Iter(impl => loopCallerProcCopy.Add(impl.Name, dup.VisitProcedure(loopCaller[impl.Name].Proc)));

            loopCallerImplCopy
            .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key);

            loopCallerProcCopy
            .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key);

            loopCallerImplCopy
            .Iter(kvp => kvp.Value.Proc = loopCallerProcCopy[kvp.Key]);

            // Instrument callers
            foreach (var kvp in loopCallerImplCopy)
            {
                var impl = kvp.Value;

                var av = BoogieAstFactory.MkLocal("LoopBound_AssertVar", Microsoft.Boogie.Type.Bool);
                impl.LocVars.Add(av);

                // av := true
                var init     = BoogieAstFactory.MkVarEqConst(av, true);
                var initCmds = new List <Cmd>();
                initCmds.Add(init);
                initCmds.AddRange(impl.Blocks[0].Cmds);
                impl.Blocks[0].Cmds = initCmds;

                // av := false
                foreach (var blk in impl.Blocks)
                {
                    var newCmds = new List <Cmd>();
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        // disable assertions
                        if (blk.Cmds[i] is AssertCmd && !BoogieUtil.isAssertTrue(blk.Cmds[i]))
                        {
                            newCmds.Add(new AssumeCmd(Token.NoToken, (blk.Cmds[i] as AssertCmd).Expr));
                            continue;
                        }
                        var cc = blk.Cmds[i] as CallCmd;
                        if (cc != null && cc.callee == kvp.Key)
                        {
                            newCmds.Add(blk.Cmds[i]);
                            newCmds.Add(BoogieAstFactory.MkVarEqConst(av, false));
                        }
                        else if (cc != null && loopProcsCopy.ContainsKey(cc.callee))
                        {
                            var ncc = new CallCmd(cc.tok, loopProcsCopy[cc.callee].Name, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync);
                            ncc.Proc = loopProcsCopy[cc.callee];
                            newCmds.Add(ncc);
                        }
                        else
                        {
                            newCmds.Add(blk.Cmds[i]);
                        }
                    }
                    blk.Cmds = newCmds;
                }

                // assert av
                impl.Blocks
                .Where(blk => blk.TransferCmd is ReturnCmd)
                .Iter(blk => blk.Cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(av))));
            }

            // Prepare program
            var ret = new Program();

            program.TopLevelDeclarations
            .Where(decl => !(decl is Implementation))
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopProcsCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopCallerImplCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopCallerProcCopy.Values
            .Iter(decl => ret.AddTopLevelDeclaration(decl));

            loopImpls
            .Iter(impl => ret.AddTopLevelDeclaration(impl));

            loopCallerImplCopy.Values
            .Iter(impl => impl.AddAttribute("entrypoint"));

            // Store mapping: entrypoint -> loop
            loopImpls
            .Select(loop => Tuple.Create(loop, loopCallerImplCopy[loop.Name]))
            .Iter(tup => tup.Item2.AddAttribute("LB_Mapping", tup.Item1.Name));

            ret = BoogieUtil.ReResolveInMem(ret);

            return(ret);
        }