485 lines
28 KiB
C#
485 lines
28 KiB
C#
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 class AsyncRewriter : StateMachineRewriter
|
|
{
|
|
private sealed class AsyncIteratorRewriter : AsyncRewriter
|
|
{
|
|
private FieldSymbol _promiseOfValueOrEndField;
|
|
|
|
private FieldSymbol _currentField;
|
|
|
|
private FieldSymbol _disposeModeField;
|
|
|
|
private FieldSymbol _combinedTokensField;
|
|
|
|
private readonly bool _isEnumerable;
|
|
|
|
protected override bool PreserveInitialParameterValuesAndThreadId => _isEnumerable;
|
|
|
|
internal AsyncIteratorRewriter(BoundStatement body, MethodSymbol method, int methodOrdinal, AsyncStateMachine stateMachineType, ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
|
|
: base(body, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
|
|
{
|
|
_isEnumerable = method.IsAsyncReturningIAsyncEnumerable(method.DeclaringCompilation);
|
|
}
|
|
|
|
protected override void VerifyPresenceOfRequiredAPIs(BindingDiagnosticBag bag)
|
|
{
|
|
base.VerifyPresenceOfRequiredAPIs(bag);
|
|
if (_isEnumerable)
|
|
{
|
|
EnsureWellKnownMember((WellKnownMember)427, bag);
|
|
EnsureWellKnownMember((WellKnownMember)457, bag);
|
|
EnsureWellKnownMember((WellKnownMember)458, bag);
|
|
EnsureWellKnownMember((WellKnownMember)459, bag);
|
|
EnsureWellKnownMember((WellKnownMember)460, bag);
|
|
}
|
|
EnsureWellKnownMember((WellKnownMember)428, bag);
|
|
EnsureWellKnownMember((WellKnownMember)429, bag);
|
|
EnsureWellKnownMember((WellKnownMember)426, bag);
|
|
EnsureWellKnownMember((WellKnownMember)443, bag);
|
|
EnsureWellKnownMember((WellKnownMember)444, bag);
|
|
EnsureWellKnownMember((WellKnownMember)445, bag);
|
|
EnsureWellKnownMember((WellKnownMember)430, bag);
|
|
EnsureWellKnownMember((WellKnownMember)431, bag);
|
|
EnsureWellKnownMember((WellKnownMember)436, bag);
|
|
EnsureWellKnownMember((WellKnownMember)432, bag);
|
|
EnsureWellKnownMember((WellKnownMember)433, bag);
|
|
EnsureWellKnownMember((WellKnownMember)434, bag);
|
|
EnsureWellKnownMember((WellKnownMember)435, bag);
|
|
EnsureWellKnownMember((WellKnownMember)437, bag);
|
|
EnsureWellKnownMember((WellKnownMember)438, bag);
|
|
EnsureWellKnownMember((WellKnownMember)439, bag);
|
|
EnsureWellKnownMember((WellKnownMember)440, bag);
|
|
EnsureWellKnownMember((WellKnownMember)441, bag);
|
|
EnsureWellKnownMember((WellKnownMember)442, bag);
|
|
}
|
|
|
|
protected override void GenerateMethodImplementations()
|
|
{
|
|
base.GenerateMethodImplementations();
|
|
if (_isEnumerable)
|
|
{
|
|
GenerateIAsyncEnumerableImplementation_GetAsyncEnumerator();
|
|
}
|
|
GenerateIAsyncEnumeratorImplementation_MoveNextAsync();
|
|
GenerateIAsyncEnumeratorImplementation_Current();
|
|
GenerateIValueTaskSourceBoolImplementation_GetResult();
|
|
GenerateIValueTaskSourceBoolImplementation_GetStatus();
|
|
GenerateIValueTaskSourceBoolImplementation_OnCompleted();
|
|
GenerateIValueTaskSourceImplementation_GetResult();
|
|
GenerateIValueTaskSourceImplementation_GetStatus();
|
|
GenerateIValueTaskSourceImplementation_OnCompleted();
|
|
GenerateIAsyncDisposable_DisposeAsync();
|
|
}
|
|
|
|
protected override void GenerateControlFields()
|
|
{
|
|
base.GenerateControlFields();
|
|
NamedTypeSymbol namedTypeSymbol = F.SpecialType((SpecialType)7);
|
|
_promiseOfValueOrEndField = F.StateMachineField(F.WellKnownType((WellKnownType)290).Construct(namedTypeSymbol), GeneratedNames.MakeAsyncIteratorPromiseOfValueOrEndFieldName(), isPublic: true);
|
|
TypeSymbol iteratorElementType = ((AsyncStateMachine)stateMachineType).IteratorElementType;
|
|
_currentField = F.StateMachineField(iteratorElementType, GeneratedNames.MakeIteratorCurrentFieldName());
|
|
_disposeModeField = F.StateMachineField(namedTypeSymbol, GeneratedNames.MakeDisposeModeFieldName());
|
|
if (_isEnumerable && method.Parameters.Any((ParameterSymbol p) => p.IsSourceParameterWithEnumeratorCancellationAttribute()))
|
|
{
|
|
_combinedTokensField = F.StateMachineField(F.WellKnownType((WellKnownType)299), GeneratedNames.MakeAsyncIteratorCombinedTokensFieldName());
|
|
}
|
|
}
|
|
|
|
protected override void GenerateConstructor()
|
|
{
|
|
F.CurrentFunction = stateMachineType.Constructor;
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
instance.Add(F.BaseInitialization());
|
|
instance.Add((BoundStatement)GenerateCreateAndAssignBuilder());
|
|
instance.Add((BoundStatement)F.Assignment(F.InstanceField(stateField), F.Parameter(F.CurrentFunction.Parameters[0])));
|
|
BoundExpression boundExpression = MakeCurrentThreadId();
|
|
if (boundExpression != null && (object)initialThreadIdField != null)
|
|
{
|
|
instance.Add((BoundStatement)F.Assignment(F.InstanceField(initialThreadIdField), boundExpression));
|
|
}
|
|
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()));
|
|
}
|
|
|
|
private BoundExpressionStatement GenerateCreateAndAssignBuilder()
|
|
{
|
|
return F.Assignment(F.InstanceField(_builderField), F.StaticCall(null, _asyncMethodBuilderMemberCollection.CreateBuilder));
|
|
}
|
|
|
|
protected override void InitializeStateMachine(ArrayBuilder<BoundStatement> bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal)
|
|
{
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
StateMachineState value = (StateMachineState)(_isEnumerable ? (-2) : (-3));
|
|
bodyBuilder.Add((BoundStatement)F.Assignment(F.Local(stateMachineLocal), F.New(stateMachineType.Constructor.AsMember(frameType), F.Literal(value))));
|
|
}
|
|
|
|
protected override BoundStatement InitializeParameterField(MethodSymbol getEnumeratorMethod, ParameterSymbol parameter, BoundExpression resultParameter, BoundExpression parameterProxy)
|
|
{
|
|
if ((object)_combinedTokensField != null && parameter.IsSourceParameterWithEnumeratorCancellationAttribute() && parameter.Type.Equals(F.Compilation.GetWellKnownType((WellKnownType)298), (TypeCompareKind)0))
|
|
{
|
|
BoundParameter boundParameter = F.Parameter(getEnumeratorMethod.Parameters[0]);
|
|
BoundFieldAccess boundFieldAccess = F.Field(F.This(), _combinedTokensField);
|
|
return F.If(F.Call(parameterProxy, (WellKnownMember)457, F.Default(parameterProxy.Type)), F.Assignment(resultParameter, boundParameter), F.If(F.LogicalOr(F.Call(boundParameter, (WellKnownMember)457, parameterProxy), F.Call(boundParameter, (WellKnownMember)457, F.Default(boundParameter.Type))), F.Assignment(resultParameter, parameterProxy), F.Block(F.Assignment(boundFieldAccess, F.StaticCall((WellKnownMember)458, parameterProxy, boundParameter)), F.Assignment(resultParameter, F.Property(boundFieldAccess, (WellKnownMember)459)))));
|
|
}
|
|
return F.Assignment(resultParameter, parameterProxy);
|
|
}
|
|
|
|
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 GenerateIAsyncEnumeratorImplementation_MoveNextAsync()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)289).Construct(_currentField.Type);
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)428).AsMember(newOwner);
|
|
NamedTypeSymbol newOwner2 = (NamedTypeSymbol)_promiseOfValueOrEndField.Type;
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)431).AsMember(newOwner2);
|
|
MethodSymbol methodSymbol3 = F.WellKnownMethod((WellKnownMember)430).AsMember(newOwner2);
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)methodSymbol.ReturnType;
|
|
MethodSymbol ctor = F.WellKnownMethod((WellKnownMember)444).AsMember(namedTypeSymbol);
|
|
MethodSymbol ctor2 = F.WellKnownMethod((WellKnownMember)443).AsMember(namedTypeSymbol);
|
|
OpenMethodImplementation(methodSymbol);
|
|
GetPartsForStartingMachine(out var callReset, out var instSymbol, out var instAssignment, out var startCall, out var promise_get_Version);
|
|
BoundStatement boundStatement = F.If(F.IntEqual(F.InstanceField(stateField), F.Literal((StateMachineState)(-2))), F.Return(F.Default(namedTypeSymbol)));
|
|
LocalSymbol localSymbol = F.SynthesizedLocal(F.SpecialType((SpecialType)11), null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)(-2));
|
|
BoundLocal boundLocal = F.Local(localSymbol);
|
|
BoundExpressionStatement boundExpressionStatement = F.Assignment(boundLocal, F.Call(F.Field(F.This(), _promiseOfValueOrEndField), promise_get_Version));
|
|
BoundStatement boundStatement2 = F.If(F.IntEqual(F.Call(F.Field(F.This(), _promiseOfValueOrEndField), methodSymbol2, boundLocal), F.Literal(1)), F.Return(F.New(ctor, F.Call(F.Field(F.This(), _promiseOfValueOrEndField), methodSymbol3, boundLocal))));
|
|
BoundReturnStatement boundReturnStatement = F.Return(F.New(ctor2, F.This(), boundLocal));
|
|
F.CloseMethod(F.Block(ImmutableArray.Create(instSymbol, localSymbol), boundStatement, callReset, instAssignment, startCall, boundExpressionStatement, boundStatement2, boundReturnStatement));
|
|
}
|
|
|
|
private void GetPartsForStartingMachine(out BoundExpressionStatement callReset, out LocalSymbol instSymbol, out BoundStatement instAssignment, out BoundExpressionStatement startCall, out MethodSymbol promise_get_Version)
|
|
{
|
|
BoundFieldAccess receiver = F.InstanceField(_promiseOfValueOrEndField);
|
|
MethodSymbol methodSymbol = (MethodSymbol)F.WellKnownMethod((WellKnownMember)433, isOptional: true).SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
callReset = F.ExpressionStatement(F.Call(receiver, methodSymbol));
|
|
MethodSymbol methodSymbol2 = _asyncMethodBuilderMemberCollection.Start.Construct(stateMachineType);
|
|
instSymbol = F.SynthesizedLocal(stateMachineType, null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)(-2));
|
|
BoundLocal boundLocal = F.Local(instSymbol);
|
|
instAssignment = F.Assignment(boundLocal, F.This());
|
|
startCall = F.ExpressionStatement(F.Call(F.InstanceField(_builderField), methodSymbol2, ImmutableArray.Create((BoundExpression)boundLocal)));
|
|
promise_get_Version = F.WellKnownMethod((WellKnownMember)436).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
}
|
|
|
|
private void GenerateIAsyncDisposable_DisposeAsync()
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)426);
|
|
OpenMethodImplementation(methodSymbol);
|
|
TypeSymbol returnType = methodSymbol.ReturnType;
|
|
GetPartsForStartingMachine(out var callReset, out var instSymbol, out var instAssignment, out var startCall, out var promise_get_Version);
|
|
BoundStatement boundStatement = F.If(F.IntGreaterThanOrEqual(F.InstanceField(stateField), F.Literal((StateMachineState)(-1))), F.Throw(F.New(F.WellKnownType((WellKnownType)240))));
|
|
BoundStatement boundStatement2 = F.If(F.IntEqual(F.InstanceField(stateField), F.Literal((StateMachineState)(-2))), F.Return(F.Default(returnType)));
|
|
MethodSymbol ctor = F.WellKnownMethod((WellKnownMember)445).AsMember((NamedTypeSymbol)methodSymbol.ReturnType);
|
|
BoundReturnStatement boundReturnStatement = F.Return(F.New(ctor, F.This(), F.Call(F.InstanceField(_promiseOfValueOrEndField), promise_get_Version)));
|
|
F.CloseMethod(F.Block(ImmutableArray.Create(instSymbol), boundStatement, boundStatement2, F.Assignment(F.InstanceField(_disposeModeField), F.Literal(value: true)), callReset, instAssignment, startCall, boundReturnStatement));
|
|
}
|
|
|
|
private void GenerateIAsyncEnumeratorImplementation_Current()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)289).Construct(_currentField.Type);
|
|
MethodSymbol getterToImplement = F.WellKnownMethod((WellKnownMember)429).AsMember(newOwner);
|
|
OpenPropertyImplementation(getterToImplement);
|
|
F.CloseMethod(F.Block(F.Return(F.InstanceField(_currentField))));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceBoolImplementation_GetResult()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)293).Construct(F.SpecialType((SpecialType)7));
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)437).AsMember(newOwner);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)430).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Return(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]))));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceBoolImplementation_GetStatus()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)293).Construct(F.SpecialType((SpecialType)7));
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)438).AsMember(newOwner);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)431).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Return(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]))));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceBoolImplementation_OnCompleted()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)293).Construct(F.SpecialType((SpecialType)7));
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)439).AsMember(newOwner);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)432).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Block(F.ExpressionStatement(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]), F.Parameter(methodSymbol.Parameters[1]), F.Parameter(methodSymbol.Parameters[2]), F.Parameter(methodSymbol.Parameters[3]))), F.Return()));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceImplementation_GetResult()
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)440);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)430).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Block(F.ExpressionStatement(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]))), F.Return()));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceImplementation_GetStatus()
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)441);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)431).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Return(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]))));
|
|
}
|
|
|
|
private void GenerateIValueTaskSourceImplementation_OnCompleted()
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)442);
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)432).AsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
OpenMethodImplementation(methodSymbol);
|
|
F.CloseMethod(F.Block(F.ExpressionStatement(F.Call(F.InstanceField(_promiseOfValueOrEndField), methodSymbol2, F.Parameter(methodSymbol.Parameters[0]), F.Parameter(methodSymbol.Parameters[1]), F.Parameter(methodSymbol.Parameters[2]), F.Parameter(methodSymbol.Parameters[3]))), F.Return()));
|
|
}
|
|
|
|
private void GenerateIAsyncEnumerableImplementation_GetAsyncEnumerator()
|
|
{
|
|
NamedTypeSymbol newOwner = F.WellKnownType((WellKnownType)288).Construct(_currentField.Type);
|
|
MethodSymbol getEnumeratorMethod = F.WellKnownMethod((WellKnownMember)427).AsMember(newOwner);
|
|
BoundExpression managedThreadId = null;
|
|
GenerateIteratorGetEnumerator(getEnumeratorMethod, ref managedThreadId, (StateMachineState)(-3));
|
|
}
|
|
|
|
protected override void GenerateResetInstance(ArrayBuilder<BoundStatement> builder, StateMachineState initialState)
|
|
{
|
|
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
|
builder.Add((BoundStatement)F.Assignment(F.Field(F.This(), stateField), F.Literal(initialState)));
|
|
builder.Add((BoundStatement)GenerateCreateAndAssignBuilder());
|
|
builder.Add((BoundStatement)F.Assignment(F.InstanceField(_disposeModeField), F.Literal(value: false)));
|
|
}
|
|
|
|
protected override void GenerateMoveNext(SynthesizedImplementationMethod moveNextMethod)
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)435, isOptional: true);
|
|
if ((object)methodSymbol != null)
|
|
{
|
|
methodSymbol = (MethodSymbol)methodSymbol.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
}
|
|
MethodSymbol methodSymbol2 = F.WellKnownMethod((WellKnownMember)434, isOptional: true);
|
|
if ((object)methodSymbol2 != null)
|
|
{
|
|
methodSymbol2 = (MethodSymbol)methodSymbol2.SymbolAsMember((NamedTypeSymbol)_promiseOfValueOrEndField.Type);
|
|
}
|
|
new AsyncIteratorMethodToStateMachineRewriter(method, _methodOrdinal, _asyncMethodBuilderMemberCollection, new AsyncIteratorInfo(_promiseOfValueOrEndField, _combinedTokensField, _currentField, _disposeModeField, methodSymbol, methodSymbol2), F, stateField, _builderField, instanceIdField, (IReadOnlySet<Symbol>)(object)hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics).GenerateMoveNext(body, moveNextMethod);
|
|
}
|
|
}
|
|
|
|
private class AwaitDetector : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
|
|
{
|
|
private bool _sawAwait;
|
|
|
|
public static bool ContainsAwait(BoundNode node)
|
|
{
|
|
AwaitDetector awaitDetector = new AwaitDetector();
|
|
awaitDetector.Visit(node);
|
|
return awaitDetector._sawAwait;
|
|
}
|
|
|
|
public override BoundNode VisitAwaitExpression(BoundAwaitExpression node)
|
|
{
|
|
_sawAwait = true;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private readonly AsyncMethodBuilderMemberCollection _asyncMethodBuilderMemberCollection;
|
|
|
|
private readonly bool _constructedSuccessfully;
|
|
|
|
private readonly int _methodOrdinal;
|
|
|
|
private FieldSymbol? _builderField;
|
|
|
|
protected override bool PreserveInitialParameterValuesAndThreadId => false;
|
|
|
|
private AsyncRewriter(BoundStatement body, MethodSymbol method, int methodOrdinal, AsyncStateMachine stateMachineType, ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder, VariableSlotAllocator? slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
|
|
: base(body, method, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
|
|
{
|
|
_constructedSuccessfully = AsyncMethodBuilderMemberCollection.TryCreate(F, method, base.stateMachineType.TypeMap, out _asyncMethodBuilderMemberCollection);
|
|
_methodOrdinal = methodOrdinal;
|
|
}
|
|
|
|
internal static BoundStatement Rewrite(BoundStatement bodyWithAwaitLifted, MethodSymbol method, int methodOrdinal, ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder, VariableSlotAllocator? slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, out AsyncStateMachine? stateMachineType)
|
|
{
|
|
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
|
|
if (!method.IsAsync)
|
|
{
|
|
stateMachineType = null;
|
|
return bodyWithAwaitLifted;
|
|
}
|
|
CSharpCompilation declaringCompilation = method.DeclaringCompilation;
|
|
bool flag = method.IsAsyncReturningIAsyncEnumerable(declaringCompilation) || method.IsAsyncReturningIAsyncEnumerator(declaringCompilation);
|
|
if (flag && !method.IsIterator)
|
|
{
|
|
bool flag2 = AwaitDetector.ContainsAwait(bodyWithAwaitLifted);
|
|
diagnostics.Add(flag2 ? ErrorCode.ERR_PossibleAsyncIteratorWithoutYield : ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait, method.GetFirstLocation());
|
|
stateMachineType = null;
|
|
return bodyWithAwaitLifted;
|
|
}
|
|
TypeKind typeKind = (TypeKind)((((CompilationOptions)compilationState.Compilation.Options).EnableEditAndContinue || method.IsIterator) ? 2 : 10);
|
|
stateMachineType = new AsyncStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, typeKind);
|
|
((ModuleCompilationState<NamedTypeSymbol, MethodSymbol>)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)compilationState.ModuleBuilderOpt).CompilationState).SetStateMachineType(method, (NamedTypeSymbol)stateMachineType);
|
|
AsyncRewriter asyncRewriter = (flag ? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics) : new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics));
|
|
if (!asyncRewriter.VerifyPresenceOfRequiredAPIs())
|
|
{
|
|
return bodyWithAwaitLifted;
|
|
}
|
|
try
|
|
{
|
|
return asyncRewriter.Rewrite();
|
|
}
|
|
catch (SyntheticBoundNodeFactory.MissingPredefinedMember missingPredefinedMember)
|
|
{
|
|
((BindingDiagnosticBag)diagnostics).Add(missingPredefinedMember.Diagnostic);
|
|
return new BoundBadStatement(bodyWithAwaitLifted.Syntax, ImmutableArray.Create((BoundNode)bodyWithAwaitLifted), hasErrors: true);
|
|
}
|
|
}
|
|
|
|
protected bool VerifyPresenceOfRequiredAPIs()
|
|
{
|
|
BindingDiagnosticBag instance = BindingDiagnosticBag.GetInstance(withDiagnostics: true, ((BindingDiagnosticBag<AssemblySymbol>)(object)diagnostics).AccumulatesDependencies);
|
|
VerifyPresenceOfRequiredAPIs(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();
|
|
if (!num)
|
|
{
|
|
return _constructedSuccessfully;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected virtual void VerifyPresenceOfRequiredAPIs(BindingDiagnosticBag bag)
|
|
{
|
|
EnsureWellKnownMember((WellKnownMember)268, bag);
|
|
EnsureWellKnownMember((WellKnownMember)269, bag);
|
|
}
|
|
|
|
private Symbol EnsureWellKnownMember(WellKnownMember member, BindingDiagnosticBag bag)
|
|
{
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
return Binder.GetWellKnownTypeMember(F.Compilation, member, bag, body.Syntax.Location);
|
|
}
|
|
|
|
protected override void GenerateControlFields()
|
|
{
|
|
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
|
stateField = F.StateMachineField(F.SpecialType((SpecialType)13), GeneratedNames.MakeStateMachineStateFieldName(), isPublic: true);
|
|
_builderField = F.StateMachineField(_asyncMethodBuilderMemberCollection.BuilderType, GeneratedNames.AsyncBuilderFieldName(), isPublic: true);
|
|
MethodInstrumentation methodBodyInstrumentations = F.ModuleBuilderOpt.GetMethodBodyInstrumentations(method);
|
|
if (((MethodInstrumentation)(ref methodBodyInstrumentations)).Kinds.Contains((InstrumentationKind)(-1)))
|
|
{
|
|
instanceIdField = F.StateMachineField(F.SpecialType((SpecialType)16), GeneratedNames.MakeStateMachineStateIdFieldName(), isPublic: true);
|
|
}
|
|
}
|
|
|
|
protected override void GenerateMethodImplementations()
|
|
{
|
|
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Invalid comparison between Unknown and I4
|
|
MethodSymbol methodToImplement = F.WellKnownMethod((WellKnownMember)268);
|
|
MethodSymbol methodToImplement2 = F.WellKnownMethod((WellKnownMember)269);
|
|
SynthesizedImplementationMethod moveNextMethod = OpenMoveNextMethodImplementation(methodToImplement);
|
|
GenerateMoveNext(moveNextMethod);
|
|
OpenMethodImplementation(methodToImplement2, "SetStateMachine");
|
|
if ((int)F.CurrentType.TypeKind == 2)
|
|
{
|
|
F.CloseMethod(F.Return());
|
|
}
|
|
else
|
|
{
|
|
F.CloseMethod(F.Block(F.ExpressionStatement(F.Call(F.Field(F.This(), _builderField), _asyncMethodBuilderMemberCollection.SetStateMachine, new BoundExpression[1] { F.Parameter(F.CurrentFunction.Parameters[0]) })), F.Return()));
|
|
}
|
|
GenerateConstructor();
|
|
}
|
|
|
|
protected virtual void GenerateConstructor()
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000c: Invalid comparison between Unknown and I4
|
|
if ((int)stateMachineType.TypeKind == 2)
|
|
{
|
|
F.CurrentFunction = stateMachineType.Constructor;
|
|
F.CloseMethod(F.Block(ImmutableArray.Create(F.BaseInitialization(), F.Return())));
|
|
}
|
|
}
|
|
|
|
protected override void InitializeStateMachine(ArrayBuilder<BoundStatement> bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
if ((int)frameType.TypeKind == 2)
|
|
{
|
|
bodyBuilder.Add((BoundStatement)F.Assignment(F.Local(stateMachineLocal), F.New(frameType.InstanceConstructors[0])));
|
|
}
|
|
}
|
|
|
|
protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
|
|
{
|
|
if (!AsyncMethodBuilderMemberCollection.TryCreate(F, method, null, out var collection))
|
|
{
|
|
return new BoundBadStatement(F.Syntax, ImmutableArray<BoundNode>.Empty, hasErrors: true);
|
|
}
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
instance.Add((BoundStatement)F.Assignment(F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType)), F.StaticCall(null, collection.CreateBuilder)));
|
|
instance.Add(GenerateParameterStorage(stateMachineVariable, proxies));
|
|
instance.Add((BoundStatement)F.Assignment(F.Field(F.Local(stateMachineVariable), stateField.AsMember(frameType)), F.Literal((StateMachineState)(-1))));
|
|
if ((object)instanceIdField != null)
|
|
{
|
|
MethodSymbol methodSymbol = F.WellKnownMethod((WellKnownMember)361);
|
|
if ((object)methodSymbol != null)
|
|
{
|
|
instance.Add((BoundStatement)F.Assignment(F.Field(F.Local(stateMachineVariable), instanceIdField.AsMember(frameType)), F.Call(null, methodSymbol)));
|
|
}
|
|
}
|
|
MethodSymbol methodSymbol2 = collection.Start.Construct(frameType);
|
|
if (collection.CheckGenericMethodConstraints)
|
|
{
|
|
methodSymbol2.CheckConstraints(new ConstraintsHelper.CheckConstraintsArgs(F.Compilation, F.Compilation.Conversions, includeNullability: false, F.Syntax.Location, diagnostics));
|
|
}
|
|
instance.Add((BoundStatement)F.ExpressionStatement(F.Call(F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType)), methodSymbol2, ImmutableArray.Create((BoundExpression)F.Local(stateMachineVariable)))));
|
|
instance.Add((BoundStatement)(method.IsAsyncReturningVoid() ? F.Return() : F.Return(F.Property(F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType)), collection.Task))));
|
|
return F.Block(instance.ToImmutableAndFree());
|
|
}
|
|
|
|
protected virtual void GenerateMoveNext(SynthesizedImplementationMethod moveNextMethod)
|
|
{
|
|
new AsyncMethodToStateMachineRewriter(method, _methodOrdinal, _asyncMethodBuilderMemberCollection, F, stateField, _builderField, instanceIdField, (IReadOnlySet<Symbol>)(object)hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics).GenerateMoveNext(body, moveNextMethod);
|
|
}
|
|
}
|