예제 #1
0
        public static void CompileMethodBodies(
            CSharpCompilation compilation,
            PEModuleBuilder moduleBeingBuilt,
            bool generateDebugInfo,
            bool hasDeclarationErrors,
            Predicate <Symbol> filter,
            SyntaxTree filterTree,
            TextSpan?filterSpanWithinTree,
            DiagnosticBag diagnostics,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.CSharp_Compiler_CompileMethodBodies, message: compilation.AssemblyName, cancellationToken: cancellationToken))
            {
                Debug.Assert(filter == null || filterTree == null, "Cannot provide both a filter predicate and a filter tree.");

                if (filter == null && filterTree != null)
                {
                    filter = s => s.IsDefinedInSourceTree(filterTree, filterSpanWithinTree);
                }

                if (compilation.PreviousSubmission != null)
                {
                    // In case there is a previous submission, we should ensure
                    // it has already created anonymous type/delegates templates

                    // NOTE: if there are any errors, we will pick up what was created anyway
                    compilation.PreviousSubmission.EnsureAnonymousTypeTemplates(cancellationToken);

                    // TODO: revise to use a loop instead of a recursion
                }

                MethodBodyCompiler.CompileMethodBodies(compilation, moduleBeingBuilt, generateDebugInfo, hasDeclarationErrors, diagnostics, filter, cancellationToken);

                MethodSymbol entryPoint = GetEntryPoint(compilation, moduleBeingBuilt, hasDeclarationErrors, diagnostics, cancellationToken);
                if (moduleBeingBuilt != null)
                {
                    moduleBeingBuilt.SetEntryPoint(entryPoint);
                }
            }
        }
예제 #2
0
        public static void CompileMethodBodies(
            CSharpCompilation compilation,
            PEModuleBuilder moduleBeingBuilt,
            bool generateDebugInfo,
            bool hasDeclarationErrors,
            DiagnosticBag diagnostics,
            Predicate <Symbol> filter,
            CancellationToken cancellationToken)
        {
            MethodBodyCompiler methodBodyCompiler = new MethodBodyCompiler(
                compilation,
                moduleBeingBuilt,
                generateDebugInfo,
                hasDeclarationErrors,
                diagnostics,
                filter,
                cancellationToken);

            if (compilation.Options.ConcurrentBuild)
            {
                methodBodyCompiler.compilerTasks = new ConcurrentStack <Task>();
            }

            // directly traverse global namespace (no point to defer this to async)
            methodBodyCompiler.CompileNamespace(compilation.SourceModule.GlobalNamespace);
            methodBodyCompiler.WaitForWorkers();

            // compile additional and anonymous types if any
            if (moduleBeingBuilt != null)
            {
                var additionalTypes = moduleBeingBuilt.GetAdditionalTopLevelTypes();
                if (!additionalTypes.IsEmpty)
                {
                    methodBodyCompiler.CompileGeneratedMethods(additionalTypes, diagnostics);
                }

                // By this time we have processed all types reachable from module's global namespace
                compilation.AnonymousTypeManager.AssignTemplatesNamesAndCompile(methodBodyCompiler, moduleBeingBuilt, diagnostics);
                methodBodyCompiler.WaitForWorkers();

                var privateImplClass = moduleBeingBuilt.PrivateImplClass;
                if (privateImplClass != null)
                {
                    // all threads that were adding methods must be finished now, we can freeze the class:
                    privateImplClass.Freeze();

                    methodBodyCompiler.CompileGeneratedMethods(privateImplClass, diagnostics);
                }
            }

            // If we are trying to emit and there's an error without a corresponding diagnostic (e.g. because
            // we depend on an invalid type or constant from another module), then explicitly add a diagnostic.
            // This diagnostic is not very helpful to the user, but it will prevent us from emitting an invalid
            // module or crashing.
            if (moduleBeingBuilt != null && methodBodyCompiler.GlobalHasErrors && !diagnostics.HasAnyErrors() && !hasDeclarationErrors)
            {
                diagnostics.Add(ErrorCode.ERR_ModuleEmitFailure, NoLocation.Singleton, ((Microsoft.Cci.INamedEntity)moduleBeingBuilt).Name);
            }

            diagnostics.AddRange(compilation.AdditionalCodegenWarnings);

            // we can get unused field warnings only if compiling whole compilation.
            if (filter == null)
            {
                WarnUnusedFields(compilation, diagnostics, cancellationToken);
            }
        }