Exemplo n.º 1
0
        public static bool Verify(Dafny.Program dafnyProgram, ResolverTagger resolver, string uniqueIdPrefix, string requestId, ErrorReporterDelegate er)
        {
            Dafny.Translator translator = new Dafny.Translator(dafnyProgram.reporter, er);
            translator.InsertChecksums = true;
            translator.UniqueIdPrefix  = uniqueIdPrefix;
            Bpl.Program boogieProgram = translator.Translate(dafnyProgram);

            resolver.ReInitializeVerificationErrors(requestId, boogieProgram.Implementations);

            // TODO(wuestholz): Maybe we should use a fixed program ID to limit the memory overhead due to the program cache in Boogie.
            PipelineOutcome oc = BoogiePipeline(boogieProgram, 1 < Dafny.DafnyOptions.Clo.VerifySnapshots ? uniqueIdPrefix : null, requestId, er);

            switch (oc)
            {
            case PipelineOutcome.Done:
            case PipelineOutcome.VerificationCompleted:
                // TODO:  This would be the place to proceed to compile the program, if desired
                return(true);

            case PipelineOutcome.FatalError:
            default:
                return(false);
            }
        }
Exemplo n.º 2
0
 public virtual Program VisitProgram(Program node) {
   Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Program>() != null);
   var decls = node.TopLevelDeclarations.ToList();
   node.ClearTopLevelDeclarations();
   node.AddTopLevelDeclarations(this.VisitDeclarationList(decls));
   return node;
 }
Exemplo n.º 3
0
 public ProgramModification(Program program, string procedure)
 {
     this.program   = DeepCloneProgram(program);
     this.procedure = procedure;
 }
Exemplo n.º 4
0
            public bool RunOn(Microsoft.Boogie.Program prog, PassInfo passInfo)
            {
                var toRemove      = new HashSet <Declaration>();
                var implToFalsify = new List <Implementation>();
                var procToKeep    = new HashSet <Declaration>();

                // Check there is at least one entry point
                bool containsEntryPoint = false;

                foreach (var impl in prog.TopLevelDeclarations.OfType <Implementation>())
                {
                    if (IsEntryPoint(impl))
                    {
                        containsEntryPoint = true;
                        break;
                    }
                }

                if (!containsEntryPoint)
                {
                    throw new EntryPointNotFoundException();
                }

                // Determine which implementation we want to remove and
                // which implementations we will need to keep
                foreach (var decl in prog.TopLevelDeclarations)
                {
                    var declAsImplementation = decl as Implementation;
                    if (declAsImplementation == null)
                    {
                        continue;
                    }

                    if (!IsEntryPoint(declAsImplementation))
                    {
                        // We want to remove this implementation
                        toRemove.Add(declAsImplementation);
                    }
                    else
                    {
                        implToFalsify.Add(declAsImplementation);
                        Debug.Assert(declAsImplementation.Proc != null);
                        procToKeep.Add(declAsImplementation.Proc);
                    }
                }

                // Determine which procedures we should remove
                foreach (var decl in prog.TopLevelDeclarations)
                {
                    var declAsProc = decl as Procedure;
                    if (declAsProc == null)
                    {
                        continue;
                    }

                    if (!procToKeep.Contains(declAsProc))
                    {
                        toRemove.Add(declAsProc);
                    }
                }

                // Now remove the procedures and implementations we don't need
                foreach (var decl in toRemove)
                {
                    prog.RemoveTopLevelDeclaration(decl);
                }

                // Now change entry point bodies to just contain an "assert false"
                foreach (var impl in implToFalsify)
                {
                    // Remove any ensures. We probably aren't maintaining it
                    // any more if we remove the body.
                    impl.Proc.Ensures.Clear();

                    // The body won't be modifying anything so clear the modset
                    impl.Proc.Modifies.Clear();

                    // Remove existing blocks
                    impl.Blocks.Clear();

                    // Add block that asserts false and then returns
                    var newBlock = new Block(Token.NoToken,
                                             "entry",
                                             new List <Cmd>()
                    {
                        new AssertCmd(Token.NoToken, Expr.False)
                    },
                                             new ReturnCmd(Token.NoToken));
                    impl.Blocks.Add(newBlock);
                }

                return((toRemove.Count + implToFalsify.Count) > 0);
            }
Exemplo n.º 5
0
 internal Program(Microsoft.Boogie.Program boogieProgram)
     : base(null)
 {
     this.boogieProgram = boogieProgram;
 }
