using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Emit.NoPia; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp; internal class IteratorRewriter : StateMachineRewriter { private readonly TypeWithAnnotations _elementType; private readonly bool _isEnumerable; private FieldSymbol _currentField; protected override bool PreserveInitialParameterValuesAndThreadId => _isEnumerable; private IteratorRewriter(BoundStatement body, MethodSymbol method, bool isEnumerable, IteratorStateMachine stateMachineType, ArrayBuilder stateMachineStateDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) : base(body, method, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics) { _elementType = stateMachineType.ElementType; _isEnumerable = isEnumerable; } internal static BoundStatement Rewrite(BoundStatement body, MethodSymbol method, int methodOrdinal, ArrayBuilder stateMachineStateDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, out IteratorStateMachine stateMachineType) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0052: Unknown result type (might be due to invalid IL or missing references) TypeWithAnnotations iteratorElementTypeWithAnnotations = method.IteratorElementTypeWithAnnotations; if (iteratorElementTypeWithAnnotations.IsDefault || method.IsAsync) { stateMachineType = null; return body; } SpecialType specialType = method.ReturnType.OriginalDefinition.SpecialType; bool isEnumerable; if (specialType - 24 > 1) { if (specialType - 28 > 1) { throw ExceptionUtilities.UnexpectedValue((object)method.ReturnType.OriginalDefinition.SpecialType); } isEnumerable = false; } else { isEnumerable = true; } stateMachineType = new IteratorStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, isEnumerable, iteratorElementTypeWithAnnotations); ((ModuleCompilationState)((PEModuleBuilder)compilationState.ModuleBuilderOpt).CompilationState).SetStateMachineType(method, (NamedTypeSymbol)stateMachineType); IteratorRewriter iteratorRewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics); if (!iteratorRewriter.VerifyPresenceOfRequiredAPIs()) { return body; } return iteratorRewriter.Rewrite(); } protected bool VerifyPresenceOfRequiredAPIs() { BindingDiagnosticBag instance = BindingDiagnosticBag.GetInstance(withDiagnostics: true, ((BindingDiagnosticBag)(object)diagnostics).AccumulatesDependencies); EnsureSpecialType((SpecialType)13, instance); EnsureSpecialType((SpecialType)35, instance); EnsureSpecialMember((SpecialMember)92, instance); EnsureSpecialType((SpecialType)28, instance); EnsureSpecialPropertyGetter((SpecialMember)85, instance); EnsureSpecialMember((SpecialMember)87, instance); EnsureSpecialMember((SpecialMember)88, instance); EnsureSpecialType((SpecialType)29, instance); EnsureSpecialPropertyGetter((SpecialMember)90, instance); if (_isEnumerable) { EnsureSpecialType((SpecialType)24, instance); EnsureSpecialMember((SpecialMember)84, instance); EnsureSpecialType((SpecialType)25, instance); EnsureSpecialMember((SpecialMember)89, instance); } bool num = ((BindingDiagnosticBag)instance).HasAnyErrors(); if (!num) { ((BindingDiagnosticBag)(object)diagnostics).AddDependencies((BindingDiagnosticBag)(object)instance, false); } else { ((BindingDiagnosticBag)(object)diagnostics).AddRange((BindingDiagnosticBag)(object)instance, false); } ((BindingDiagnosticBag)(object)instance).Free(); return !num; } private Symbol EnsureSpecialMember(SpecialMember member, BindingDiagnosticBag bag) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Binder.TryGetSpecialTypeMember(F.Compilation, member, body.Syntax, bag, out var symbol); return symbol; } private void EnsureSpecialType(SpecialType type, BindingDiagnosticBag bag) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) Binder.GetSpecialType(F.Compilation, type, body.Syntax, bag); } private void EnsureSpecialPropertyGetter(SpecialMember member, BindingDiagnosticBag bag) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) PropertySymbol propertySymbol = (PropertySymbol)EnsureSpecialMember(member, bag); if ((object)propertySymbol != null) { MethodSymbol getMethod = propertySymbol.GetMethod; if ((object)getMethod == null) { Binder.Error(bag, ErrorCode.ERR_PropertyLacksGet, SyntaxNodeOrToken.op_Implicit(body.Syntax), propertySymbol); } else { bag.ReportUseSite(getMethod, body.Syntax.Location); } } } protected override void GenerateControlFields() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) stateField = F.StateMachineField(F.SpecialType((SpecialType)13), GeneratedNames.MakeStateMachineStateFieldName()); MethodInstrumentation methodBodyInstrumentations = F.ModuleBuilderOpt.GetMethodBodyInstrumentations(method); if (((MethodInstrumentation)(ref methodBodyInstrumentations)).Kinds.Contains((InstrumentationKind)(-1))) { instanceIdField = F.StateMachineField(F.SpecialType((SpecialType)16), GeneratedNames.MakeStateMachineStateIdFieldName()); } _currentField = F.StateMachineField(_elementType, GeneratedNames.MakeIteratorCurrentFieldName()); } protected override void GenerateMethodImplementations() { try { BoundExpression managedThreadId = null; GenerateEnumeratorImplementation(); if (_isEnumerable) { GenerateEnumerableImplementation(ref managedThreadId); } GenerateConstructor(managedThreadId); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember missingPredefinedMember) { ((BindingDiagnosticBag)diagnostics).Add(missingPredefinedMember.Diagnostic); } } private void GenerateEnumeratorImplementation() { MethodSymbol methodToImplement = F.SpecialMethod((SpecialMember)92); MethodSymbol methodToImplement2 = F.SpecialMethod((SpecialMember)87); MethodSymbol methodToImplement3 = F.SpecialMethod((SpecialMember)88); MethodSymbol getMethod = F.SpecialProperty((SpecialMember)85).GetMethod; NamedTypeSymbol newOwner = F.SpecialType((SpecialType)29).Construct(ImmutableArray.Create(_elementType)); MethodSymbol getterToImplement = F.SpecialProperty((SpecialMember)90).GetMethod.AsMember(newOwner); SynthesizedImplementationMethod disposeMethod = OpenMethodImplementation(methodToImplement, null, hasMethodBodyDependency: true); SynthesizedImplementationMethod moveNextMethod = OpenMoveNextMethodImplementation(methodToImplement2); GenerateMoveNextAndDispose(moveNextMethod, disposeMethod); OpenPropertyImplementation(getterToImplement); F.CloseMethod(F.Return(F.Field(F.This(), _currentField))); OpenMethodImplementation(methodToImplement3); F.CloseMethod(F.Throw(F.New(F.WellKnownType((WellKnownType)240)))); OpenPropertyImplementation(getMethod); F.CloseMethod(F.Return(F.Field(F.This(), _currentField))); } private void GenerateEnumerableImplementation(ref BoundExpression managedThreadId) { MethodSymbol methodToImplement = F.SpecialMethod((SpecialMember)84); NamedTypeSymbol newOwner = F.SpecialType((SpecialType)25).Construct(_elementType.Type); MethodSymbol getEnumeratorMethod = F.SpecialMethod((SpecialMember)89).AsMember(newOwner); SynthesizedImplementationMethod synthesizedImplementationMethod = GenerateIteratorGetEnumerator(getEnumeratorMethod, ref managedThreadId, (StateMachineState)0); OpenMethodImplementation(methodToImplement); F.CloseMethod(F.Return(F.Call(F.This(), synthesizedImplementationMethod))); } private void GenerateConstructor(BoundExpression managedThreadId) { F.CurrentFunction = stateMachineType.Constructor; ArrayBuilder instance = ArrayBuilder.GetInstance(); instance.Add(F.BaseInitialization()); instance.Add((BoundStatement)F.Assignment(F.Field(F.This(), stateField), F.Parameter(F.CurrentFunction.Parameters[0]))); if (managedThreadId != null) { instance.Add((BoundStatement)F.Assignment(F.Field(F.This(), initialThreadIdField), managedThreadId)); } if ((object)instanceIdField != null) { MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)361); if ((object)methodSymbol != null) { instance.Add((BoundStatement)F.Assignment(F.InstanceField(instanceIdField), F.Call(null, methodSymbol))); } } instance.Add((BoundStatement)F.Return()); F.CloseMethod(F.Block(instance.ToImmutableAndFree())); instance = null; } protected override void InitializeStateMachine(ArrayBuilder bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) StateMachineState value = (StateMachineState)(_isEnumerable ? (-2) : 0); bodyBuilder.Add((BoundStatement)F.Assignment(F.Local(stateMachineLocal), F.New(stateMachineType.Constructor.AsMember(frameType), F.Literal(value)))); } protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary proxies) { ArrayBuilder instance = ArrayBuilder.GetInstance(); instance.Add(GenerateParameterStorage(stateMachineVariable, proxies)); instance.Add((BoundStatement)F.Return(F.Local(stateMachineVariable))); return F.Block(instance.ToImmutableAndFree()); } private void GenerateMoveNextAndDispose(SynthesizedImplementationMethod moveNextMethod, SynthesizedImplementationMethod disposeMethod) { new IteratorMethodToStateMachineRewriter(F, method, stateField, _currentField, instanceIdField, (IReadOnlySet)(object)hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics).GenerateMoveNextAndDispose(body, moveNextMethod, disposeMethod); } }