Esempio n. 1
0
        static Graph <Function> BuildFunctionCallGraph(Microsoft.Armada.Program program)
        {
            Graph <Function>   functionCallGraph = new Graph <Function>();
            FunctionCallFinder callFinder        = new FunctionCallFinder();

            foreach (var module in program.Modules())
            {
                foreach (var decl in module.TopLevelDecls)
                {
                    if (decl is ClassDecl)
                    {
                        var c = (ClassDecl)decl;
                        foreach (var member in c.Members)
                        {
                            if (member is Function)
                            {
                                var f = (Function)member;

                                List <Function> calls = new List <Function>();
                                foreach (var e in f.Reads)
                                {
                                    if (e != null && e.E != null)
                                    {
                                        callFinder.Visit(e.E, calls);
                                    }
                                }
                                foreach (var e in f.Req)
                                {
                                    if (e != null)
                                    {
                                        callFinder.Visit(e, calls);
                                    }
                                }
                                foreach (var e in f.Ens)
                                {
                                    if (e != null)
                                    {
                                        callFinder.Visit(e, calls);
                                    }
                                }
                                if (f.Body != null)
                                {
                                    callFinder.Visit(f.Body, calls);
                                }

                                foreach (var callee in calls)
                                {
                                    functionCallGraph.AddEdge(f, callee);
                                }
                            }
                        }
                    }
                }
            }

            return(functionCallGraph);
        }
Esempio n. 2
0
        /// <summary>
        /// Prints the program's function call graph in a format suitable for consumption in other tools
        /// </summary>
        public static void PrintFunctionCallGraph(Microsoft.Armada.Program program)
        {
            var functionCallGraph = BuildFunctionCallGraph(program);

            foreach (var vertex in functionCallGraph.GetVertices())
            {
                var func = vertex.N;
                Console.Write("{0},{1}=", func.CompileName, func.EnclosingClass.Module.CompileName);
                foreach (var callee in vertex.Successors)
                {
                    Console.Write("{0} ", callee.N.CompileName);
                }
                Console.Write("\n");
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Microsoft.Armada.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Assert(dafnyProgramName != null);
            Console.WriteLine("Running CompileDafnyProgram : {0}", dafnyProgramName);
            Console.WriteLine("Number of modules = {0}", dafnyProgram.CompileModules.Count);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Microsoft.Armada.Compiler compiler;

            switch (ArmadaOptions.O.CompileTarget)
            {
            case ArmadaOptions.CompilationTarget.Clight:
            default:
                compiler = new Microsoft.Armada.ClightTsoCompiler(dafnyProgram.reporter, otherFileNames);
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            string targetProgramText;
            var    otherFiles = new Dictionary <string, string>();
            {
                var fileQueue = new Queue <FileTargetWriter>();
                using (var wr = new TargetWriter(0)) {
                    compiler.Compile(dafnyProgram, wr);
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    targetProgramText = sw.ToString();
                }

                while (fileQueue.Count > 0)
                {
                    var wr = fileQueue.Dequeue();
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    otherFiles.Add(wr.Filename, sw.ToString());
                }
            }
            string baseName   = Path.GetFileNameWithoutExtension(dafnyProgramName);
            string callToMain = null;

            if (hasMain)
            {
                using (var wr = new TargetWriter(0)) {
                    compiler.EmitCallToMain(mainMethod, wr);
                    callToMain = wr.ToString(); // assume there aren't multiple files just to call main
                }
            }
            bool completeProgram = dafnyProgram.reporter.Count(ErrorLevel.Error) == oldErrorCount;

            // blurt out the code to a file, if requested, or if other files were specified for the C# command line.
            string targetFilename = null;

            if (ArmadaOptions.O.SpillTargetCode > 0 || otherFileNames.Count > 0 || (invokeCompiler && !compiler.SupportsInMemoryCompilation))
            {
                var p = callToMain == null ? targetProgramText : targetProgramText + callToMain;
                targetFilename = WriteDafnyProgramToFiles(dafnyProgramName, p, completeProgram, otherFiles, outputWriter);
            }

            // compile the program into an assembly
            if (!completeProgram || !invokeCompiler)
            {
                // don't compile
                // Caller interprets this as success/fail and returns an error if false,
                //  but we didn't actually hit an error, we just didn't invoke the compiler
                return(true);
            }

            // compile the program into an assembly
            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames,
                                                                     hasMain, hasMain && ArmadaOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && ArmadaOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    if (ArmadaOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Running...");
                        outputWriter.WriteLine();
                    }
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
                else
                {
                    // make sure to give some feedback to the user
                    if (ArmadaOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Program compiled successfully");
                    }
                }
            }
            return(compiledCorrectly);
        }
Esempio n. 4
0
        /// <summary>
        /// Compute various interesting statistics about the Dafny program
        /// </summary>
        public static void PrintStats(Microsoft.Armada.Program program)
        {
            SortedDictionary <string, ulong> stats = new SortedDictionary <string, ulong>();

            foreach (var module in program.Modules())
            {
                IncrementStat(stats, "Modules");
                UpdateMax(stats, "Module height (max)", (ulong)module.Height);

                ulong num_scc = (ulong)module.CallGraph.TopologicallySortedComponents().Count;
                UpdateMax(stats, "Call graph width (max)", num_scc);

                foreach (var decl in module.TopLevelDecls)
                {
                    if (decl is DatatypeDecl)
                    {
                        IncrementStat(stats, "Datatypes");
                    }
                    else if (decl is ClassDecl)
                    {
                        var c = (ClassDecl)decl;
                        if (c.Name != "_default")
                        {
                            IncrementStat(stats, "Classes");
                        }

                        foreach (var member in c.Members)
                        {
                            if (member is Function)
                            {
                                IncrementStat(stats, "Functions (total)");
                                var f = (Function)member;
                                if (f.IsRecursive)
                                {
                                    IncrementStat(stats, "Functions recursive");
                                }
                            }
                            else if (member is Method)
                            {
                                IncrementStat(stats, "Methods (total)");
                                var method = (Method)member;
                                if (method.IsRecursive)
                                {
                                    IncrementStat(stats, "Methods recursive");
                                }
                                if (method.IsGhost)
                                {
                                    IncrementStat(stats, "Methods ghost");
                                }
                            }
                        }
                    }
                }
            }

            // Print out the results, with some nice formatting
            Console.WriteLine("");
            Console.WriteLine("Statistics");
            Console.WriteLine("----------");

            int max_key_length = 0;

            foreach (var key in stats.Keys)
            {
                if (key.Length > max_key_length)
                {
                    max_key_length = key.Length;
                }
            }

            foreach (var keypair in stats)
            {
                string keyString = keypair.Key.PadRight(max_key_length + 2);
                Console.WriteLine("{0} {1,4}", keyString, keypair.Value);
            }
        }