Files
2026-08-27 10:56:38 -06:00

238 lines
11 KiB
C#

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<StateMachineStateDebugInfo> 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<StateMachineStateDebugInfo> 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<NamedTypeSymbol, MethodSymbol>)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)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<AssemblySymbol>)(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<AssemblySymbol>)(object)diagnostics).AddDependencies((BindingDiagnosticBag<AssemblySymbol>)(object)instance, false);
}
else
{
((BindingDiagnosticBag<AssemblySymbol>)(object)diagnostics).AddRange((BindingDiagnosticBag<AssemblySymbol>)(object)instance, false);
}
((BindingDiagnosticBag<AssemblySymbol>)(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<Symbol>(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<BoundStatement> instance = ArrayBuilder<BoundStatement>.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<BoundStatement> 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<Symbol, CapturedSymbolReplacement> proxies)
{
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.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<Symbol>)(object)hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics).GenerateMoveNextAndDispose(body, moveNextMethod, disposeMethod);
}
}