예제 #1
0
        public override void Emit(EmitContext ec)
        {
            //
            // Load Iterator storey instance
            //
            method.Storey.Instance.Emit(ec);

            //
            // Initialize iterator PC when it's unitialized
            //
            if (IsEnumerable)
            {
                ILGenerator ig = ec.ig;
                ig.Emit(OpCodes.Dup);
                IntConstant.EmitInt(ig, (int)State.Uninitialized);

                FieldInfo field = IteratorHost.PC.FieldBuilder;
#if GMCS_SOURCE
                if (Storey.MemberName.IsGeneric)
                {
                    field = TypeBuilder.GetField(Storey.Instance.Type, field);
                }
#endif
                ig.Emit(OpCodes.Stfld, field);
            }
        }
예제 #2
0
        //
        // Called back from Yield
        //
        public void MarkYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point)
        {
            ILGenerator ig = ec.ig;

            // Store the new current
            ig.Emit(OpCodes.Ldarg_0);
            expr.Emit(ec);
            ig.Emit(OpCodes.Stfld, IteratorHost.CurrentField.FieldBuilder);

            // store resume program-counter
            ig.Emit(OpCodes.Ldarg_0);
            IntConstant.EmitInt(ig, resume_pc);
            ig.Emit(OpCodes.Stfld, IteratorHost.PC.FieldBuilder);

            // mark finally blocks as disabled
            if (unwind_protect && skip_finally != null)
            {
                ig.Emit(OpCodes.Ldc_I4_1);
                ig.Emit(OpCodes.Stloc, skip_finally);
            }

            // Return ok
            ig.Emit(unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok);

            ig.MarkLabel(resume_point);
        }
예제 #3
0
        public void EmitDispose(EmitContext ec)
        {
            ILGenerator ig = ec.ig;

            Label end = ig.DefineLabel();

            Label [] labels          = null;
            int      n_resume_points = resume_points == null ? 0 : resume_points.Count;

            for (int i = 0; i < n_resume_points; ++i)
            {
                ResumableStatement s = (ResumableStatement)resume_points [i];
                Label ret            = s.PrepareForDispose(ec, end);
                if (ret.Equals(end) && labels == null)
                {
                    continue;
                }
                if (labels == null)
                {
                    labels = new Label [resume_points.Count + 1];
                    for (int j = 0; j <= i; ++j)
                    {
                        labels [j] = end;
                    }
                }
                labels [i + 1] = ret;
            }

            if (labels != null)
            {
                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);
            }

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

            if (labels != null)
            {
                //SymbolWriter.StartIteratorDispatcher (ec.ig);
                ig.Emit(OpCodes.Ldloc, current_pc);
                ig.Emit(OpCodes.Switch, labels);
                //SymbolWriter.EndIteratorDispatcher (ec.ig);

                foreach (ResumableStatement s in resume_points)
                {
                    s.EmitForDispose(ec, this, end, true);
                }
            }

            ig.MarkLabel(end);
        }
예제 #4
0
        void EmitMoveNext_NoResumePoints(EmitContext ec, Block original_block)
        {
            ILGenerator ig = ec.ig;

            ig.Emit(OpCodes.Ldarg_0);
            ig.Emit(OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);

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

            // We only care if the PC is zero (start executing) or non-zero (don't do anything)
            ig.Emit(OpCodes.Brtrue, move_next_error);

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

            ig.MarkLabel(move_next_error);
            ig.Emit(OpCodes.Ldc_I4_0);
            ig.Emit(OpCodes.Ret);
        }
예제 #5
0
                protected override void DoEmit(EmitContext ec)
                {
                    ILGenerator ig         = ec.ig;
                    Label       label_init = ig.DefineLabel();

                    ig.Emit(OpCodes.Ldarg_0);
                    ig.Emit(OpCodes.Ldflda, host.PC.FieldBuilder);
                    IntConstant.EmitInt(ig, (int)Iterator.State.Start);
                    IntConstant.EmitInt(ig, (int)Iterator.State.Uninitialized);
                    ig.Emit(OpCodes.Call, TypeManager.int_interlocked_compare_exchange);

                    IntConstant.EmitInt(ig, (int)Iterator.State.Uninitialized);
                    ig.Emit(OpCodes.Bne_Un_S, label_init);

                    ig.Emit(OpCodes.Ldarg_0);
                    ig.Emit(OpCodes.Ret);

                    ig.MarkLabel(label_init);

                    new_storey.Emit(ec);
                    ig.Emit(OpCodes.Ret);
                }
예제 #6
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);
        }