Esempio n. 1
0
 public void printLanguageSemantics()
 {
     Console.WriteLine("-------------------------------------------------------------");
     Console.WriteLine("Language Extensions:");
     Console.WriteLine("Thread spawn      : \"async call n := foo(...)\" \t Returns thread id");
     LanguageSemantics.print();
     Console.WriteLine("-------------------------------------------------------------");
 }
Esempio n. 2
0
        public override Procedure VisitProcedure(Procedure node)
        {
            // Make sure not to visit the same Procedure twice
            if (allProcs.Contains(node.Name))
            {
                return(node);
            }
            allProcs.Add(node.Name);

            if (node.Name.Equals(mainProcName))
            {
                mainProcExists = true;

                /*
                 * // Check if this guy takes input parameters
                 * if (node.InParams.Length != 0)
                 * {
                 *  throw new InvalidProg("main procedure " + node.Name + " has input paramters");
                 * }
                 *
                 * if (node.OutParams.Length != 0)
                 * {
                 *  Console.WriteLine("Warning: output parameters of the main procedure will be ignored");
                 * }
                 */
            }

            // Keep record of all modified globals
            foreach (IdentifierExpr ie in node.Modifies)
            {
                GlobalVariable g = (GlobalVariable)ie.Decl;
                if (g == null)
                {
                    continue;
                }
                if (!modifiedGlobals.ContainsKey(g.Name))
                {
                    modifiedGlobals.Add(g.Name, g);
                }
            }

            // No need to go down into a procedure
            //node.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
            //node.InParams = this.VisitVariableSeq(node.InParams);
            //node.OutParams = this.VisitVariableSeq(node.OutParams);

            if (node.Name == LanguageSemantics.getThreadIDName() ||
                node.Name == LanguageSemantics.getChildThreadIDName())
            {
                Debug.Assert(node.OutParams.Count == 1);
                if (node.OutParams[0].TypedIdent.Type.IsBv)
                {
                    threadIdType = node.OutParams[0].TypedIdent.Type;
                }
            }

            return(node);
        }
Esempio n. 3
0
        public InstrumentationPolicy(int K, HashSet <string> glob, HashSet <string> procsWithImpl, HashSet <string> asyncProcs, HashSet <Tuple <string, string> > recursiveProcs, ConcurrencyMode mode)
        {
            executionContextBound = K;
            globalsToInstrument   = glob;
            this.procsWithImpl    = procsWithImpl;
            this.asyncProcs       = asyncProcs;
            this.recursiveProcs   = recursiveProcs;
            this.mode             = mode;

            atomicBeginProcName    = LanguageSemantics.atomicBeginProcName();
            atomicEndProcName      = LanguageSemantics.atomicEndProcName();
            assertNotReachableName = LanguageSemantics.assertNotReachableName();
            getThreadIDName        = LanguageSemantics.getThreadIDName();
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        // Return the set of all procedures that can trasitively reach
        // an assertion, or another procedure's requires
        private HashSet <string> procsWithAssertions(Program program)
        {
            // Build a call graph and mark procedures with assertions in them
            Dictionary <string, HashSet <string> > callSucc = new Dictionary <string, HashSet <string> >();
            Dictionary <string, HashSet <string> > callPred = new Dictionary <string, HashSet <string> >();
            HashSet <string> hasAssert = new HashSet <string>();

            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Implementation)
                {
                    var impl = decl as Implementation;
                    callSucc.Add(impl.Name, new HashSet <string>());

                    foreach (var block in impl.Blocks)
                    {
                        foreach (var cmd in block.Cmds)
                        {
                            if (cmd is AssertCmd)
                            {
                                hasAssert.Add(impl.Name);
                            }
                            if (cmd is CallCmd)
                            {
                                var ccmd = cmd as CallCmd;
                                callSucc[impl.Name].Add(ccmd.Proc.Name);
                                if (LanguageSemantics.assertNotReachableName() == ccmd.Proc.Name)
                                {
                                    hasAssert.Add(impl.Name);
                                }
                            }
                        }
                    }
                }
            }

            // Build the predecessor map
            foreach (var kvp in callSucc)
            {
                if (!callPred.ContainsKey(kvp.Key))
                {
                    callPred.Add(kvp.Key, new HashSet <string>());
                }

                foreach (var tgt in kvp.Value)
                {
                    if (!callPred.ContainsKey(tgt))
                    {
                        callPred.Add(tgt, new HashSet <string>());
                    }
                    callPred[tgt].Add(kvp.Key);
                }
            }

            // Requires become asserts on the caller.
            // (No need to bother about ensures because if we're not interested
            // in a procedure, then we don't care about verifying its ensures either)
            foreach (var decl in program.TopLevelDeclarations)
            {
                if (decl is Procedure)
                {
                    var proc = decl as Procedure;

                    foreach (Requires re in proc.Requires)
                    {
                        if (re.Free)
                        {
                            continue;
                        }
                        if (!callPred.ContainsKey(proc.Name))
                        {
                            continue;
                        }

                        foreach (var pred in callPred[proc.Name])
                        {
                            hasAssert.Add(pred);
                        }
                    }
                }
            }

            // Now propagate hasAssert to all its predecessors
            var done = false;

            while (!done)
            {
                var newproc = new HashSet <string>();
                foreach (var proc in hasAssert)
                {
                    foreach (var pred in callPred[proc])
                    {
                        newproc.Add(pred);
                    }
                }

                if (newproc.Any(x => !hasAssert.Contains(x)))
                {
                    hasAssert.UnionWith(newproc);
                }
                else
                {
                    done = true;
                }
            }
            return(hasAssert);
        }
Esempio n. 6
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);
        }
Esempio n. 7
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");
                }
            }
        }