Example #1
0
        void EmitMoveNext(EmitContext ec)
        {
            move_next_ok    = ec.DefineLabel();
            move_next_error = ec.DefineLabel();

            if (resume_points == null)
            {
                EmitMoveNext_NoResumePoints(ec, block);
                return;
            }

            current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt);
            ec.EmitThis();
            ec.Emit(OpCodes.Ldfld, storey.PC.Spec);
            ec.Emit(OpCodes.Stloc, current_pc);

            // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit
            ec.EmitThis();
            ec.EmitInt((int)IteratorStorey.State.After);
            ec.Emit(OpCodes.Stfld, storey.PC.Spec);

            Label[] labels = new Label[1 + resume_points.Count];
            labels[0] = ec.DefineLabel();

            bool need_skip_finally = false;

            for (int i = 0; i < resume_points.Count; ++i)
            {
                ResumableStatement s = resume_points[i];
                need_skip_finally |= s is ExceptionStatement;
                labels[i + 1]      = s.PrepareForEmit(ec);
            }

            if (need_skip_finally)
            {
                skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool);
                ec.EmitInt(0);
                ec.Emit(OpCodes.Stloc, skip_finally);
            }

            var async_init = this as AsyncInitializer;

            if (async_init != null)
            {
                ec.BeginExceptionBlock();
            }

            SymbolWriter.StartIteratorDispatcher(ec);
            ec.Emit(OpCodes.Ldloc, current_pc);
            ec.Emit(OpCodes.Switch, labels);

            ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher(ec);

            ec.MarkLabel(labels[0]);

            iterator_body_end = ec.DefineLabel();

            SymbolWriter.StartIteratorBody(ec);
            block.Emit(ec);
            SymbolWriter.EndIteratorBody(ec);

            SymbolWriter.StartIteratorDispatcher(ec);

            ec.MarkLabel(iterator_body_end);

            if (async_init != null)
            {
                var catch_value = LocalVariable.CreateCompilerGenerated(ec.Module.Compiler.BuiltinTypes.Exception, block, Location);

                ec.BeginCatchBlock(catch_value.Type);
                catch_value.EmitAssign(ec);

                ec.EmitThis();
                ec.EmitInt((int)IteratorStorey.State.After);
                ec.Emit(OpCodes.Stfld, storey.PC.Spec);

                ((AsyncTaskStorey)async_init.Storey).EmitSetException(ec, new LocalVariableReference(catch_value, Location));

                ec.Emit(OpCodes.Leave, move_next_ok);
                ec.EndExceptionBlock();
            }

            ec.EmitThis();
            ec.EmitInt((int)IteratorStorey.State.After);
            ec.Emit(OpCodes.Stfld, storey.PC.Spec);

            EmitMoveNextEpilogue(ec);

            ec.MarkLabel(move_next_error);

            if (ReturnType.Kind != MemberKind.Void)
            {
                ec.EmitInt(0);
                ec.Emit(OpCodes.Ret);
            }

            ec.MarkLabel(move_next_ok);

            if (ReturnType.Kind != MemberKind.Void)
            {
                ec.EmitInt(1);
                ec.Emit(OpCodes.Ret);
            }

            SymbolWriter.EndIteratorDispatcher(ec);
        }