Exemplo n.º 6
0
 public static Expr FunctionCallReresolvingApply(Substitution always, Substitution forOld, Expr expr, Program program)
 {
   Contract.Requires(always != null);
   Contract.Requires(forOld != null);
   Contract.Requires(expr != null);
   Contract.Ensures(Contract.Result<Expr>() != null);
   return (Expr)new FunctionCallReresolvingNormalSubstituter(program, always, forOld).Visit(expr);
 }
Exemplo n.º 7
0
 private bool Translate()
 {
     var translator = new Dafny.Translator(reporter) { InsertChecksums = true, UniqueIdPrefix = fname };
       boogieProgram = translator.Translate(dafnyProgram); // FIXME how are translation errors reported?
       return true;
 }
Exemplo n.º 8
0
        static ExitValue ProcessFiles(IList <string /*!*/> /*!*/ dafnyFileNames, ReadOnlyCollection <string> otherFileNames,
                                      ErrorReporter reporter, bool lookForSnapshots = true, string programId = null)
        {
            Contract.Requires(cce.NonNullElements(dafnyFileNames));

            ExitValue exitValue = ExitValue.VERIFIED;

            if (CommandLineOptions.Clo.VerifySeparately && 1 < dafnyFileNames.Count)
            {
                foreach (var f in dafnyFileNames)
                {
                    string extension = Path.GetExtension(f);
                    if (extension != null)
                    {
                        extension = extension.ToLower();
                    }
                    if (extension != ".dfy")
                    {
                        continue;
                    }
                    Console.WriteLine();
                    Console.WriteLine("-------------------- {0} --------------------", f);
                    var ev = ProcessFiles(new List <string> {
                        f
                    }, new List <string>().AsReadOnly(), reporter, lookForSnapshots, f);
                    if (exitValue != ev && ev != ExitValue.VERIFIED)
                    {
                        exitValue = ev;
                    }
                }
                return(exitValue);
            }

            if (0 <= CommandLineOptions.Clo.VerifySnapshots && lookForSnapshots)
            {
                var snapshotsByVersion = ExecutionEngine.LookForSnapshots(dafnyFileNames);
                foreach (var s in snapshotsByVersion)
                {
                    var ev = ProcessFiles(new List <string>(s), new List <string>().AsReadOnly(), reporter, false, programId);
                    if (exitValue != ev && ev != ExitValue.VERIFIED)
                    {
                        exitValue = ev;
                    }
                }
                return(exitValue);
            }

            Dafny.Program dafnyProgram;
            Resolver      r           = null;
            string        programName = dafnyFileNames.Count == 1 ? dafnyFileNames[0] : "the program";

            //Same as ParseCheck, except for the instance of out Resolver
            string err = Dafny.Main.Parse(dafnyFileNames, programName, reporter, out dafnyProgram);

            if (err == null)
            {
                err = Dafny.Main.Resolve(dafnyProgram, reporter, out r);
            }

            if (err != null)
            {
                exitValue = ExitValue.DAFNY_ERROR;
                ExecutionEngine.printer.ErrorWriteLine(Console.Out, err);
            }
            else if (dafnyProgram != null && !CommandLineOptions.Clo.NoResolve && !CommandLineOptions.Clo.NoTypecheck &&
                     DafnyOptions.O.DafnyVerify)
            {
                Bpl.Program boogieProgram = Translate(dafnyProgram, r);


                PipelineStatistics stats;
                PipelineOutcome    oc;
                var verified = Boogie(dafnyFileNames, boogieProgram, programId, out stats, out oc);

                Compile(dafnyFileNames[0], otherFileNames, dafnyProgram, oc, stats, verified);

                exitValue = verified ? ExitValue.VERIFIED : ExitValue.NOT_VERIFIED;
            }

            if (err == null && dafnyProgram != null && DafnyOptions.O.PrintStats)
            {
                Util.PrintStats(dafnyProgram);
            }
            if (err == null && dafnyProgram != null && DafnyOptions.O.PrintFunctionCallGraph)
            {
                Util.PrintFunctionCallGraph(dafnyProgram);
            }
            return(exitValue);
        }
