예제 #1
0
        public static void Start(ProgramOptions programOptions)
        {
            Console.WriteLine(programOptions);
            Settings.SetProgramOptions(programOptions);
            var outputPath = SetupOutputFile();

            streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.Prelude.bpl"));

            if (Settings.AsyncSupport || Settings.AsyncSupportGenerics)
            {
                streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.CommonAsyncPrelude.bpl"));
            }

            if (Settings.AsyncSupport)
            {
                streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.AsyncPrelude.bpl"));
            }

            if (Settings.AsyncSupportGenerics)
            {
                streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.AsyncPreludeGeneric.bpl"));
            }

            using (var host = new PeReader.DefaultHost())
            {
                #region Load assemblies
                ISet <Assembly> inputAssemblies = new HashSet <Assembly>();
                foreach (string inputFile in Settings.InputFiles)
                {
                    Assembly assembly = new Assembly(host);
                    assembly.Load(inputFile);
                    inputAssemblies.Add(assembly);
                }
                #endregion

                #region Execute CHA
                var CHAnalysis = new ClassHierarchyAnalysis(host);
                CHAnalysis.Analyze();
                #endregion

                #region Initialize host types
                Types.Initialize(host);
                #endregion

                // TODO(diegog): Analysis not integrated yet
                // This can be used to obtain the allocated types and delegates
                //var allocationsAndDelelegatesAnalysis = new TypesAndDelegatesCollector(host);

                #region Write three address code for debugging
                TACWriter.WriteTAC(inputAssemblies);
                #endregion

                #region Look for references (used in mixed memory model)
                if (Settings.MemoryModel == ProgramOptions.MemoryModelOption.Mixed)
                {
                    ReferenceFinder.TraverseForFields(inputAssemblies);
                }
                #endregion

                #region Translate defined types and add axioms about subtyping
                TypeDefinitionTranslator.TranslateTypes(inputAssemblies);
                #endregion

                #region Translate defined methods
                MethodTranslator.TranslateAssemblies(inputAssemblies, CHAnalysis);
                #endregion

                #region Create main wrapper with static fields initialization and static constructors calls
                StaticInitializer.SearchStaticConstructorsAndMain(inputAssemblies);
                streamWriter.WriteLine(StaticInitializer.CreateInitializeGlobals());
                streamWriter.WriteLine(StaticInitializer.CreateMainWrappers());
                streamWriter.WriteLine(StaticInitializer.CreateStaticVariablesAllocProcedure());
                streamWriter.WriteLine(StaticInitializer.CreateDefaultValuesStaticVariablesProcedure());
                streamWriter.WriteLine(StaticInitializer.CreateStaticConstructorsCallsProcedure());
                #endregion

                #region Translate types that are referenced but not defined in the input assemblies
                TypeDefinitionTranslator.DefineUndeclaredSuperClasses();
                TypeDefinitionTranslator.ParametricTypeDeclarations();
                #endregion

                #region Translate string constants
                BoogieLiteral.Strings.WriteStringConsts(streamWriter);
                #endregion

                #region Translate delegates
                streamWriter.WriteLine(DelegateStore.DefineMethodsIdentifiers());
                streamWriter.WriteLine(DelegateStore.CreateDelegateMethod());
                streamWriter.WriteLine(DelegateStore.InvokeDelegateMethod());
                #endregion

                // CreateAllAsyncMethods(streamWriter);
                #region Heuristic to catch getters & setters. If they are in our input assemblies we generate a body using a field associated to that property
                IEnumerable <IMethodReference> usedProperties = new List <IMethodReference>();
                if (Settings.StubGettersSetters || Settings.StubGettersSettersWhitelist.Count > 0)
                {
                    GetterSetterStub getterSetterStub = new GetterSetterStub();
                    usedProperties = getterSetterStub.Stub(inputAssemblies, streamWriter);
                }
                #endregion

                #region Generate stubs for async methods
                if (Settings.AsyncSupport)
                {
                    AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies);
                    streamWriter.WriteLine(asyncStubs.AsyncMethodBuilderStartStub(false));
                    streamWriter.WriteLine(asyncStubs.AsyncStubsScheduleTask(false));
                }

                if (Settings.AsyncSupportGenerics)
                {
                    AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies);
                    streamWriter.WriteLine(asyncStubs.AsyncMethodBuilderStartStub(true));
                    streamWriter.WriteLine(asyncStubs.AsyncStubsScheduleTask(true));
                }

                if (!Settings.AsyncSupport && Settings.AsyncSupportGenerics)
                {
                    // this is only in AsyncSupport prelude
                    // we can't add it to AsyncSupportGenerics because we are not always sure there will be all defined types and functions

                    bool hasEventually = inputAssemblies.GetAllDefinedMethods().Any(m => m.Name.Value.Equals("Eventually"));
                    if (hasEventually)
                    {
                        AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies);
                        streamWriter.WriteLine(asyncStubs.EventuallyStub());
                    }
                }

                #endregion

                streamWriter.WriteLine(StringTranslator.Stubs());

                #region Translate called methods as extern (bodyless methods or methods not present in our input assemblies)

                var externMethods = InstructionTranslator.CalledMethods.Except(inputAssemblies.GetAllDefinedMethods().Where(m => m.Body.Size > 0)).Except(usedProperties);
                externMethods = externMethods.Where(m => !StringTranslator.GetBoogieNamesForStubs().Contains(BoogieMethod.From(m).Name));
                foreach (var methodRef in externMethods)
                {
                    var head = Helpers.GetExternalMethodDefinition(Helpers.GetUnspecializedVersion(methodRef));
                    streamWriter.WriteLine(head);
                }

                #endregion

                #region Translate class fields
                // we declare read or written fields
                foreach (var field in FieldTranslator.GetFieldDefinitions())
                {
                    streamWriter.WriteLine(field);
                }
                #endregion

                streamWriter.Close();

                #region Append bpl input files
                foreach (var bplInputFile in Settings.BplInputFiles)
                {
                    var output = new FileStream(outputPath, FileMode.Append, FileAccess.Write);

                    using (var inputStream = File.OpenRead(bplInputFile))
                    {
                        inputStream.CopyTo(output);
                    }

                    output.Close();
                }
                #endregion
            }
        }