Example #2
0
        void EmitMoveNext(EmitContext ec)
        {
            move_next_ok    = ec.DefineLabel();
            move_next_error = ec.DefineLabel();

            if (resume_points == null)
            {
                EmitMoveNext_NoResumePoints(ec, block);
                return;
            }

            current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt);
            ec.Emit(OpCodes.Ldarg_0);
            ec.Emit(OpCodes.Ldfld, IteratorHost.PC.Spec);
            ec.Emit(OpCodes.Stloc, current_pc);

            // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit
            ec.Emit(OpCodes.Ldarg_0);
            ec.EmitInt((int)State.After);
            ec.Emit(OpCodes.Stfld, IteratorHost.PC.Spec);

            Label [] labels = new Label [1 + resume_points.Count];
            labels [0] = ec.DefineLabel();

            bool need_skip_finally = false;

            for (int i = 0; i < resume_points.Count; ++i)
            {
                ResumableStatement s = resume_points [i];
                need_skip_finally |= s is ExceptionStatement;
                labels [i + 1]     = s.PrepareForEmit(ec);
            }

            if (need_skip_finally)
            {
                skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool);
                ec.Emit(OpCodes.Ldc_I4_0);
                ec.Emit(OpCodes.Stloc, skip_finally);
            }

            SymbolWriter.StartIteratorDispatcher(ec);
            ec.Emit(OpCodes.Ldloc, current_pc);
            ec.Emit(OpCodes.Switch, labels);

            ec.Emit(OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher(ec);

            ec.MarkLabel(labels [0]);

            SymbolWriter.StartIteratorBody(ec);
            block.Emit(ec);
            SymbolWriter.EndIteratorBody(ec);

            SymbolWriter.StartIteratorDispatcher(ec);

            ec.Emit(OpCodes.Ldarg_0);
            ec.EmitInt((int)State.After);
            ec.Emit(OpCodes.Stfld, IteratorHost.PC.Spec);

            ec.MarkLabel(move_next_error);
            ec.EmitInt(0);
            ec.Emit(OpCodes.Ret);

            ec.MarkLabel(move_next_ok);
            ec.Emit(OpCodes.Ldc_I4_1);
            ec.Emit(OpCodes.Ret);

            SymbolWriter.EndIteratorDispatcher(ec);
        }
Example #3
0
        internal void EmitMoveNext(EmitContext ec, Block original_block)
        {
            ILGenerator ig = ec.ig;

            move_next_ok    = ig.DefineLabel();
            move_next_error = ig.DefineLabel();

            if (resume_points == null)
            {
                EmitMoveNext_NoResumePoints(ec, original_block);
                return;
            }

            current_pc = ec.GetTemporaryLocal(TypeManager.uint32_type);
            ig.Emit(OpCodes.Ldarg_0);
            ig.Emit(OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
            ig.Emit(OpCodes.Stloc, current_pc);

            // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit
            ig.Emit(OpCodes.Ldarg_0);
            IntConstant.EmitInt(ig, (int)State.After);
            ig.Emit(OpCodes.Stfld, IteratorHost.PC.FieldBuilder);

            Label [] labels = new Label [1 + resume_points.Count];
            labels [0] = ig.DefineLabel();

            bool need_skip_finally = false;

            for (int i = 0; i < resume_points.Count; ++i)
            {
                ResumableStatement s = (ResumableStatement)resume_points [i];
                need_skip_finally |= s is ExceptionStatement;
                labels [i + 1]     = s.PrepareForEmit(ec);
            }

            if (need_skip_finally)
            {
                skip_finally = ec.GetTemporaryLocal(TypeManager.bool_type);
                ig.Emit(OpCodes.Ldc_I4_0);
                ig.Emit(OpCodes.Stloc, skip_finally);
            }

            SymbolWriter.StartIteratorDispatcher(ec.ig);
            ig.Emit(OpCodes.Ldloc, current_pc);
            ig.Emit(OpCodes.Switch, labels);

            ig.Emit(OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher(ec.ig);

            ig.MarkLabel(labels [0]);

            SymbolWriter.StartIteratorBody(ec.ig);
            original_block.Emit(ec);
            SymbolWriter.EndIteratorBody(ec.ig);

            SymbolWriter.StartIteratorDispatcher(ec.ig);

            ig.Emit(OpCodes.Ldarg_0);
            IntConstant.EmitInt(ig, (int)State.After);
            ig.Emit(OpCodes.Stfld, IteratorHost.PC.FieldBuilder);

            ig.MarkLabel(move_next_error);
            ig.Emit(OpCodes.Ldc_I4_0);
            ig.Emit(OpCodes.Ret);

            ig.MarkLabel(move_next_ok);
            ig.Emit(OpCodes.Ldc_I4_1);
            ig.Emit(OpCodes.Ret);

            SymbolWriter.EndIteratorDispatcher(ec.ig);
        }