Beispiel #1
0
        private void CompileGeneratedMethods(TypeCompilationState compilationState)
        {
            if (compilationState.AnyGeneratedMethods)
            {
                foreach (var methodWithBody in compilationState.GeneratedMethods)
                {
                    // We make sure that an asynchronous mutation to the diagnostic bag does not
                    // confuse the method body generator by making a fresh bag and then loading
                    // any diagnostics emitted into it back into the main diagnostic bag.
                    var diagnosticsThisMethod = DiagnosticBag.GetInstance();

                    var            method           = methodWithBody.Method;
                    BoundStatement bodyWithoutAsync = AsyncRewriter2.Rewrite(methodWithBody.Body, method, compilationState, diagnosticsThisMethod, generateDebugInfo);

                    MethodBody emittedBody = null;

                    if (!diagnosticsThisMethod.HasAnyErrors() && !globalHasErrors)
                    {
                        emittedBody = Compiler.GenerateMethodBody(
                            compilationState,
                            method,
                            bodyWithoutAsync,
                            diagnosticsThisMethod,
                            optimize,
                            debugDocumentProvider,
                            GetNamespaceScopes(method, methodWithBody.DebugImports));
                    }

                    this.diagnostics.AddRange(diagnosticsThisMethod);
                    diagnosticsThisMethod.Free();

                    // error while generating IL
                    if (emittedBody == null)
                    {
                        break;
                    }

                    moduleBeingBuilt.SetMethodBody(method, emittedBody);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Rewrite an async method into a state machine class.
        /// </summary>
        /// <param name="body">The original body of the method</param>
        /// <param name="method">The method's identity</param>
        /// <param name="compilationState">The collection of generated methods that result from this transformation and which must be emitted</param>
        /// <param name="diagnostics">Diagnostic bag for diagnostics.</param>
        /// <param name="generateDebugInfo"></param>
        internal static BoundStatement Rewrite(
            BoundStatement body,
            MethodSymbol method,
            TypeCompilationState compilationState,
            DiagnosticBag diagnostics,
            bool generateDebugInfo)
        {
            if (!method.IsAsync)
            {
                return body;
            }

            var bodyWithAwaitLifted = AwaitLiftingRewriter.Rewrite(body, method, compilationState, diagnostics);
            var rewriter = new AsyncRewriter2(bodyWithAwaitLifted, method, ((SourceMethodSymbol)method).AsyncStateMachineType, compilationState, diagnostics, generateDebugInfo);
            if (!rewriter.constructedSuccessfully)
            {
                return body;
            }

            var bodyReplacement = rewriter.Rewrite();
            return bodyReplacement;
        }
Beispiel #3
0
        /// <summary>
        /// Rewrite an async method into a state machine class.
        /// </summary>
        /// <param name="body">The original body of the method</param>
        /// <param name="method">The method's identity</param>
        /// <param name="compilationState">The collection of generated methods that result from this transformation and which must be emitted</param>
        /// <param name="diagnostics">Diagnostic bag for diagnostics.</param>
        /// <param name="generateDebugInfo"></param>
        internal static BoundStatement Rewrite(
            BoundStatement body,
            MethodSymbol method,
            TypeCompilationState compilationState,
            DiagnosticBag diagnostics,
            bool generateDebugInfo)
        {
            if (!method.IsAsync)
            {
                return(body);
            }

            var bodyWithAwaitLifted = AwaitLiftingRewriter.Rewrite(body, method, compilationState, diagnostics);
            var rewriter            = new AsyncRewriter2(bodyWithAwaitLifted, method, ((SourceMethodSymbol)method).AsyncStateMachineType, compilationState, diagnostics, generateDebugInfo);

            if (!rewriter.constructedSuccessfully)
            {
                return(body);
            }

            var bodyReplacement = rewriter.Rewrite();

            return(bodyReplacement);
        }
Beispiel #4
0
        internal static BoundStatement LowerStatement(
            bool generateDebugInfo,
            MethodSymbol method,
            BoundStatement body,
            SynthesizedSubmissionFields previousSubmissionFields,
            TypeCompilationState compilationState,
            DiagnosticBag diagnostics)
        {
            if (body.HasErrors)
            {
                return(body);
            }

            bool sawLambdas;
            bool sawDynamicOperations;
            bool sawAwaitInExceptionHandler;
            var  loweredBody = LocalRewriter.Rewrite(
                method.DeclaringCompilation,
                generateDebugInfo,
                method,
                method.ContainingType,
                body,
                compilationState,
                diagnostics,
                previousSubmissionFields,
                out sawLambdas,
                out sawDynamicOperations,
                out sawAwaitInExceptionHandler);

            if (sawDynamicOperations && compilationState.ModuleBuilder.IsENCDelta)
            {
                // Dynamic operations are not supported in ENC.
                var location = method.Locations[0];
                diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_EnCNoDynamicOperation), location);
            }

            if (loweredBody.HasErrors)
            {
                return(loweredBody);
            }

            if (sawAwaitInExceptionHandler)
            {
                // If we have awaits in handlers, we need to
                // replace handlers with synthetic ones which can be consumed by async rewriter.
                // The reason why this rewrite happens before the lambda rewrite
                // is that we may need access to exception locals and it would be fairly hard to do
                // if these locals are captured into closures (possibly nested ones).
                Debug.Assert(method.IteratorElementType == null);
                loweredBody = AsyncHandlerRewriter.Rewrite(
                    generateDebugInfo,
                    method,
                    method.ContainingType,
                    loweredBody,
                    compilationState,
                    diagnostics);
            }

            if (loweredBody.HasErrors)
            {
                return(loweredBody);
            }

            BoundStatement bodyWithoutLambdas = loweredBody;

            if (sawLambdas)
            {
                LambdaRewriter.Analysis lambdaAnalysis = LambdaRewriter.Analysis.Analyze(loweredBody, method, out sawLambdas);
                if (sawLambdas)
                {
                    bodyWithoutLambdas = LambdaRewriter.Rewrite(loweredBody, method.ContainingType, method.ThisParameter, method, compilationState, diagnostics, lambdaAnalysis, generateDebugInfo);
                }
            }

            if (bodyWithoutLambdas.HasErrors)
            {
                return(bodyWithoutLambdas);
            }

            BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, compilationState, diagnostics, generateDebugInfo);

            if (bodyWithoutIterators.HasErrors)
            {
                return(bodyWithoutIterators);
            }

            BoundStatement bodyWithoutAsync = AsyncRewriter2.Rewrite(bodyWithoutIterators, method, compilationState, diagnostics, generateDebugInfo);

            return(bodyWithoutAsync);
        }