예제 #2
0
        public static void Start(ProgramOptions programOptions)
        {
            Console.WriteLine(programOptions);
            Settings.SetProgramOptions(programOptions);
            var outputPath = SetupOutputFile();

            Prelude.Write(); // writes prelude.bpl content into the output file

            using (var host = TinyBCTHost.NewHost())
            {
                var CHAnalysis = CreateCHAnalysis(host);
                Types.Initialize(host);

                // TODO(diegog): Analysis not integrated yet
                // This can be used to obtain the allocated types and delegates
                var allocationsAndDelelegatesAnalysis = new TypesAndDelegatesCollector(host);
                //allocationsAndDelelegatesAnalysis.Analyze();

                Action <string> writeTAC = (String inputFile) =>
                {
                    using (var assembly = new Assembly(host))
                    {
                        // analysis-net setup
                        assembly.Load(inputFile);

                        TACWriter.Open(inputFile);
                        var visitor = new Traverser(host, assembly.PdbReader, CHAnalysis);
                        visitor.AddMethodDefinitionAction(TACWriter.IMethodDefinitionTraverse); // saves tac code for debugging
                        visitor.Traverse(assembly.Module);
                        TACWriter.Close();
                    }
                };


                ProcessFiles(writeTAC);

                Action <string> translateTypeDefinitions = (String inputFile) =>
                {
                    using (var assembly = new Assembly(host))
                    {
                        // analysis-net setup
                        assembly.Load(inputFile);
                        Types.Initialize(host);

                        var visitor = new Traverser(host, assembly.PdbReader, CHAnalysis);
                        visitor.AddNamedTypeDefinitionAction(TypeDefinitionTranslator.TypeDefinitionTranslatorTraverse); // generates axioms for typing
                        visitor.Traverse(assembly.Module);
                    }
                };

                ProcessFiles(translateTypeDefinitions);


                Action <string> translateMethodDefinitions = (String inputFile) =>
                {
                    using (var assembly = new Assembly(host))
                    {
                        // analysis-net setup
                        assembly.Load(inputFile);
                        Types.Initialize(host);

                        var visitor = new Traverser(host, assembly.PdbReader, CHAnalysis);
                        visitor.AddMethodDefinitionAction(MethodTranslator.IMethodDefinitionTraverse); // given a IMethodDefinition and a MethodBody are passed to a MethodTranslator object
                        visitor.Traverse(assembly.Module);
                    }
                };

                ProcessFiles(translateMethodDefinitions);

                Action <string> translateCallsToStaticConstructors = (String inputFile) =>
                {
                    using (var assembly = new Assembly(host))
                    {
                        // analysis-net setup
                        assembly.Load(inputFile);
                        Types.Initialize(host);

                        var visitor = new Traverser(host, assembly.PdbReader, CHAnalysis);
                        visitor.AddMethodDefinitionAction(StaticInitializer.IMethodDefinitionTraverse); // given a IMethodDefinition and a MethodBody are passed to a MethodTranslator object
                        visitor.Traverse(assembly.Module);
                    }
                };

                ProcessFiles(translateCallsToStaticConstructors);
                streamWriter.WriteLine(StaticInitializer.CreateInitializeGlobals());
                streamWriter.WriteLine(StaticInitializer.CreateMainWrappers());

                // TypeDefinitionTranslator.TypeAxioms(); diego's axioms
                // information stored from previous steps is used
                TypeDefinitionTranslator.DefineUndeclaredSuperClasses();

                BoogieLiteral.Strings.WriteStringConsts(streamWriter);

                streamWriter.WriteLine(DelegateStore.DefineMethodsIdentifiers());
                streamWriter.WriteLine(DelegateStore.CreateDelegateMethod());
                streamWriter.WriteLine(DelegateStore.InvokeDelegateMethod());

                // CreateAllAsyncMethods(streamWriter);



                // extern method called
                foreach (var methodRef in InstructionTranslator.ExternMethodsCalled)
                {
                    var head = Helpers.GetExternalMethodDefinition(Helpers.GetUnspecializedVersion(methodRef));
                    streamWriter.WriteLine(head);
                }
                foreach (var methodRef in InstructionTranslator.PotentiallyMissingMethodsCalled)
                {
                    if (Helpers.IsCurrentlyMissing(methodRef))
                    {
                        var head = Helpers.GetExternalMethodDefinition(Helpers.GetUnspecializedVersion(methodRef));
                        streamWriter.WriteLine(head);
                    }
                }

                // we declare read or written fields
                foreach (var field in FieldTranslator.GetFieldDefinitions())
                {
                    streamWriter.WriteLine(field);
                }

                streamWriter.Close();

                foreach (var bplInputFile in Settings.BplInputFiles)
                {
                    var output = new FileStream(outputPath, FileMode.Append, FileAccess.Write);
                    ////output.WriteLine("// Appending {0}", bplInputFile);
                    ////streamWriter.Flush();

                    using (var inputStream = File.OpenRead(bplInputFile))
                    {
                        inputStream.CopyTo(output);//streamWriter.BaseStream);
                    }

                    output.Close();
                }
            }
        }