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); } }
// // 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); }
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); }
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); }
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); }
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); }