Exemplo n.º 9
0
 public virtual Program VisitProgram(Program node)
 {
     Contract.Requires(node != null);
       Contract.Ensures(Contract.Result<Program>() != null);
       node.TopLevelDeclarations = this.VisitDeclarationList(node.TopLevelDeclarations);
       return node;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Returns two things: an object that determines the heap representation,
 /// and (optionally) an initial program that contains declarations needed
 /// for the heap representation.
 /// </summary>
 /// <param name="sink">
 /// The heap might need to generate declarations so it needs access to the Sink.
 /// </param>
 /// <returns>
 /// false if and only if an error occurrs and the heap and/or program are not in a
 /// good state to be used.
 /// </returns>
 public abstract bool MakeHeap(Sink sink, out Heap heap, out Bpl.Program /*?*/ program);
Exemplo n.º 11
0
        internal static bool ParsePrelude(string initialPreludeText, object instance, out Bpl.Program /*?*/ prelude)
        {
            prelude = null;

            var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            var type  = instance.GetType();

            FieldInfo /*?*/[]   fields = type.GetFields(flags);
            RepresentationFor[] rfs    = new RepresentationFor[fields.Length];
            for (int i = 0; i < fields.Length; i++)
            {
                var      field = fields[i];
                object[] cas   = field.GetCustomAttributes(typeof(RepresentationFor), false);
                if (cas == null || cas.Length == 0) // only look at fields that have the attribute
                {
                    fields[i] = null;
                }
                else
                {
                    foreach (var a in cas) // should be exactly one
                    {
                        RepresentationFor rf = a as RepresentationFor;
                        if (rf != null)
                        {
                            rfs[i] = rf;
                            break;
                        }
                    }
                }
            }

            #region Gather all of the Boogie declarations from the fields of this class
            var preludeText = new StringBuilder(initialPreludeText);
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                if (field == null)
                {
                    continue;
                }
                preludeText.AppendLine(rfs[i].declaration);
            }
            #endregion

            #region Parse the declarations
            int errorCount = Bpl.Parser.Parse(preludeText.ToString(), "foo", out prelude);
            if (prelude == null || errorCount > 0)
            {
                prelude = null;
                return(false);
            }
            #endregion

            #region Use the compiled program to get the ASTs
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                if (field == null)
                {
                    continue;
                }
                if (!rfs[i].required)
                {
                    continue;
                }
                var val = prelude.TopLevelDeclarations.First(d => { Bpl.NamedDeclaration nd = d as Bpl.NamedDeclaration; return(nd != null && nd.Name.Equals(rfs[i].name)); });
                field.SetValue(instance, val);
            }
            #endregion

            #region Check that every field in this class has been set
            for (int i = 0; i < fields.Length; i++)
            {
                var field = fields[i];
                if (field == null)
                {
                    continue;
                }
                if (!rfs[i].required)
                {
                    continue;
                }
                if (field.GetValue(instance) == null)
                {
                    return(false);
                }
            }
            #endregion Check that every field in this class has been set

            return(true);
        }
Exemplo n.º 12
0
 public override Program VisitProgram(Program node) {
   //Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Program>() != null);
   return base.VisitProgram((Program)node.Clone());
 }
Exemplo n.º 13
0
        public static Program makeProgram(Microsoft.Boogie.Program boogieProgram)
        {
            var pf = new ProgramFactory();

            return(pf.makeProgram(boogieProgram));
        }
Exemplo n.º 14
0
 public override Program VisitProgram(Program node)
 {
     Contract.Ensures(Contract.Result<Program>() == node);
     this.VisitDeclarationList(node.TopLevelDeclarations.ToList());
     return node;
 }
