public static void Run(MethodSymbol method, BoundStatement block, ILBuilder builder, PEModuleBuilder module, DiagnosticBag diagnostics, bool optimize, bool emitSequencePoints) { CodeGenerator generator = new CodeGenerator(method, block, builder, module, diagnostics, optimize, emitSequencePoints); generator.Generate(); Debug.Assert(generator.asyncCatchHandlerOffset < 0); Debug.Assert(generator.asyncYieldPoints == null); Debug.Assert(generator.asyncResumePoints == null); if (!diagnostics.HasAnyErrors()) { builder.Realize(); } }
public static void Run(MethodSymbol method, BoundStatement block, ILBuilder builder, PEModuleBuilder module, DiagnosticBag diagnostics, bool optimize, bool emitSequencePoints, out int asyncCatchHandlerOffset, out ImmutableArray<int> asyncYieldPoints, out ImmutableArray<int> asyncResumePoints) { CodeGenerator generator = new CodeGenerator(method, block, builder, module, diagnostics, optimize, emitSequencePoints); generator.Generate(); if (!diagnostics.HasAnyErrors()) { builder.Realize(); } asyncCatchHandlerOffset = (generator.asyncCatchHandlerOffset < 0) ? -1 : generator.builder.GetILOffsetFromMarker(generator.asyncCatchHandlerOffset); ArrayBuilder<int> yieldPoints = generator.asyncYieldPoints; ArrayBuilder<int> resumePoints = generator.asyncResumePoints; if (yieldPoints == null) { asyncYieldPoints = ImmutableArray<int>.Empty; asyncResumePoints = ImmutableArray<int>.Empty; } else { var yieldPointBuilder = ArrayBuilder<int>.GetInstance(); var resumePointBuilder = ArrayBuilder<int>.GetInstance(); int n = yieldPoints.Count; for (int i = 0; i < n; i++) { int yieldOffset = generator.builder.GetILOffsetFromMarker(yieldPoints[i]); int resumeOffset = generator.builder.GetILOffsetFromMarker(resumePoints[i]); Debug.Assert(resumeOffset >= 0); // resume marker should always be reachable from dispatch // yield point may not be reachable if the whole // await is not reachable; we just ignore such awaits if (yieldOffset > 0) { yieldPointBuilder.Add(yieldOffset); resumePointBuilder.Add(resumeOffset); } } asyncYieldPoints = yieldPointBuilder.ToImmutableAndFree(); asyncResumePoints = resumePointBuilder.ToImmutableAndFree(); yieldPoints.Free(); resumePoints.Free(); } }
/// <summary> /// Generates method body that calls another method. /// Used for wrapping a method call into a method, e.g. an entry point. /// </summary> internal static MethodBody GenerateMethodBody( PEModuleBuilder moduleBuilder, MethodSymbol routine, Action<ILBuilder> builder, VariableSlotAllocator variableSlotAllocatorOpt, DiagnosticBag diagnostics, bool emittingPdb) { var compilation = moduleBuilder.Compilation; var localSlotManager = new LocalSlotManager(variableSlotAllocatorOpt); var optimizations = compilation.Options.OptimizationLevel; DebugDocumentProvider debugDocumentProvider = null; if (emittingPdb) { debugDocumentProvider = (path, basePath) => moduleBuilder.GetOrAddDebugDocument(path, basePath, CreateDebugDocumentForFile); } ILBuilder il = new ILBuilder(moduleBuilder, localSlotManager, optimizations); try { Cci.AsyncMethodBodyDebugInfo asyncDebugInfo = null; builder(il); // il.Realize(); // var localVariables = il.LocalSlotManager.LocalsInOrder(); if (localVariables.Length > 0xFFFE) { //diagnosticsForThisMethod.Add(ErrorCode.ERR_TooManyLocals, method.Locations.First()); } //if (diagnosticsForThisMethod.HasAnyErrors()) //{ // // we are done here. Since there were errors we should not emit anything. // return null; //} //// We will only save the IL builders when running tests. //if (moduleBuilder.SaveTestData) //{ // moduleBuilder.SetMethodTestData(method, builder.GetSnapshot()); //} // Only compiler-generated MoveNext methods have iterator scopes. See if this is one. var stateMachineHoistedLocalScopes = default(ImmutableArray<Cci.StateMachineHoistedLocalScope>); //if (isStateMachineMoveNextMethod) //{ // stateMachineHoistedLocalScopes = builder.GetHoistedLocalScopes(); //} var stateMachineHoistedLocalSlots = default(ImmutableArray<EncHoistedLocalInfo>); var stateMachineAwaiterSlots = default(ImmutableArray<Cci.ITypeReference>); //if (optimizations == OptimizationLevel.Debug && stateMachineTypeOpt != null) //{ // Debug.Assert(method.IsAsync || method.IsIterator); // GetStateMachineSlotDebugInfo(moduleBuilder, moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), variableSlotAllocatorOpt, diagnosticsForThisMethod, out stateMachineHoistedLocalSlots, out stateMachineAwaiterSlots); // Debug.Assert(!diagnostics.HasAnyErrors()); //} return new MethodBody( il.RealizedIL, il.MaxStack, (Cci.IMethodDefinition)routine.PartialDefinitionPart ?? routine, variableSlotAllocatorOpt?.MethodId ?? new DebugId(0, moduleBuilder.CurrentGenerationOrdinal), localVariables, il.RealizedSequencePoints, debugDocumentProvider, il.RealizedExceptionHandlers, il.GetAllScopes(), il.HasDynamicLocal, null, // importScopeOpt, ImmutableArray<LambdaDebugInfo>.Empty, // lambdaDebugInfo, ImmutableArray<ClosureDebugInfo>.Empty, // closureDebugInfo, null, //stateMachineTypeOpt?.Name, stateMachineHoistedLocalScopes, stateMachineHoistedLocalSlots, stateMachineAwaiterSlots, asyncDebugInfo); } finally { // Basic blocks contain poolable builders for IL and sequence points. Free those back // to their pools. il.FreeBasicBlocks(); //// Remember diagnostics. //diagnostics.AddRange(diagnosticsForThisMethod); //diagnosticsForThisMethod.Free(); } }