internal AsyncMethodToStateMachineRewriter(
            MethodSymbol method,
            int methodOrdinal,
            AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection,
            SyntheticBoundNodeFactory F,
            FieldSymbol state,
            FieldSymbol builder,
            IReadOnlySet <Symbol> hoistedVariables,
            IReadOnlyDictionary <Symbol, CapturedSymbolReplacement> nonReusableLocalProxies,
            SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
            VariableSlotAllocator slotAllocatorOpt,
            int nextFreeHoistedLocalSlot,
            DiagnosticBag diagnostics)
            : base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics, useFinalizerBookkeeping: false)
        {
            _method = method;
            _asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection;
            _asyncMethodBuilderField            = builder;
            _exprReturnLabel = F.GenerateLabel("exprReturn");
            _exitLabel       = F.GenerateLabel("exitLabel");

            _exprRetValue = method.IsGenericTaskReturningAsync(F.Compilation)
                ? F.SynthesizedLocal(asyncMethodBuilderMemberCollection.ResultType, syntax: F.Syntax, kind: SynthesizedLocalKind.AsyncMethodReturnValue)
                : null;

            _awaiterFields = new Dictionary <TypeSymbol, FieldSymbol>(TypeSymbol.EqualsIgnoringDynamicTupleNamesAndNullabilityComparer);
            _nextAwaiterId = slotAllocatorOpt?.PreviousAwaiterSlotCount ?? 0;
        }