Exemplo n.º 15
0
        /// <summary>
        /// The entry point of the program.
        /// </summary>
        /// <param name="args">The command line arguments.</param>
        public static void Main(string[] args)
        {
            int?statusCode = null;

            try
            {
                // standard command line options for Boogie
                CommandLineOptions.Install(new GRCommandLineOptions());
                if (!CommandLineOptions.Clo.Parse(args))
                {
                    return;
                }

                CommandLineOptions.Clo.PrintUnstructured    = 2;
                CommandLineOptions.Clo.DoModSetAnalysis     = true;
                CommandLineOptions.Clo.PruneInfeasibleEdges = true;

                if (!CommandLineOptions.Clo.Files.Any())
                {
                    throw new Exception("An input file must be provided!");
                }
                else if (CommandLineOptions.Clo.Files.Count > 1)
                {
                    throw new Exception("GPURepair can work on only one file at a time!");
                }

                Logger.FileName        = CommandLineOptions.Clo.Files.First();
                Logger.DetailedLogging = ((GRCommandLineOptions)CommandLineOptions.Clo).DetailedLogging;

                ClauseLogger.FileName   = CommandLineOptions.Clo.Files.First();
                ClauseLogger.LogCLauses = ((GRCommandLineOptions)CommandLineOptions.Clo).LogClauses;

                Barrier.LoopDepthWeight   = ((GRCommandLineOptions)CommandLineOptions.Clo).LoopDepthWeight;
                Barrier.GridBarrierWeight = ((GRCommandLineOptions)CommandLineOptions.Clo).GridBarrierWeight;

                Dictionary <string, bool> assignments;

                // repair the program
                Solver.SolverType solverType = ((GRCommandLineOptions)CommandLineOptions.Clo).SolverType;
                bool disableInspection       = ((GRCommandLineOptions)CommandLineOptions.Clo).DisableInspection;
                bool useAxioms = ((GRCommandLineOptions)CommandLineOptions.Clo).UseAxioms;

                Repairer repairer = new Repairer(Logger.FileName, disableInspection, useAxioms);
                Microsoft.Boogie.Program program = repairer.Repair(solverType, out assignments);

                SummaryGenerator     generator = new SummaryGenerator();
                IEnumerable <string> changes   = generator.GenerateSummary(assignments,
                                                                           Logger.FileName.Replace(".cbpl", ".summary"));

                Logger.Log($"Changes;{changes.Count()}");
                Console.WriteLine("Number of changes required: {0}.", changes.Count());

                if (changes.Any())
                {
                    using (TokenTextWriter writer = new TokenTextWriter(Logger.FileName.Replace(".cbpl", ".fixed.cbpl"), true))
                        program.Emit(writer);
                }
            }
            catch (Exception ex)
            {
                Logger.Log($"ExceptionMessage;{ex.Message}");
                Console.Error.WriteLine(ex.Message);

                if (ex is AssertionException)
                {
                    statusCode = 201;
                }
                else if (ex is RepairException)
                {
                    statusCode = 202;
                }
                else if (ex is NonBarrierException)
                {
                    statusCode = 203;
                }
                else if (ex is SummaryGeneratorException)
                {
                    statusCode = 204;
                }
            }

            if (statusCode != null)
            {
                Environment.Exit(statusCode.Value);
            }
        }
Exemplo n.º 16
0
 /// <summary>
 /// Creates an analysis context using information from the given analysis context.
 /// </summary>
 /// <param name="program">Program</param>
 /// <param name="rc">ResolutionContext</param>
 /// <returns>AnalysisContext</returns>
 internal static AnalysisContext Create(Microsoft.Boogie.Program program, ResolutionContext rc)
 {
     return(new AnalysisContext(program, rc));
 }
