示例#1
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            if (!aggressive)
            {
                return(null);
            }

            var procsWithAsserts           = procsWithAssertions(p);
            HashSet <string> procsToDelete = new HashSet <string>();

            // Gather the set of procedures to delete
            foreach (Declaration d in p.TopLevelDeclarations)
            {
                if (d is Procedure)
                {
                    var proc = d as Procedure;

                    if (proc.Name.Equals(p.mainProcName))
                    {
                        continue;
                    }

                    if (procsWithAsserts.Contains(proc.Name))
                    {
                        continue;
                    }

                    if (proc.OutParams.Count > 0)
                    {
                        continue;
                    }

                    var modifiesShared = false;
                    foreach (IdentifierExpr ie in proc.Modifies)
                    {
                        if (LanguageSemantics.isShared(ie.Decl.Name))
                        {
                            modifiesShared = true;
                            break;
                        }
                    }

                    if (!modifiesShared)
                    {
                        procsToDelete.Add(proc.Name);
                    }
                }
            }

            // Delete the implementations
            CBAProgram ret = new CBAProgram(new Program(), p.mainProcName, p.contextBound);

            foreach (Declaration d in p.TopLevelDeclarations)
            {
                if (d is Implementation)
                {
                    Implementation impl = d as Implementation;
                    if (procsToDelete.Contains(impl.Name) && !BoogieUtil.hasAssert(impl))
                    {
                        Log.WriteLine(Log.Debug, "Deleting " + impl.Name);
                        continue;
                    }
                    ret.AddTopLevelDeclaration(d);
                }
                else
                {
                    ret.AddTopLevelDeclaration(d);
                }
            }

            Log.WriteLine(Log.Debug, "Empty Mod Sets: Deleted " + (p.TopLevelDeclarations.Count() - ret.TopLevelDeclarations.Count()).ToString() +
                          " implementations");
            return(ret);
        }
示例#2
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            if (p.mode == ConcurrencyMode.FixedContext)
            {
                InstrumentationConfig.addRaiseException = false;
            }

            // Step1: Gather program information
            pinfo = new ProgramInfo(p.mainProcName, p, LanguageSemantics.assertNotReachableName());

            TidArithmetic.reset();
            if (pinfo.threadIdType.IsBv)
            {
                TidArithmetic.useIntArithmetic = false;
                p.AddTopLevelDeclaration(TidArithmetic.getBvAdd());
                p.AddTopLevelDeclaration(TidArithmetic.getBvGt());
            }
            else
            {
                TidArithmetic.useIntArithmetic = true;
            }

            // Step2: Set up a variable manager
            vmgr = new VariableManager(pinfo);

            // Step3: Set up the instrumentation policy

            // The globals not to instrument are:
            //   -- ones not modified by any procedure
            //   -- ones not shared
            //   -- ones to treat as thread-local
            HashSet <string> globalsToInstrument = new HashSet <string>();

            foreach (var g in pinfo.declaredGlobals)
            {
                string name = g.Key;
                if (!pinfo.modifiedGlobals.ContainsKey(name))
                {
                    continue;
                }
                if (!LanguageSemantics.isShared(name))
                {
                    continue;
                }
                if (pinfo.threadLocalGlobals.ContainsKey(name))
                {
                    continue;
                }
                globalsToInstrument.Add(name);
            }

            var rprocs = findRecursiveProcs(p);

            //foreach (var be in rprocs) Console.WriteLine("{0} -> {1}", be.Item1, be.Item2);

            policy =
                new InstrumentationPolicy(p.contextBound, globalsToInstrument, pinfo.procsWithImplementation, pinfo.asyncProcs, rprocs, p.mode);

            //policy.print(Log.getWriter(Log.Debug));

            // Step4: Split program declarations based on the instrumentation policy

            // skipping this step (not needed for basic CBA reduction)

            // Step5: Carry out the K-split instrumentation
            inst = new Instrumenter(policy, vmgr, pinfo, tinfo_instrument);
            List <Declaration> newDecls = inst.instrument(p.TopLevelDeclarations.ToList());

            foreach (var trp in inst.blocksWithFixedK)
            {
                blockExecutionContextMap.Add(trp.fst + "::" + trp.snd, trp.trd);
            }

            // Step6: Instrument main with initialization and the Checker
            Implementation mainProcImpl = BoogieUtil.findProcedureImpl(newDecls, p.mainProcName);

            inst.instrumentGivenMainImpl(mainProcImpl);

            // Step7: Instrument Async calls
            bool instrumentedAsync     = false;
            InstrumentAsyncCalls ainst = new InstrumentAsyncCalls(vmgr, pinfo, tinfo_async);

            foreach (var decl in newDecls)
            {
                if (decl is Implementation)
                {
                    ainst.VisitImplementation(decl as Implementation);
                    instrumentedAsync = instrumentedAsync || ainst.hasAsync;
                }
            }

            if (!instrumentedAsync)
            {
                Log.WriteLine(Log.Debug, "Warning: Did not find any async call");
            }

            // Step8: Set entrypoint
            mainProcImpl.AddAttribute("entrypoint");

            // Step9: Add new variable declarations
            newDecls.AddRange(vmgr.getNewDeclarations(policy.executionContextBound));
            newDecls.AddRange(BoogieAstFactory.newDecls);
            BoogieAstFactory.newDecls.Clear();

            // Thats it.

            Program ret = new Program();

            ret.TopLevelDeclarations = newDecls;

            if (InstrumentationConfig.printInstrumented)
            {
                // Re-resolve ret
                ProgTransformation.PersistentProgram tprog = new ProgTransformation.PersistentProgram(ret);
                var instrumented = tprog.getProgram();

                // Re-do the modsets -- make them as concise as possible.
                BoogieUtil.DoModSetAnalysis(instrumented);

                // Temporary fix for Boogie's bug while inlining calls
                // that have don't care expressions.
                RewriteCallDontCares rdc = new RewriteCallDontCares();
                rdc.VisitProgram(instrumented);

                BoogieUtil.PrintProgram(instrumented, InstrumentationConfig.instrumentedFile);

                throw new NormalExit("Printed " + InstrumentationConfig.instrumentedFile);
            }

            // Resolve the program (Do not typecheck because that does inlining).
            //BoogieUtil.PrintProgram(ret, "instrumented.bpl");
            //ret = BoogieUtil.ReadAndOnlyResolve("instrumented.bpl");
            if (p.mode == ConcurrencyMode.FixedContext)
            {
                InstrumentationConfig.addRaiseException = true;
            }

            p = new CBAProgram(ret, p.mainProcName, p.contextBound);

            return(p);
        }
示例#3
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");
                }
            }
        }