Example #2
0
 private AsyncRewriter(
     BoundStatement body,
     MethodSymbol method,
     int methodOrdinal,
     AsyncStateMachine stateMachineType,
     VariableSlotAllocator slotAllocatorOpt,
     TypeCompilationState compilationState,
     DiagnosticBag diagnostics)
     : base(body, method, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
 {
     _constructedSuccessfully = AsyncMethodBuilderMemberCollection.TryCreate(F, method, this.stateMachineType.TypeMap, out _asyncMethodBuilderMemberCollection);
     _methodOrdinal           = methodOrdinal;
 }
Example #3
0
        private static bool TryCreate(
            SyntheticBoundNodeFactory F,
            bool customBuilder,
            NamedTypeSymbol builderType,
            TypeSymbol resultType,
            MethodSymbol createBuilderMethod,
            PropertySymbol taskProperty,
            WellKnownMember?setException,
            WellKnownMember setResult,
            WellKnownMember awaitOnCompleted,
            WellKnownMember awaitUnsafeOnCompleted,
            WellKnownMember start,
            WellKnownMember?setStateMachine,
            out AsyncMethodBuilderMemberCollection collection)
        {
            MethodSymbol setExceptionMethod;
            MethodSymbol setResultMethod;
            MethodSymbol awaitOnCompletedMethod;
            MethodSymbol awaitUnsafeOnCompletedMethod;
            MethodSymbol startMethod;
            MethodSymbol setStateMachineMethod;

            if (TryGetBuilderMember(F, setException, builderType, customBuilder, out setExceptionMethod) &&
                TryGetBuilderMember(F, setResult, builderType, customBuilder, out setResultMethod) &&
                TryGetBuilderMember(F, awaitOnCompleted, builderType, customBuilder, out awaitOnCompletedMethod) &&
                TryGetBuilderMember(F, awaitUnsafeOnCompleted, builderType, customBuilder, out awaitUnsafeOnCompletedMethod) &&
                TryGetBuilderMember(F, start, builderType, customBuilder, out startMethod) &&
                TryGetBuilderMember(F, setStateMachine, builderType, customBuilder, out setStateMachineMethod))
            {
                collection = new AsyncMethodBuilderMemberCollection(
                    builderType,
                    resultType,
                    createBuilderMethod,
                    setExceptionMethod,
                    setResultMethod,
                    awaitOnCompletedMethod,
                    awaitUnsafeOnCompletedMethod,
                    startMethod,
                    setStateMachineMethod,
                    taskProperty,
                    checkGenericMethodConstraints: customBuilder);

                return(true);
            }

            collection = default(AsyncMethodBuilderMemberCollection);
            return(false);
        }
Example #4
0
            protected override void GenerateConstructor()
            {
                // Produces:
                // .ctor(int state)
                // {
                //     this.state = state;
                //     this.initialThreadId = {managedThreadId};
                //     this.builder = System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create();
                // }
                Debug.Assert(stateMachineType.Constructor is IteratorConstructor);

                F.CurrentFunction = stateMachineType.Constructor;
                var bodyBuilder = ArrayBuilder <BoundStatement> .GetInstance();

                bodyBuilder.Add(F.BaseInitialization());
                bodyBuilder.Add(F.Assignment(F.InstanceField(stateField), F.Parameter(F.CurrentFunction.Parameters[0]))); // this.state = state;

                var managedThreadId = MakeCurrentThreadId();

                if (managedThreadId != null && (object)initialThreadIdField != null)
                {
                    // this.initialThreadId = {managedThreadId};
                    bodyBuilder.Add(F.Assignment(F.InstanceField(initialThreadIdField), managedThreadId));
                }

                // this.builder = System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create();
                AsyncMethodBuilderMemberCollection methodScopeAsyncMethodBuilderMemberCollection;
                bool found = AsyncMethodBuilderMemberCollection.TryCreate(F, method, typeMap: null, out methodScopeAsyncMethodBuilderMemberCollection);

                Debug.Assert(found);

                bodyBuilder.Add(
                    F.Assignment(
                        F.InstanceField(_builderField),
                        F.StaticCall(
                            null,
                            methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

                bodyBuilder.Add(F.Return());
                F.CloseMethod(F.Block(bodyBuilder.ToImmutableAndFree()));
                bodyBuilder = null;
            }
        private int _nextYieldReturnState = StateMachineStates.InitialAsyncIteratorStateMachine;  // -3

        internal AsyncIteratorMethodToStateMachineRewriter(MethodSymbol method,
                                                           int methodOrdinal,
                                                           AsyncMethodBuilderMemberCollection asyncMethodBuilderMemberCollection,
                                                           AsyncIteratorInfo asyncIteratorInfo,
                                                           SyntheticBoundNodeFactory F,
                                                           FieldSymbol state,
                                                           FieldSymbol builder,
                                                           IReadOnlySet <Symbol> hoistedVariables,
                                                           IReadOnlyDictionary <Symbol, CapturedSymbolReplacement> nonReusableLocalProxies,
                                                           SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
                                                           VariableSlotAllocator slotAllocatorOpt,
                                                           int nextFreeHoistedLocalSlot,
                                                           DiagnosticBag diagnostics)
            : base(method, methodOrdinal, asyncMethodBuilderMemberCollection, F,
                   state, builder, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals,
                   slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
        {
            Debug.Assert(asyncIteratorInfo != null);

            _asyncIteratorInfo           = asyncIteratorInfo;
            _enclosingFinallyOrExitLabel = _exprReturnLabel;
            _exprReturnLabelTrue         = F.GenerateLabel("yieldReturn");
        }
Example #6
0
        protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType)
        {
            // If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder<T>
            // needs to use the method's type parameters inside the rewritten method body. All other methods generated
            // during async rewriting are members of the synthesized state machine struct, and use the type parameters
            // structs type parameters.
            AsyncMethodBuilderMemberCollection methodScopeAsyncMethodBuilderMemberCollection;

            if (!AsyncMethodBuilderMemberCollection.TryCreate(F, method, null, out methodScopeAsyncMethodBuilderMemberCollection))
            {
                return(new BoundBadStatement(F.Syntax, ImmutableArray <BoundNode> .Empty, hasErrors: true));
            }

            var bodyBuilder = ArrayBuilder <BoundStatement> .GetInstance();

            var builderVariable = F.SynthesizedLocal(methodScopeAsyncMethodBuilderMemberCollection.BuilderType, null);

            // local.$builder = System.Runtime.CompilerServices.AsyncTaskMethodBuilder<typeArgs>.Create();
            bodyBuilder.Add(
                F.Assignment(
                    F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType)),
                    F.StaticCall(
                        null,
                        methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

            // local.$stateField = NotStartedStateMachine
            bodyBuilder.Add(
                F.Assignment(
                    F.Field(F.Local(stateMachineVariable), stateField.AsMember(frameType)),
                    F.Literal(StateMachineStates.NotStartedStateMachine)));

            bodyBuilder.Add(
                F.Assignment(
                    F.Local(builderVariable),
                    F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType))));

            // local.$builder.Start(ref local) -- binding to the method AsyncTaskMethodBuilder<typeArgs>.Start()
            var startMethod = methodScopeAsyncMethodBuilderMemberCollection.Start.Construct(frameType);

            if (methodScopeAsyncMethodBuilderMemberCollection.CheckGenericMethodConstraints)
            {
                startMethod.CheckConstraints(F.Compilation.Conversions, F.Syntax, F.Compilation, diagnostics);
            }
            bodyBuilder.Add(
                F.ExpressionStatement(
                    F.Call(
                        F.Local(builderVariable),
                        startMethod,
                        ImmutableArray.Create <BoundExpression>(F.Local(stateMachineVariable)))));

            bodyBuilder.Add(method.IsVoidReturningAsync()
                ? F.Return()
                : F.Return(
                                F.Property(
                                    F.Field(F.Local(stateMachineVariable), _builderField.AsMember(frameType)),
                                    methodScopeAsyncMethodBuilderMemberCollection.Task)));

            return(F.Block(
                       ImmutableArray.Create(builderVariable),
                       bodyBuilder.ToImmutableAndFree()));
        }
Example #7
0
        internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection)
        {
            if (method.IsIterator)
            {
                var builderType = F.WellKnownType(WellKnownType.core_runtime_compiler_AsyncIteratorMethodBuilder);
                Debug.Assert((object)builderType != null);

                TryGetBuilderMember <MethodSymbol>(
                    F,
                    WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Create,
                    builderType,
                    customBuilder: false,
                    out MethodSymbol createBuilderMethod);

                if (createBuilderMethod is null)
                {
                    collection = default;
                    return(false);
                }

                return(TryCreate(
                           F,
                           customBuilder: false,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: null,
                           setException: null, // unused
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__Complete,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncIteratorMethodBuilder__MoveNext_T,
                           setStateMachine: null, // unused
                           collection: out collection));
            }

            if (method.IsVoidReturningAsync())
            {
                var builderType = F.WellKnownType(WellKnownType.core_runtime_compiler_AsyncVoidMethodBuilder);
                Debug.Assert((object)builderType != null);
                MethodSymbol createBuilderMethod;
                bool         customBuilder = false;
                TryGetBuilderMember <MethodSymbol>(
                    F,
                    WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Create,
                    builderType,
                    customBuilder,
                    out createBuilderMethod);
                if ((object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: null,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsTaskReturningAsync(F.Compilation))
            {
                var             returnType = (NamedTypeSymbol)method.ReturnType.TypeSymbol;
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false);
                    if ((object)builderType != null)
                    {
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.core_runtime_compiler_AsyncTaskMethodBuilder);
                    Debug.Assert((object)builderType != null);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)createBuilderMethod == null ||
                    (object)taskProperty == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsGenericTaskReturningAsync(F.Compilation))
            {
                var returnType = (NamedTypeSymbol)method.ReturnType.TypeSymbol;
                var resultType = returnType.TypeArgumentsNoUseSiteDiagnostics.Single().TypeSymbol;
                if (resultType.IsDynamic())
                {
                    resultType = F.SpecialType(SpecialType.System_Object);
                }
                if (typeMap != null)
                {
                    resultType = typeMap.SubstituteType(resultType).TypeSymbol;
                }
                returnType = returnType.ConstructedFrom.Construct(resultType);
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true);
                    if ((object)builderType != null)
                    {
                        builderType         = builderType.ConstructedFrom.Construct(resultType);
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.core_runtime_compiler_AsyncTaskMethodBuilder_T);
                    Debug.Assert((object)builderType != null);
                    builderType = builderType.Construct(resultType);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)taskProperty == null ||
                    (object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: resultType,
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine,
                           collection: out collection));
            }

            throw ExceptionUtilities.UnexpectedValue(method);
        }