Exemplo n.º 17
0
        static ExitValue ProcessFiles(IList <string /*!*/> /*!*/ dafnyFileNames, ReadOnlyCollection <string> otherFileNames,
                                      ErrorReporter reporter, bool lookForSnapshots = true, string programId = null)
        {
            Contract.Requires(cce.NonNullElements(dafnyFileNames));

            if (programId == null)
            {
                programId = "main_program_id";
            }

            ExitValue exitValue = ExitValue.VERIFIED;

            if (CommandLineOptions.Clo.VerifySeparately && 1 < dafnyFileNames.Count)
            {
                foreach (var f in dafnyFileNames)
                {
                    string extension = Path.GetExtension(f);
                    if (extension != null)
                    {
                        extension = extension.ToLower();
                    }
                    if (extension != ".dfy")
                    {
                        continue;
                    }
                    Console.WriteLine();
                    Console.WriteLine("-------------------- {0} --------------------", f);
                    var ev = ProcessFiles(new List <string> {
                        f
                    }, new List <string>().AsReadOnly(), reporter, lookForSnapshots, f);
                    if (exitValue != ev && ev != ExitValue.VERIFIED)
                    {
                        exitValue = ev;
                    }
                }
                return(exitValue);
            }

            if (0 <= CommandLineOptions.Clo.VerifySnapshots && lookForSnapshots)
            {
                var snapshotsByVersion = ExecutionEngine.LookForSnapshots(dafnyFileNames);
                foreach (var s in snapshotsByVersion)
                {
                    var ev = ProcessFiles(new List <string>(s), new List <string>().AsReadOnly(), reporter, false, programId);
                    if (exitValue != ev && ev != ExitValue.VERIFIED)
                    {
                        exitValue = ev;
                    }
                }
                return(exitValue);
            }

            using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, dafnyFileNames[dafnyFileNames.Count - 1])) {
                Dafny.Program dafnyProgram;
                string        programName = dafnyFileNames.Count == 1 ? dafnyFileNames[0] : "the program";
                string        err         = Dafny.Main.ParseCheck(dafnyFileNames, programName, reporter, out dafnyProgram);
                if (err != null)
                {
                    exitValue = ExitValue.DAFNY_ERROR;
                    ExecutionEngine.printer.ErrorWriteLine(Console.Out, err);
                }
                else if (dafnyProgram != null && !CommandLineOptions.Clo.NoResolve && !CommandLineOptions.Clo.NoTypecheck &&
                         DafnyOptions.O.DafnyVerify)
                {
                    Dafny.Translator translator    = new Dafny.Translator(dafnyProgram.reporter);
                    Bpl.Program      boogieProgram = translator.Translate(dafnyProgram);
                    if (CommandLineOptions.Clo.PrintFile != null)
                    {
                        ExecutionEngine.PrintBplFile(CommandLineOptions.Clo.PrintFile, boogieProgram, false, false, CommandLineOptions.Clo.PrettyPrint);
                    }

                    string bplFilename;
                    if (CommandLineOptions.Clo.PrintFile != null)
                    {
                        bplFilename = CommandLineOptions.Clo.PrintFile;
                    }
                    else
                    {
                        string baseName = cce.NonNull(Path.GetFileName(dafnyFileNames[dafnyFileNames.Count - 1]));
                        baseName    = cce.NonNull(Path.ChangeExtension(baseName, "bpl"));
                        bplFilename = Path.Combine(Path.GetTempPath(), baseName);
                    }

                    PipelineStatistics stats = null;
                    PipelineOutcome    oc    = BoogiePipelineWithRerun(boogieProgram, bplFilename, out stats, 1 < Dafny.DafnyOptions.Clo.VerifySnapshots ? programId : null);
                    var allOk          = stats.ErrorCount == 0 && stats.InconclusiveCount == 0 && stats.TimeoutCount == 0 && stats.OutOfMemoryCount == 0;
                    var resultFileName = DafnyOptions.O.DafnyPrintCompiledFile ?? dafnyFileNames[0];
                    switch (oc)
                    {
                    case PipelineOutcome.VerificationCompleted:
                        ExecutionEngine.printer.WriteTrailer(stats);
                        if ((DafnyOptions.O.Compile && allOk && CommandLineOptions.Clo.ProcsToCheck == null) || DafnyOptions.O.ForceCompile)
                        {
                            CompileDafnyProgram(dafnyProgram, resultFileName, otherFileNames);
                        }
                        break;

                    case PipelineOutcome.Done:
                        ExecutionEngine.printer.WriteTrailer(stats);
                        if (DafnyOptions.O.ForceCompile)
                        {
                            CompileDafnyProgram(dafnyProgram, resultFileName, otherFileNames);
                        }
                        break;

                    default:
                        // error has already been reported to user
                        break;
                    }
                    exitValue = allOk ? ExitValue.VERIFIED : ExitValue.NOT_VERIFIED;
                }

                if (err == null && dafnyProgram != null && DafnyOptions.O.PrintStats)
                {
                    Util.PrintStats(dafnyProgram);
                }
                if (err == null && dafnyProgram != null && DafnyOptions.O.PrintFunctionCallGraph)
                {
                    Util.PrintFunctionCallGraph(dafnyProgram);
                }
            }
            return(exitValue);
        }
