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); } } }
/// <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; }
/// <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); }
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); }