internal ILBuilder(ITokenDeferral module, LocalSlotManager localSlotManager, OptimizationLevel optimizations) { Debug.Assert(BitConverter.IsLittleEndian); this.module = module; this.LocalSlotManager = localSlotManager; _emitState = default(EmitState); _scopeManager = new LocalScopeManager(); leaderBlock = _currentBlock = _scopeManager.CreateBlock(this); _labelInfos = new SmallDictionary<object, LabelInfo>(ReferenceEqualityComparer.Instance); _optimizations = optimizations; }
internal ILBuilder(ITokenDeferral module, LocalSlotManager localSlotManager, bool isOptimizing) { Debug.Assert(BitConverter.IsLittleEndian); this.module = module; this.LocalSlotManager = localSlotManager; this.emitState = default(EmitState); this.scopeManager = new LocalScopeManager(); leaderBlock = currentBlock = this.scopeManager.CreateBlock(this); labelInfos = new SmallDictionary<object, LabelInfo>(ReferenceEqualityComparer.Instance); this.isOptimizing = isOptimizing; }
/// <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) => { if (path.IsPharFile()) { path = PhpFileUtilities.BuildPharStubFileName(path); } return(moduleBuilder.DebugDocumentsBuilder.GetOrAddDebugDocument( path, basePath, normalizedPath => CreateDebugSourceDocument(normalizedPath, routine))); }; } ILBuilder il = new ILBuilder(moduleBuilder, localSlotManager, optimizations.AsOptimizationLevel()); try { StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfo = 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 <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, stateMachineMoveNextDebugInfo, null)); // dynamicAnalysisDataOpt } 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(); } }
/// <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(); } }