public override void EmitForDispose (EmitContext ec, Iterator iterator, Label end, bool have_dispatcher) { if (emitted_dispose) return; emitted_dispose = true; Label end_of_try = ec.DefineLabel (); // Ensure that the only way we can get into this code is through a dispatcher if (have_dispatcher) ec.Emit (OpCodes.Br, end); ec.BeginExceptionBlock (); ec.MarkLabel (dispose_try_block); Label [] labels = null; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = (ResumableStatement) resume_points [i]; Label ret = s.PrepareForDispose (ec, end_of_try); if (ret.Equals (end_of_try) && labels == null) continue; if (labels == null) { labels = new Label [resume_points.Count]; for (int j = 0; j < i; ++j) labels [j] = end_of_try; } labels [i] = ret; } if (labels != null) { int j; for (j = 1; j < labels.Length; ++j) if (!labels [0].Equals (labels [j])) break; bool emit_dispatcher = j < labels.Length; if (emit_dispatcher) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit (OpCodes.Ldloc, iterator.CurrentPC); ec.EmitInt (first_resume_pc); ec.Emit (OpCodes.Sub); ec.Emit (OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); } foreach (ResumableStatement s in resume_points) s.EmitForDispose (ec, iterator, end_of_try, emit_dispatcher); } ec.MarkLabel (end_of_try); ec.BeginFinallyBlock (); EmitFinallyBody (ec); ec.EndExceptionBlock (); }
protected sealed override void DoEmit (EmitContext ec) { EmitPreTryBody (ec); if (resume_points != null) { ec.EmitInt ((int) Iterator.State.Running); ec.Emit (OpCodes.Stloc, iter.CurrentPC); } ec.BeginExceptionBlock (); if (resume_points != null) { ec.MarkLabel (resume_point); // For normal control flow, we want to fall-through the Switch // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above ec.Emit (OpCodes.Ldloc, iter.CurrentPC); ec.EmitInt (first_resume_pc); ec.Emit (OpCodes.Sub); Label [] labels = new Label [resume_points.Count]; for (int i = 0; i < resume_points.Count; ++i) labels [i] = resume_points [i].PrepareForEmit (ec); ec.Emit (OpCodes.Switch, labels); } EmitTryBody (ec); ec.BeginFinallyBlock (); Label start_finally = ec.DefineLabel (); if (resume_points != null) { ec.Emit (OpCodes.Ldloc, iter.SkipFinally); ec.Emit (OpCodes.Brfalse_S, start_finally); ec.Emit (OpCodes.Endfinally); } ec.MarkLabel (start_finally); EmitFinallyBody (ec); ec.EndExceptionBlock (); }