Files
PURErat-crack-scode/decompiled/Libraries/microsoft.codeanalysis.csharp/Microsoft.CodeAnalysis.CSharp/MethodToStateMachineRewriter.cs
T

707 lines
28 KiB
C#
Raw Normal View History

2026-08-27 10:56:38 -06:00
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
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 abstract class MethodToStateMachineRewriter : MethodToClassRewriter
{
internal readonly MethodSymbol OriginalMethod;
protected readonly SyntheticBoundNodeFactory F;
protected readonly FieldSymbol stateField;
protected readonly LocalSymbol cachedState;
protected readonly LocalSymbol? cachedThis;
protected readonly FieldSymbol? instanceIdField;
private readonly ResumableStateMachineStateAllocator _resumableStateAllocator;
private Dictionary<LabelSymbol, List<StateMachineState>> _dispatches = new Dictionary<LabelSymbol, List<StateMachineState>>();
private Dictionary<TypeSymbol, ArrayBuilder<StateMachineFieldSymbol>>? _lazyAvailableReusableHoistedFields;
private int _nextHoistedFieldId = 1;
private readonly EmptyStructTypeCache _emptyStructTypeCache = EmptyStructTypeCache.CreateNeverEmpty();
private readonly IReadOnlySet<Symbol> _hoistedVariables;
private readonly SynthesizedLocalOrdinalsDispenser _synthesizedLocalOrdinals;
private int _nextFreeHoistedLocalSlot;
private readonly ArrayBuilder<StateMachineStateDebugInfo> _stateDebugInfoBuilder;
protected BoundBlockInstrumentation? instrumentation;
protected abstract StateMachineState FirstIncreasingResumableState { get; }
protected abstract string EncMissingStateMessage { get; }
protected override TypeMap TypeMap => ((SynthesizedContainer)F.CurrentType).TypeMap;
protected override MethodSymbol CurrentMethod => F.CurrentFunction;
protected override NamedTypeSymbol ContainingType => OriginalMethod.ContainingType;
internal IReadOnlySet<Symbol> HoistedVariables => _hoistedVariables;
public MethodToStateMachineRewriter(SyntheticBoundNodeFactory F, MethodSymbol originalMethod, FieldSymbol state, FieldSymbol? instanceIdField, IReadOnlySet<Symbol> hoistedVariables, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies, SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals, ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder, VariableSlotAllocator? slotAllocatorOpt, int nextFreeHoistedLocalSlot, BindingDiagnosticBag diagnostics)
: base(slotAllocatorOpt, F.CompilationState, diagnostics)
{
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Invalid comparison between Unknown and I4
this.F = F;
stateField = state;
this.instanceIdField = instanceIdField;
cachedState = F.SynthesizedLocal(F.SpecialType((SpecialType)13), F.Syntax, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)27);
OriginalMethod = originalMethod;
_hoistedVariables = hoistedVariables;
_synthesizedLocalOrdinals = synthesizedLocalOrdinals;
_nextFreeHoistedLocalSlot = nextFreeHoistedLocalSlot;
foreach (KeyValuePair<Symbol, CapturedSymbolReplacement> nonReusableLocalProxy in nonReusableLocalProxies)
{
proxies.Add(nonReusableLocalProxy.Key, nonReusableLocalProxy.Value);
}
ParameterSymbol thisParameter = originalMethod.ThisParameter;
if ((object)thisParameter != null && thisParameter.Type.IsReferenceType && proxies.TryGetValue(thisParameter, out CapturedSymbolReplacement value) && (int)((CompilationOptions)F.Compilation.Options).OptimizationLevel == 1)
{
BoundExpression boundExpression = value.Replacement(F.Syntax, (NamedTypeSymbol frameType) => F.This());
cachedThis = F.SynthesizedLocal(boundExpression.Type, F.Syntax, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)(-5));
}
_stateDebugInfoBuilder = stateMachineStateDebugInfoBuilder;
_resumableStateAllocator = new ResumableStateMachineStateAllocator(slotAllocatorOpt, FirstIncreasingResumableState, increasing: true);
}
protected abstract BoundStatement GenerateReturn(bool finished);
protected override bool NeedsProxy(Symbol localOrParameter)
{
return _hoistedVariables.Contains(localOrParameter);
}
protected override BoundExpression FramePointer(SyntaxNode syntax, NamedTypeSymbol frameClass)
{
SyntaxNode syntax2 = F.Syntax;
F.Syntax = syntax;
BoundThisReference result = F.This();
F.Syntax = syntax2;
return result;
}
protected void AddResumableState(SyntaxNode awaitOrYieldReturnSyntax, AwaitDebugId awaitId, out StateMachineState state, out GeneratedLabelSymbol resumeLabel)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
AddResumableState(_resumableStateAllocator, awaitOrYieldReturnSyntax, awaitId, out state, out resumeLabel);
}
protected void AddResumableState(ResumableStateMachineStateAllocator allocator, SyntaxNode awaitOrYieldReturnSyntax, AwaitDebugId awaitId, out StateMachineState stateNumber, out GeneratedLabelSymbol resumeLabel)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected I4, but got Unknown
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
stateNumber = (StateMachineState)(int)allocator.AllocateState(awaitOrYieldReturnSyntax, awaitId);
AddStateDebugInfo(awaitOrYieldReturnSyntax, awaitId, stateNumber);
AddState(stateNumber, out resumeLabel);
}
protected void AddStateDebugInfo(SyntaxNode node, AwaitDebugId awaitId, StateMachineState state)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
int num = CurrentMethod.CalculateLocalSyntaxOffset(node.SpanStart, node.SyntaxTree);
_stateDebugInfoBuilder.Add(new StateMachineStateDebugInfo(num, awaitId, state));
}
protected void AddState(StateMachineState stateNumber, out GeneratedLabelSymbol resumeLabel)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (_dispatches == null)
{
_dispatches = new Dictionary<LabelSymbol, List<StateMachineState>>();
}
resumeLabel = F.GenerateLabel("stateMachine");
_dispatches.Add(resumeLabel, new List<StateMachineState> { stateNumber });
}
protected BoundStatement Dispatch(bool isOutermost)
{
IEnumerable<SyntheticBoundNodeFactory.SyntheticSwitchSection> items = _dispatches.OrderBy<KeyValuePair<LabelSymbol, List<StateMachineState>>, StateMachineState>(delegate(KeyValuePair<LabelSymbol, List<StateMachineState>> kv)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
KeyValuePair<LabelSymbol, List<StateMachineState>> keyValuePair = kv;
return keyValuePair.Value[0];
}).Select(delegate(KeyValuePair<LabelSymbol, List<StateMachineState>> kv)
{
SyntheticBoundNodeFactory f = F;
KeyValuePair<LabelSymbol, List<StateMachineState>> keyValuePair = kv;
ImmutableArray<int> values = EnumerableExtensions.SelectAsArray<StateMachineState, int>((IReadOnlyCollection<StateMachineState>)keyValuePair.Value, (Func<StateMachineState, int>)((StateMachineState state) => (int)state));
BoundStatement[] array = new BoundStatement[1];
SyntheticBoundNodeFactory f2 = F;
keyValuePair = kv;
array[0] = f2.Goto(keyValuePair.Key);
return f.SwitchSection(values, array);
});
BoundStatement boundStatement = F.Switch(F.Local(cachedState), items.ToImmutableArray());
if (isOutermost)
{
BoundStatement boundStatement2 = GenerateMissingStateDispatch();
if (boundStatement2 != null)
{
boundStatement = F.Block(boundStatement, boundStatement2);
}
}
return boundStatement;
}
protected virtual BoundStatement? GenerateMissingStateDispatch()
{
return _resumableStateAllocator.GenerateThrowMissingStateDispatch(F, F.Local(cachedState), EncMissingStateMessage);
}
private BoundStatement PossibleIteratorScope(ImmutableArray<LocalSymbol> locals, Func<BoundStatement> wrapped)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Invalid comparison between Unknown and I4
if (locals.IsDefaultOrEmpty)
{
return wrapped();
}
ArrayBuilder<StateMachineFieldSymbol> instance = ArrayBuilder<StateMachineFieldSymbol>.GetInstance();
ImmutableArray<LocalSymbol>.Enumerator enumerator = locals.GetEnumerator();
while (enumerator.MoveNext())
{
LocalSymbol current = enumerator.Current;
if (!NeedsProxy(current) || (int)current.RefKind != 0)
{
continue;
}
bool reused = false;
if (!proxies.TryGetValue(current, out CapturedSymbolReplacement value))
{
value = new CapturedToStateMachineFieldReplacement(GetOrAllocateReusableHoistedField(TypeMap.SubstituteType(current.Type).Type, out reused, current), isReusable: true);
proxies.Add(current, value);
}
if ((int)current.SynthesizedKind == 0)
{
SyntaxNode scopeDesignatorOpt = current.ScopeDesignatorOpt;
if (scopeDesignatorOpt == null || scopeDesignatorOpt.Kind() != SyntaxKind.SwitchSection)
{
goto IL_00c8;
}
}
if ((int)current.SynthesizedKind != 30)
{
continue;
}
goto IL_00c8;
IL_00c8:
if (!reused)
{
instance.Add(((CapturedToStateMachineFieldReplacement)value).HoistedField);
}
}
BoundStatement boundStatement = wrapped();
ArrayBuilder<BoundExpression> instance2 = ArrayBuilder<BoundExpression>.GetInstance();
enumerator = locals.GetEnumerator();
while (enumerator.MoveNext())
{
LocalSymbol current2 = enumerator.Current;
if (!proxies.TryGetValue(current2, out CapturedSymbolReplacement value2))
{
continue;
}
if (value2 is CapturedToStateMachineFieldReplacement capturedToStateMachineFieldReplacement)
{
AddVariableCleanup(instance2, capturedToStateMachineFieldReplacement.HoistedField);
if (value2.IsReusable)
{
FreeReusableHoistedField(capturedToStateMachineFieldReplacement.HoistedField);
}
continue;
}
ImmutableArray<StateMachineFieldSymbol>.Enumerator enumerator2 = ((CapturedToExpressionSymbolReplacement)value2).HoistedFields.GetEnumerator();
while (enumerator2.MoveNext())
{
StateMachineFieldSymbol current3 = enumerator2.Current;
AddVariableCleanup(instance2, current3);
if (value2.IsReusable)
{
FreeReusableHoistedField(current3);
}
}
}
if (instance2.Count != 0)
{
boundStatement = F.Block(boundStatement, F.Block(ArrayBuilderExtensions.SelectAsArray<BoundExpression, SyntheticBoundNodeFactory, BoundStatement>(instance2, (Func<BoundExpression, SyntheticBoundNodeFactory, BoundStatement>)((BoundExpression e, SyntheticBoundNodeFactory f) => f.ExpressionStatement(e)), F)));
}
instance2.Free();
if (instance.Count != 0)
{
boundStatement = MakeStateMachineScope(instance.ToImmutable(), boundStatement);
}
instance.Free();
return boundStatement;
}
internal BoundBlock MakeStateMachineScope(ImmutableArray<StateMachineFieldSymbol> hoistedLocals, BoundStatement statement)
{
return F.Block(new BoundStateMachineScope(F.Syntax, hoistedLocals, statement));
}
internal static bool TryUnwrapBoundStateMachineScope(ref BoundStatement statement, out ImmutableArray<StateMachineFieldSymbol> hoistedLocals)
{
if (statement.Kind == BoundKind.Block)
{
ImmutableArray<BoundStatement> statements = ((BoundBlock)statement).Statements;
if (statements.Length == 1 && statements[0].Kind == BoundKind.StateMachineScope)
{
BoundStateMachineScope boundStateMachineScope = (BoundStateMachineScope)statements[0];
statement = boundStateMachineScope.Statement;
hoistedLocals = boundStateMachineScope.Fields;
return true;
}
}
hoistedLocals = ImmutableArray<StateMachineFieldSymbol>.Empty;
return false;
}
private void AddVariableCleanup(ArrayBuilder<BoundExpression> cleanup, FieldSymbol field)
{
if (MightContainReferences(field.Type))
{
cleanup.Add(F.AssignmentExpression(F.Field(F.This(), field), F.NullOrDefault(field.Type)));
}
}
private bool MightContainReferences(TypeSymbol type)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Invalid comparison between Unknown and I4
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
if (type.IsReferenceType || (int)type.TypeKind == 11)
{
return true;
}
if ((int)type.TypeKind != 10)
{
return false;
}
if ((int)type.SpecialType == 36)
{
return true;
}
if ((int)type.SpecialType != 0)
{
return false;
}
if (!type.IsFromCompilation(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).Compilation))
{
return true;
}
foreach (FieldSymbol structInstanceField in _emptyStructTypeCache.GetStructInstanceFields(type))
{
if (MightContainReferences(structInstanceField.Type))
{
return true;
}
}
return false;
}
private StateMachineFieldSymbol GetOrAllocateReusableHoistedField(TypeSymbol type, out bool reused, LocalSymbol local = null)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
if (_lazyAvailableReusableHoistedFields != null && _lazyAvailableReusableHoistedFields.TryGetValue(type, out ArrayBuilder<StateMachineFieldSymbol> value) && value.Count > 0)
{
StateMachineFieldSymbol result = value.Last();
value.RemoveLast();
reused = true;
return result;
}
reused = false;
int num = _nextHoistedFieldId++;
if ((object)local != null && (int)local.SynthesizedKind == 0)
{
string name = GeneratedNames.MakeHoistedLocalFieldName((SynthesizedLocalKind)0, num, local.Name);
return F.StateMachineField(type, name, (SynthesizedLocalKind)0, num);
}
return F.StateMachineField(type, GeneratedNames.ReusableHoistedLocalFieldName(num));
}
private void FreeReusableHoistedField(StateMachineFieldSymbol field)
{
if (_lazyAvailableReusableHoistedFields == null || !_lazyAvailableReusableHoistedFields.TryGetValue(field.Type, out ArrayBuilder<StateMachineFieldSymbol> value))
{
if (_lazyAvailableReusableHoistedFields == null)
{
_lazyAvailableReusableHoistedFields = new Dictionary<TypeSymbol, ArrayBuilder<StateMachineFieldSymbol>>(SymbolEqualityComparer.IgnoringDynamicTupleNamesAndNullability);
}
_lazyAvailableReusableHoistedFields.Add(field.Type, value = new ArrayBuilder<StateMachineFieldSymbol>());
}
value.Add(field);
}
private BoundExpression HoistRefInitialization(SynthesizedLocal local, BoundAssignmentOperator node)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
BoundExpression expr = (BoundExpression)Visit(node.Right);
ArrayBuilder<BoundExpression> instance = ArrayBuilder<BoundExpression>.GetInstance();
bool needsSacrificialEvaluation = false;
ArrayBuilder<StateMachineFieldSymbol> instance2 = ArrayBuilder<StateMachineFieldSymbol>.GetInstance();
SyntaxNode val;
int syntaxOffset;
if ((int)((CompilationOptions)F.Compilation.Options).OptimizationLevel == 0)
{
val = local.GetDeclaratorSyntax();
syntaxOffset = OriginalMethod.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(val), val.SyntaxTree);
}
else
{
val = null;
syntaxOffset = -1;
}
BoundExpression boundExpression = HoistExpression(expr, val, syntaxOffset, local.RefKind, instance, instance2, ref needsSacrificialEvaluation);
proxies.Add(local, new CapturedToExpressionSymbolReplacement(boundExpression, instance2.ToImmutableAndFree(), isReusable: true));
if (needsSacrificialEvaluation)
{
TypeSymbol type = TypeMap.SubstituteType(local.Type).Type;
LocalSymbol localSymbol = F.SynthesizedLocal(type, null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)1, (SynthesizedLocalKind)(-2));
return F.Sequence(ImmutableArray.Create(localSymbol), instance.ToImmutableAndFree(), F.AssignmentExpression(F.Local(localSymbol), boundExpression, isRef: true));
}
if (instance.Count == 0)
{
instance.Free();
return null;
}
BoundExpression result = instance.Last();
instance.RemoveLast();
return F.Sequence(ImmutableArray<LocalSymbol>.Empty, instance.ToImmutableAndFree(), result);
}
private BoundExpression HoistExpression(BoundExpression expr, SyntaxNode awaitSyntaxOpt, int syntaxOffset, RefKind refKind, ArrayBuilder<BoundExpression> sideEffects, ArrayBuilder<StateMachineFieldSymbol> hoistedFields, ref bool needsSacrificialEvaluation)
{
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Invalid comparison between Unknown and I4
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Invalid comparison between Unknown and I4
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
switch (expr.Kind)
{
case BoundKind.ArrayAccess:
{
BoundArrayAccess boundArrayAccess = (BoundArrayAccess)expr;
BoundExpression expression = HoistExpression(boundArrayAccess.Expression, awaitSyntaxOpt, syntaxOffset, (RefKind)0, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
ArrayBuilder<BoundExpression> instance = ArrayBuilder<BoundExpression>.GetInstance();
ImmutableArray<BoundExpression>.Enumerator enumerator = boundArrayAccess.Indices.GetEnumerator();
while (enumerator.MoveNext())
{
BoundExpression current = enumerator.Current;
instance.Add(HoistExpression(current, awaitSyntaxOpt, syntaxOffset, (RefKind)0, sideEffects, hoistedFields, ref needsSacrificialEvaluation));
}
needsSacrificialEvaluation = true;
return boundArrayAccess.Update(expression, instance.ToImmutableAndFree(), boundArrayAccess.Type);
}
case BoundKind.FieldAccess:
{
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)expr;
if (boundFieldAccess.FieldSymbol.IsStatic)
{
if ((int)refKind != 0 || boundFieldAccess.FieldSymbol.IsReadOnly)
{
return expr;
}
}
else if ((int)refKind != 0)
{
bool flag = !boundFieldAccess.FieldSymbol.ContainingType.IsReferenceType;
BoundExpression boundExpression = HoistExpression(boundFieldAccess.ReceiverOpt, awaitSyntaxOpt, syntaxOffset, (RefKind)(flag ? ((int)refKind) : 0), sideEffects, hoistedFields, ref needsSacrificialEvaluation);
if (boundExpression.Kind != BoundKind.ThisReference && !flag)
{
needsSacrificialEvaluation = true;
}
return F.Field(boundExpression, boundFieldAccess.FieldSymbol);
}
break;
}
case BoundKind.DefaultExpression:
case BoundKind.ThisReference:
case BoundKind.BaseReference:
return expr;
case BoundKind.Call:
{
BoundCall boundCall = (BoundCall)expr;
if ((int)refKind != 0 && (int)refKind != 3)
{
F.Diagnostics.Add(ErrorCode.ERR_RefReturningCallAndAwait, F.Syntax.Location, boundCall.Method);
}
refKind = (RefKind)0;
break;
}
case BoundKind.ConditionalOperator:
_ = (BoundConditionalOperator)expr;
if ((int)refKind != 0 && (int)refKind != 3)
{
F.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, F.Syntax.Location);
}
refKind = (RefKind)0;
break;
}
if (expr.ConstantValueOpt != (ConstantValue)null)
{
return expr;
}
if ((int)refKind != 0)
{
throw ExceptionUtilities.UnexpectedValue((object)expr.Kind);
}
TypeSymbol type = expr.Type;
StateMachineFieldSymbol stateMachineFieldSymbol;
if ((int)((CompilationOptions)F.Compilation.Options).OptimizationLevel == 0)
{
int num = _synthesizedLocalOrdinals.AssignLocalOrdinal((SynthesizedLocalKind)29, syntaxOffset);
LocalDebugId val = default(LocalDebugId);
((LocalDebugId)(ref val))._002Ector(syntaxOffset, num);
int slotIndex = default(int);
if (slotAllocatorOpt == null || !slotAllocatorOpt.TryGetPreviousHoistedLocalSlotIndex(awaitSyntaxOpt, ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).Translate(type, awaitSyntaxOpt, ((BindingDiagnosticBag)Diagnostics).DiagnosticBag), (SynthesizedLocalKind)29, val, ((BindingDiagnosticBag)Diagnostics).DiagnosticBag, ref slotIndex))
{
slotIndex = _nextFreeHoistedLocalSlot++;
}
string name = GeneratedNames.MakeHoistedLocalFieldName((SynthesizedLocalKind)29, slotIndex);
stateMachineFieldSymbol = F.StateMachineField(expr.Type, name, new LocalSlotDebugInfo((SynthesizedLocalKind)29, val), slotIndex);
}
else
{
stateMachineFieldSymbol = GetOrAllocateReusableHoistedField(type, out var _);
}
hoistedFields.Add(stateMachineFieldSymbol);
BoundFieldAccess boundFieldAccess2 = F.Field(F.This(), stateMachineFieldSymbol);
sideEffects.Add(F.AssignmentExpression(boundFieldAccess2, expr));
return boundFieldAccess2;
}
public override BoundNode Visit(BoundNode node)
{
if (node == null)
{
return node;
}
SyntaxNode syntax = F.Syntax;
F.Syntax = node.Syntax;
BoundNode? result = base.Visit(node);
F.Syntax = syntax;
return result;
}
public override BoundNode VisitBlock(BoundBlock node)
{
if (node.Instrumentation != null)
{
instrumentation = (BoundBlockInstrumentation)Visit(node.Instrumentation);
}
return PossibleIteratorScope(node.Locals, () => VisitBlock(node, removeInstrumentation: true));
}
public override BoundNode VisitStateMachineInstanceId(BoundStateMachineInstanceId node)
{
return F.Field(F.This(), instanceIdField);
}
public override BoundNode VisitScope(BoundScope node)
{
ArrayBuilder<LocalSymbol> instance = ArrayBuilder<LocalSymbol>.GetInstance();
ArrayBuilder<StateMachineFieldSymbol> instance2 = ArrayBuilder<StateMachineFieldSymbol>.GetInstance();
bool flag = false;
ImmutableArray<LocalSymbol>.Enumerator enumerator = node.Locals.GetEnumerator();
while (enumerator.MoveNext())
{
LocalSymbol current = enumerator.Current;
if (TryRewriteLocal(current, out LocalSymbol newLocal))
{
instance.Add(newLocal);
flag = flag || (object)current != newLocal;
}
else
{
instance2.Add(((CapturedToStateMachineFieldReplacement)proxies[current]).HoistedField);
}
}
ImmutableArray<BoundStatement> statements = VisitList(node.Statements);
if (instance2.Count != 0)
{
BoundStatement statement;
if (instance.Count == 0)
{
instance.Free();
statement = new BoundStatementList(node.Syntax, statements);
}
else
{
statement = node.Update(instance.ToImmutableAndFree(), statements);
}
return MakeStateMachineScope(instance2.ToImmutable(), statement);
}
instance2.Free();
ImmutableArray<LocalSymbol> locals;
if (flag)
{
locals = instance.ToImmutableAndFree();
}
else
{
instance.Free();
locals = node.Locals;
}
return node.Update(locals, statements);
}
public override BoundNode VisitForStatement(BoundForStatement node)
{
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs", 793);
}
public override BoundNode VisitUsingStatement(BoundUsingStatement node)
{
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs", 798);
}
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
{
BoundExpression boundExpression = (BoundExpression)Visit(node.Expression);
if (boundExpression != null)
{
return node.Update(boundExpression);
}
return null;
}
public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
{
if (node.Left.Kind != BoundKind.Local)
{
return base.VisitAssignmentOperator(node);
}
LocalSymbol localSymbol = ((BoundLocal)node.Left).LocalSymbol;
if (!NeedsProxy(localSymbol))
{
return base.VisitAssignmentOperator(node);
}
if (proxies.ContainsKey(localSymbol))
{
return base.VisitAssignmentOperator(node);
}
return HoistRefInitialization((SynthesizedLocal)localSymbol, node);
}
public override BoundNode VisitTryStatement(BoundTryStatement node)
{
Dictionary<LabelSymbol, List<StateMachineState>> dictionary = _dispatches;
_dispatches = null;
BoundBlock boundBlock = F.Block((BoundStatement)Visit(node.TryBlock));
GeneratedLabelSymbol generatedLabelSymbol = null;
if (_dispatches != null)
{
generatedLabelSymbol = F.GenerateLabel("tryDispatch");
boundBlock = F.Block(F.HiddenSequencePoint(), Dispatch(isOutermost: false), boundBlock);
if (dictionary == null)
{
dictionary = new Dictionary<LabelSymbol, List<StateMachineState>>();
}
dictionary.Add(generatedLabelSymbol, new List<StateMachineState>(from kv in _dispatches.Values
from n in kv
orderby n
select n));
}
_dispatches = dictionary;
ImmutableArray<BoundCatchBlock> catchBlocks = VisitList(node.CatchBlocks);
BoundBlock finallyBlockOpt = ((node.FinallyBlockOpt == null) ? null : F.Block(F.HiddenSequencePoint(), F.If(ShouldEnterFinallyBlock(), VisitFinally(node.FinallyBlockOpt)), F.HiddenSequencePoint()));
BoundStatement boundStatement = node.Update(boundBlock, catchBlocks, finallyBlockOpt, node.FinallyLabelOpt, node.PreferFaultHandler);
if ((object)generatedLabelSymbol != null)
{
boundStatement = F.Block(F.HiddenSequencePoint(), F.Label(generatedLabelSymbol), boundStatement);
}
return boundStatement;
}
protected virtual BoundBlock VisitFinally(BoundBlock finallyBlock)
{
return (BoundBlock)Visit(finallyBlock);
}
protected virtual BoundBinaryOperator ShouldEnterFinallyBlock()
{
return F.IntLessThan(F.Local(cachedState), F.Literal((StateMachineState)0));
}
protected BoundExpressionStatement GenerateSetBothStates(StateMachineState stateNumber)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
return F.Assignment(F.Field(F.This(), stateField), F.AssignmentExpression(F.Local(cachedState), F.Literal(stateNumber)));
}
protected BoundStatement CacheThisIfNeeded()
{
if ((object)cachedThis != null)
{
BoundExpression right = proxies[OriginalMethod.ThisParameter].Replacement(F.Syntax, (NamedTypeSymbol frameType) => F.This());
return F.Assignment(F.Local(cachedThis), right);
}
return F.StatementList();
}
public sealed override BoundNode VisitThisReference(BoundThisReference node)
{
if ((object)cachedThis != null)
{
return F.Local(cachedThis);
}
ParameterSymbol thisParameter = OriginalMethod.ThisParameter;
if ((object)thisParameter == null || !proxies.TryGetValue(thisParameter, out CapturedSymbolReplacement value))
{
return node.Update(VisitType(node.Type));
}
return value.Replacement(F.Syntax, (NamedTypeSymbol frameType) => F.This());
}
public override BoundNode VisitBaseReference(BoundBaseReference node)
{
if ((object)cachedThis != null)
{
return F.Local(cachedThis);
}
return proxies[OriginalMethod.ThisParameter].Replacement(F.Syntax, (NamedTypeSymbol frameType) => F.This());
}
}