public AvnInstrumentation(HashSet <string> programStubs)
 {
     passName        = "SequentialInstrumentation";
     assertInstrInfo = new cba.InsertionTrans();
     blanksInfo      = new cba.InsertionTrans();
     assertsPassed   = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
                                                                        "assertsPassed", Microsoft.Boogie.Type.Bool));
     compressBlocks          = new cba.CompressBlocks();
     originalAssertions      = new Dictionary <AssertToken, AssertCmd>();
     tokenLocation           = new Dictionary <AssertToken, Tuple <string, string> >();
     procToTokens            = new Dictionary <string, HashSet <AssertToken> >();
     suppressedTokens        = new HashSet <AssertToken>();
     tempSuppressedTokens    = new HashSet <AssertToken>();
     currProg                = null;
     this.programStubs       = programStubs;
     origMainName            = null;
     procsWithEnvAssumptions = new HashSet <string>();
     suppressInfo            = new List <cba.InsertionTrans>();
 }
        // This is to avoid a corner-case with ModifyTrans where some statements
        // that are deleted by the transformation are picked up at the end of the
        // trace while mapping back.
        // We avoid this by adding "assume true" right after procedure calls
        private cba.InsertionTrans AddBlanks(Program program)
        {
            var tinfo = new cba.InsertionTrans();

            foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
            {
                foreach (var blk in impl.Blocks)
                {
                    var currCmds = new List <Cmd>();

                    tinfo.addTrans(impl.Name, blk.Label, blk.Label);
                    var incnt = -1;
                    foreach (Cmd cmd in blk.Cmds)
                    {
                        incnt++;

                        // procedure call
                        if (cmd is CallCmd)
                        {
                            currCmds.Add(cmd);
                            tinfo.addTrans(impl.Name, blk.Label, incnt, cmd, blk.Label, currCmds.Count - 1, new List <Cmd> {
                                currCmds.Last()
                            });
                            currCmds.Add(BoogieAstFactory.MkAssume(Expr.True));
                            continue;
                        }

                        currCmds.Add(cmd);
                        tinfo.addTrans(impl.Name, blk.Label, incnt, cmd, blk.Label, currCmds.Count - 1, new List <Cmd> {
                            currCmds.Last()
                        });
                    }
                    blk.Cmds = currCmds;
                }
            }

            return(tinfo);
        }
        // Suppress an input constraint
        public int SuppressInput(Expr input)
        {
            // find main
            var main = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations,
                                                    origMainName);

            // construct the assume
            var ret = SuppressionCount++;
            var req = new Requires(true, input);

            req.Attributes = new QKeyValue(Token.NoToken, AvnAnnotations.BlockingConstraintAttr,
                                           new List <object> {
                Expr.Literal(ret)
            }, req.Attributes);

            main.Proc.Requires.Add(req);

            // For mapback (is redundant now)
            var tinfo = new cba.InsertionTrans();

            suppressInfo.Add(tinfo);
            return(ret);
        }
        public override CBAProgram runCBAPass(CBAProgram program)
        {
            // Add blanks
            blanksInfo = AddBlanks(program);

            // Remove unreachable procedures
            BoogieUtil.pruneProcs(program, program.mainProcName);

            if (!Options.TraceSlicing)
            {
                // Remove source line annotations
                sourceInfo = cba.PrintSdvPath.DeleteSourceInfo(program);
            }
            else
            {
                sourceInfo = null;
            }

            // Remove print info
            //printInfo = cba.PrintSdvPath.DeletePrintCmds(program);

            // Compress
            compressBlocks.VisitProgram(program);

            // name Ebasic
            NameEnvironmentConstraints(program);

            // Instrument assertions
            int tokenId = 0;

            origMainName = program.mainProcName;

            CBAProgram ret = null;

            if (!Options.DeepAsserts)
            {
                // Do error-bit instrumentation
                var impls = BoogieUtil.nameImplMapping(program);
                var pwa   = cba.SequentialInstrumentation.procsWithAsserts(program);

                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    var instrumented = new List <Block>();
                    foreach (var blk in impl.Blocks)
                    {
                        var currCmds  = new List <Cmd>();
                        var currLabel = blk.Label;

                        assertInstrInfo.addTrans(impl.Name, blk.Label, blk.Label);
                        var incnt = -1;
                        foreach (Cmd cmd in blk.Cmds)
                        {
                            incnt++;

                            // instrument assert
                            if (cmd is AssertCmd && !BoogieUtil.isAssertTrue(cmd))
                            {
                                currCmds.Add(BoogieAstFactory.MkVarEqExpr(assertsPassed, (cmd as AssertCmd).Expr));

                                var token = new AssertToken(tokenId);
                                originalAssertions.Add(token, cmd as AssertCmd);
                                tokenLocation.Add(token, Tuple.Create(impl.Name, currLabel));
                                procToTokens.InitAndAdd(impl.Name, token);

                                addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);

                                currLabel = addInstr(instrumented, currCmds, currLabel, tokenId);
                                tokenId++;
                                currCmds = new List <Cmd>();

                                continue;
                            }

                            // procedure call
                            if (cmd is CallCmd && pwa.Contains((cmd as CallCmd).callee))
                            {
                                currCmds.Add(cmd);
                                addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);
                                currLabel = addInstr(instrumented, currCmds, currLabel, -1);
                                currCmds  = new List <Cmd>();
                                continue;
                            }

                            currCmds.Add(cmd);
                            addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds);
                        }

                        instrumented.Add(new Block(Token.NoToken, currLabel, currCmds, blk.TransferCmd));
                    }

                    impl.Blocks = instrumented;
                }

                program.AddTopLevelDeclaration(assertsPassed);
                var newMain = addMain(program);

                BoogieUtil.DoModSetAnalysis(program);

                // Set inline attribute
                // free requires assertsPassed == true;
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    impl.Proc.Requires.Add(new Requires(true, Expr.Ident(assertsPassed)));
                }

                // convert free ensures e to:
                //  free ensures assertsPassed == false || e
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()
                         .Where(impl => pwa.Contains(impl.Name)))
                {
                    foreach (Ensures ens in impl.Proc.Ensures)
                    {
                        ens.Condition = Expr.Or(Expr.Not(Expr.Ident(assertsPassed)), ens.Condition);
                    }
                }

                currProg = program;
                ret      = new CBAProgram(program, newMain, 0);
            }
            else
            {
                // Use Deep-assert instrumentation
                da = new cba.DeepAssertRewrite();

                // First, tag assertions with tokens
                foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                {
                    foreach (var blk in impl.Blocks)
                    {
                        foreach (var cmd in blk.Cmds.OfType <AssertCmd>())
                        {
                            if (BoogieUtil.isAssertTrue(cmd))
                            {
                                continue;
                            }

                            var token = new AssertToken(tokenId);
                            cmd.Attributes = new QKeyValue(Token.NoToken, "avn", new List <object> {
                                Expr.Literal(tokenId)
                            },
                                                           cmd.Attributes);
                            originalAssertions.Add(token, cmd);
                            tokenLocation.Add(token, Tuple.Create(impl.Name, blk.Label));
                            procToTokens.InitAndAdd(impl.Name, token);
                            tokenId++;
                        }
                    }
                }

                // Second, do the rewrite
                var t1     = new PersistentProgram(program, program.mainProcName, program.contextBound);
                var t2     = da.run(t1);
                var daprog = t2.getCBAProgram();

                // Third, revisit the assertions and remember their location
                // in the output program. This is a bit of a hack. The "tokenLocation"
                // of a token is the pair (p1,b1) where p1 is the procedure the assertion
                // originally came from and b1 is the block in the new main that contains
                // that assertion.
                var main = BoogieUtil.findProcedureImpl(daprog.TopLevelDeclarations, daprog.mainProcName);
                foreach (var block in main.Blocks)
                {
                    foreach (var cmd in block.Cmds.OfType <AssertCmd>())
                    {
                        var tok = QKeyValue.FindIntAttribute(cmd.Attributes, "avn", -1);
                        if (tok < 0)
                        {
                            continue;
                        }
                        var token = new AssertToken(tok);

                        Debug.Assert(tokenLocation.ContainsKey(token));
                        var oldloc = tokenLocation[token];
                        tokenLocation[token] = Tuple.Create(oldloc.Item1, block.Label);
                    }
                }

                currProg = daprog;
                ret      = daprog;
            }

            return(ret);
        }