Exemplo n.º 18
0
        public CFG <BasicBlock, BasicEdge> getCFGFromDAG(Implementation imp, Program program)
        {
//            Console.WriteLine("getCFGFromDAG");
            cfg        = new CFG <BasicBlock, BasicEdge>();
            entry      = cfg.addNode("$start");
            exit       = cfg.addNode("$exit");
            labelIndex = 0;

//            Console.WriteLine("\t\t\tDeclarations");
            foreach (var tld in program.TopLevelDeclarations)
            {
                var a = tld as Axiom;
                if (a != null)
                {
//                    Console.WriteLine("\t\tAdding axiom {0}",a.Expr.ToString());
                    var assume = new Assume(procedure.expressionFactory.makeExpression(a.Expr));
                    entry.appendStatement(assume);
                }
                else
                {
                    var bf = tld as Function;
                    if (bf != null && bf.Body != null)
                    {
                        var ft = scope.findFunctionTemplate(bf.Name);
                        var b  = ft.body;
                        Debug.Assert(b != null);

                        var eqF    = BFunctionTemplate.eq.getInstance(TypeTuple.make(new[] { ft.signature.resultType }));
                        var lhs    = new BasicFAE(ft.getInstance(TypeTuple.make(from tv in ft.typeParameters select new VariableType(tv))), new ExpressionList(from bv in b.arguments select new BasicBoundVariableExpression(bv)));
                        var eqe    = new BasicFAE(eqF, new ExpressionList(lhs, b.expression));
                        var axiom  = procedure.expressionFactory.makeSentence(eqe);
                        var assume = new Assume(axiom);
                        entry.appendStatement(assume);
                    }
                }
            }

//            Console.WriteLine("\t\t\tBlocks");
//            var topoSortedBlocks
            foreach (var b in topoSort(imp.Blocks, imp.Blocks[0]))
            {
                addBlock(b);
            }
            BasicBlock start = cfg.lookupOrAddNode(imp.Blocks[0].Label);

            entry.setControlStatement(new UnconditionalBranch(entry, start));
            exit.setControlStatement(new Programs.Statements.Block(exit));

            cfg.setStartNode("$start");
            cfg.setEndNode("$exit");

            foreach (var bb in cfg.nodes)
            {
                if (!ReferenceEquals(bb, exit) && bb.successors.Count == 0)
                {
                    bb.setControlStatement(new UnconditionalBranch(bb, exit));
                }
            }

            foreach (var bb in cfg.nodes)
            {
                if (!ReferenceEquals(bb, entry) && bb.predecessors.Count == 0)
                {
                    Console.WriteLine("Warning - removing orphan - {0}", bb.label);
                    bb.setControlStatement(new Programs.Statements.Block(bb));
                    bb.delete();
                }
            }

            return(cfg);
        }
Exemplo n.º 19
0
        public bpl.Program split(bpl.Program prog)
        {
            originalProgram = prog;
            ////////////////// First identify the thread entries in the program ////////////////////
            // A procedure is a thread entry if there is any async call to it
            HashSet <string> threadEntries = new HashSet <string>();
            var impls = new Func <bpl.Program, IEnumerable <bpl.Implementation> >(p => from impl in p.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation);

            foreach (var impl in impls(originalProgram))
            {
                var cmdsRaw    = from blk in impl.Blocks select blk.Cmds;
                var cmds       = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); });
                var asyncCalls = from cmd in cmds where  con.isAsyncCall(cmd as bpl.Cmd) select cmd;
                foreach (bpl.Cmd asyncCall in asyncCalls)
                {
                    threadEntries.Add((asyncCall as bpl.CallCmd).callee);
                }
            }
            // Finally add the entry function also as a thread entry.
            threadEntries.Add(con.entryFunc);

            //////////////// Next, identify all the procedures belonging to each thread ////////////
            Dictionary <string, HashSet <string> > threadToProcs = new Dictionary <string, HashSet <string> >();
            // This is done in two steps.
            // First step: Find all non-async calls in each procedure.
            var procToCalls = new Dictionary <string, HashSet <string> >();

            //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation;
            foreach (var impl in impls(originalProgram))
            {
                procToCalls[impl.Name] = new HashSet <string>();
                var cmdsRaw   = from blk in impl.Blocks select blk.Cmds;
                var cmds      = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); });
                var syncCalls = from cmd in cmds where con.isSyncCall(cmd as bpl.Cmd) select cmd;
                foreach (bpl.Cmd syncCall in syncCalls)
                {
                    procToCalls[impl.Name].Add((syncCall as bpl.CallCmd).callee);
                }
            }
            // Second step: Find all procedures in each thread.
            foreach (var thr in threadEntries)
            {
                threadToProcs[thr] = new HashSet <string>();
            }
            foreach (var thr in threadEntries)
            {
                findReachable(procToCalls, thr, threadToProcs[thr]);
            }
            //DEBUGGING
            if (dbg)
            {
                System.Console.WriteLine("Threads in the original program:");
                foreach (var iter in threadToProcs)
                {
                    System.Console.Write(iter.Key + ": ");
                    foreach (var proc in iter.Value)
                    {
                        System.Console.Write(proc + " ");
                    }
                    System.Console.WriteLine();
                }
            }


            // [Optional]
            // Remove unreachable procs.
            // These procedures are neither reachable from Main, nor from a thread entry. They can obviously not be called in any execution.
            var reachableProcs = new HashSet <string>();

            foreach (var vals in threadToProcs.Values)
            {
                foreach (var proc in vals)
                {
                    reachableProcs.Add(proc);
                }
            }
            foreach (var val in threadToProcs.Keys)
            {
                reachableProcs.Add(val);
            }
            removeUnreachable(reachableProcs);



            //////////////// Finally, Actually split the procedures when needed //////////////////
            // For every procedure, find out how many threads contain it. We need as many copies of
            // that procedure.
            // Note: We do not want to duplicate procedures without implementation.
            //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation;
            var implNames = from impl in impls(originalProgram) select impl.Name;
            Dictionary <string, int> procCopies = new Dictionary <string, int>();
            var procs = from proc in originalProgram.TopLevelDeclarations where proc is bpl.Procedure select proc as bpl.Procedure;

            foreach (var proc in procs)
            {
                procCopies[proc.Name] = 0;
            }
            foreach (var iter in threadToProcs)
            {
                foreach (var proc in iter.Value)
                {
                    if (implNames.Contains(proc))
                    {
                        procCopies[proc]++;
                    }
                }
            }

            // Now duplicate
            // The new procedures and implementations for each thread
            // thread name --> (old procedure name --> new procedure)
            var newProcsPerThread = new Dictionary <string, Dictionary <string, bpl.Procedure> >();
            // thread name --> (old procedure name --> new implementation)
            var newImplsPerThread = new Dictionary <string, Dictionary <string, bpl.Implementation> >();
            // old name --> proc, old name --> impl
            var oldNameToImpl = new Dictionary <string, bpl.Implementation>();

            foreach (var impl in impls(originalProgram))
            {
                oldNameToImpl[impl.Name] = impl;
            }
            var oldNameToProc = new Dictionary <string, bpl.Procedure>();

            foreach (var proc in procs)
            {
                oldNameToProc[proc.Name] = proc;
            }
            foreach (var elem in threadToProcs)
            {
                string threadName = elem.Key;
                newProcsPerThread[threadName] = new Dictionary <string, bpl.Procedure>();
                newImplsPerThread[threadName] = new Dictionary <string, bpl.Implementation>();
                foreach (var procName in elem.Value)
                {
                    if (procCopies[procName] > 1)
                    {
                        // We will duplicate this procedure.
                        // Make a copy of the procedure and implementation
                        var dup  = new cba.Util.FixedDuplicator();
                        var impl = (bpl.Implementation)dup.VisitDeclaration(oldNameToImpl[procName]);
                        var proc = (bpl.Procedure)dup.VisitDeclaration(oldNameToProc[procName]);
                        impl.Proc = proc;

                        // Rename the new instances using thread id.
                        impl.Name = con.getSplitProcName(procName);
                        proc.Name = con.getSplitProcName(procName);
                        var origProcAttr = con.originalProcAttr(procName);
                        origProcAttr.Next = proc.Attributes;
                        proc.Attributes   = origProcAttr;

                        // Also add an attribute to the definition specifying the thread.
                        var threadAttr = con.getThreadAttr(threadName);
                        threadAttr.Next = proc.Attributes;
                        proc.Attributes = threadAttr;

                        //add to duplicated procedures/impls
                        newProcsPerThread[threadName][procName] = proc;
                        newImplsPerThread[threadName][procName] = impl;

                        //Add to the program
                        originalProgram.AddTopLevelDeclaration(proc);
                        originalProgram.AddTopLevelDeclaration(impl);

                        var s1 = new HashSet <string>();
                        var s2 = new HashSet <string>();
                        foreach (var im in originalProgram.TopLevelDeclarations.OfType <bpl.Implementation>())
                        {
                            s1.Add(im.Name);
                        }
                        foreach (var im in impls(originalProgram))
                        {
                            s2.Add(im.Name);
                        }

                        // We have split away the procedure calls for one thread.
                        procCopies[procName]--;
                    }
                    else if (procCopies[procName] == 1)
                    {
                        //We still need to rename this procedure
                        var impl = oldNameToImpl[procName];
                        var proc = oldNameToProc[procName];

                        //rename the new instances using thread id.
                        impl.Name = con.getSplitProcName(procName);
                        proc.Name = con.getSplitProcName(procName);
                        var origProcAttr = con.originalProcAttr(procName);
                        origProcAttr.Next = proc.Attributes;
                        proc.Attributes   = origProcAttr;

                        // Also add an attribute to the definition specifying the thread.
                        var threadAttr = con.getThreadAttr(threadName);
                        threadAttr.Next = proc.Attributes;
                        proc.Attributes = threadAttr;

                        //add to duplicated procedures/impls
                        newProcsPerThread[threadName][procName] = proc;
                        newImplsPerThread[threadName][procName] = impl;

                        // We have split away the procedure calls for one thread.
                        procCopies[procName]--;
                    }
                }
                // Tell con that we're done with one thread.
                con.nextThread();
            }

            // New re-route procedure calls as needed
            // First async calls.
            foreach (var impl in impls(originalProgram))
            {
                foreach (var blk in impl.Blocks)
                {
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        bpl.Cmd cmd = blk.Cmds[i];
                        if (con.isAsyncCall(cmd))
                        {
                            var callCmd    = cmd as bpl.CallCmd;
                            var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[callCmd.callee][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync);
                            newCallCmd.TypeParameters = callCmd.TypeParameters;
                            newCallCmd.Proc           = newProcsPerThread[callCmd.callee][callCmd.callee];
                            blk.Cmds[i] = newCallCmd;
                        }
                    }
                }
            }
            // Now sync calls.
            foreach (var elem in newImplsPerThread)
            {
                string threadName = elem.Key;
                var    newImpls   = newImplsPerThread[threadName];
                foreach (var implTuple in newImpls)
                {
                    var impl = implTuple.Value;
                    foreach (var blk in impl.Blocks)
                    {
                        for (int i = 0; i < blk.Cmds.Count; ++i)
                        {
                            bpl.Cmd cmd = blk.Cmds[i];
                            if (con.isSyncCall(cmd) && newProcsPerThread[threadName].ContainsKey((cmd as bpl.CallCmd).callee))
                            {
                                var callCmd    = cmd as bpl.CallCmd;
                                var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[threadName][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync);
                                newCallCmd.TypeParameters = callCmd.TypeParameters;
                                newCallCmd.Proc           = newProcsPerThread[threadName][callCmd.callee];
                                blk.Cmds[i] = newCallCmd;
                            }
                        }
                    }
                }
            }

            // Finally, label the entry of each thread as thread entry.
            foreach (var elem in newProcsPerThread)
            {
                var proc            = elem.Value[elem.Key];
                var threadEntryAttr = con.getThreadEntryAttr();
                threadEntryAttr.Next = proc.Attributes;
                proc.Attributes      = threadEntryAttr;
            }

            return(originalProgram);
        }
Exemplo n.º 20
0
    public override Program VisitProgram(Program node) {
      //Contract.Requires(node != null);
      Contract.Ensures(Contract.Result<Program>() != null);

      // If cloning an entire program we need to ensure that
      // Implementation.Proc gets resolved to the right Procedure
      // (i.e. we don't duplicate Procedure twice) and CallCmds
      // call the right Procedure.
      // The map below is used to achieve this.
      OldToNewProcedureMap = new Dictionary<Procedure, Procedure>();
      var newProgram = base.VisitProgram((Program)node.Clone());

      // We need to make sure that CallCmds get resolved to call Procedures we duplicated
      // instead of pointing to procedures in the old program
      var callCmds = newProgram.Blocks().SelectMany(b => b.Cmds).OfType<CallCmd>();
      foreach (var callCmd in callCmds) {
          callCmd.Proc = OldToNewProcedureMap[callCmd.Proc];
      }

      OldToNewProcedureMap = null; // This Visitor could be used for other things later so remove the map.
      return newProgram;
    }
Exemplo n.º 21
0
 /// <summary>
 /// Instantiates an instance of <see cref="ErrorReporter"/>.
 /// </summary>
 /// <param name="program">The program.</param>
 /// <param name="implName">The name of the implementation.</param>
 public ErrorReporter(Microsoft.Boogie.Program program, string implName) : base(program, implName)
 {
 }
Exemplo n.º 22
0
 public FunctionCallReresolvingNormalSubstituter(Program program, Substitution always, Substitution forold)
   : base(always, forold)
 {
   Program = program;
 }
Exemplo n.º 23
0
 /// <summary>
 /// Initilaizes an instance of <see cref="GraphAnalyzer"/>.
 /// </summary>
 /// <param name="program">The boogie program.</param>
 public GraphAnalyzer(Microsoft.Boogie.Program program)
 {
     Graph = new ProgramGraph(program);
 }