public override void Emit (EmitContext ec) { int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; if (power == 0) { if (Value <= int.MaxValue && Value >= int.MinValue) { if (TypeManager.void_decimal_ctor_int_arg == null) { TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int32_type); if (TypeManager.void_decimal_ctor_int_arg == null) return; } ec.EmitInt ((int) Value); ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); return; } if (Value <= long.MaxValue && Value >= long.MinValue) { if (TypeManager.void_decimal_ctor_long_arg == null) { TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int64_type); if (TypeManager.void_decimal_ctor_long_arg == null) return; } ec.EmitLong ((long) Value); ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg); return; } } ec.EmitInt (words [0]); ec.EmitInt (words [1]); ec.EmitInt (words [2]); // sign ec.EmitInt (words [3] >> 31); // power ec.EmitInt (power); if (TypeManager.void_decimal_ctor_five_args == null) { TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor ( TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type, TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type); if (TypeManager.void_decimal_ctor_five_args == null) return; } ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); }
void EmitMoveNext_NoResumePoints(EmitContext ec, Block original_block) { ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec); ec.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); // We only care if the PC is zero (start executing) or non-zero (don't do anything) ec.Emit (OpCodes.Brtrue, move_next_error); SymbolWriter.StartIteratorBody (ec); original_block.Emit (ec); SymbolWriter.EndIteratorBody (ec); ec.MarkLabel (move_next_error); ec.Emit (OpCodes.Ldc_I4_0); ec.Emit (OpCodes.Ret); }
protected override void DoEmit(EmitContext ec) { Label label_init = ec.DefineLabel (); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldflda, host.PC.Spec); ec.EmitInt ((int) Iterator.State.Start); ec.EmitInt ((int) Iterator.State.Uninitialized); ec.Emit (OpCodes.Call, TypeManager.int_interlocked_compare_exchange); ec.EmitInt ((int) Iterator.State.Uninitialized); ec.Emit (OpCodes.Bne_Un_S, label_init); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ret); ec.MarkLabel (label_init); new_storey.Emit (ec); ec.Emit (OpCodes.Ret); }
void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec); 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(); } ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.MarkLabel(labels[0]); iterator_body_end = ec.DefineLabel(); block.EmitEmbedded(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.Mark(Block.Original.EndLocation); 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); } }
internal void EmitMoveNext(EmitContext ec, Block original_block) { move_next_ok = ec.DefineLabel (); move_next_error = ec.DefineLabel (); if (resume_points == null) { EmitMoveNext_NoResumePoints (ec, original_block); return; } current_pc = ec.GetTemporaryLocal (TypeManager.uint32_type); 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 (TypeManager.bool_type); 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); original_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); }
public override void Emit (EmitContext ec) { MethodSpec m; int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; if (power == 0) { if (Value <= int.MaxValue && Value >= int.MinValue) { m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); if (m == null) { return; } ec.EmitInt ((int) Value); ec.Emit (OpCodes.Newobj, m); return; } if (Value <= long.MaxValue && Value >= long.MinValue) { m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); if (m == null) { return; } ec.EmitLong ((long) Value); ec.Emit (OpCodes.Newobj, m); return; } } ec.EmitInt (words [0]); ec.EmitInt (words [1]); ec.EmitInt (words [2]); // sign ec.EmitInt (words [3] >> 31); // power ec.EmitInt (power); m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); if (m != null) { ec.Emit (OpCodes.Newobj, m); } }
public override void Emit (EmitContext ec) { if (Value) ec.EmitInt (1); else ec.EmitInt (0); }
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 (); }
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 (); }
void EmitObjectInteger (EmitContext ec, object k) { if (k is int) ec.EmitInt ((int) k); else if (k is Constant) { EmitObjectInteger (ec, ((Constant) k).GetValue ()); } else if (k is uint) ec.EmitInt (unchecked ((int) (uint) k)); else if (k is long) { if ((long) k >= int.MinValue && (long) k <= int.MaxValue) { ec.EmitInt ((int) (long) k); ec.Emit (OpCodes.Conv_I8); } else ec.EmitLong ((long) k); } else if (k is ulong) { ulong ul = (ulong) k; if (ul < (1L<<32)) { ec.EmitInt (unchecked ((int) ul)); ec.Emit (OpCodes.Conv_U8); } else { ec.EmitLong (unchecked ((long) ul)); } } else if (k is char) ec.EmitInt ((int) ((char) k)); else if (k is sbyte) ec.EmitInt ((int) ((sbyte) k)); else if (k is byte) ec.EmitInt ((int) ((byte) k)); else if (k is short) ec.EmitInt ((int) ((short) k)); else if (k is ushort) ec.EmitInt ((int) ((ushort) k)); else if (k is bool) ec.EmitInt (((bool) k) ? 1 : 0); else throw new Exception ("Unhandled case"); }
/// <summary> /// This method emits code for a lookup-based switch statement (non-string) /// Basically it groups the cases into blocks that are at least half full, /// and then spits out individual lookup opcodes for each block. /// It emits the longest blocks first, and short blocks are just /// handled with direct compares. /// </summary> /// <param name="ec"></param> /// <param name="val"></param> /// <returns></returns> void TableSwitchEmit (EmitContext ec, Expression val) { int element_count = Elements.Count; object [] element_keys = new object [element_count]; Elements.Keys.CopyTo (element_keys, 0); Array.Sort (element_keys); // initialize the block list with one element per key var key_blocks = new List<KeyBlock> (element_count); foreach (object key in element_keys) key_blocks.Add (new KeyBlock (System.Convert.ToInt64 (key))); KeyBlock current_kb; // iteratively merge the blocks while they are at least half full // there's probably a really cool way to do this with a tree... while (key_blocks.Count > 1) { var key_blocks_new = new List<KeyBlock> (); current_kb = (KeyBlock) key_blocks [0]; for (int ikb = 1; ikb < key_blocks.Count; ikb++) { KeyBlock kb = (KeyBlock) key_blocks [ikb]; if ((current_kb.Size + kb.Size) * 2 >= KeyBlock.TotalLength (current_kb, kb)) { // merge blocks current_kb.last = kb.last; current_kb.Size += kb.Size; } else { // start a new block key_blocks_new.Add (current_kb); current_kb = kb; } } key_blocks_new.Add (current_kb); if (key_blocks.Count == key_blocks_new.Count) break; key_blocks = key_blocks_new; } // initialize the key lists foreach (KeyBlock kb in key_blocks) kb.element_keys = new List<object> (); // fill the key lists int iBlockCurr = 0; if (key_blocks.Count > 0) { current_kb = (KeyBlock) key_blocks [0]; foreach (object key in element_keys) { bool next_block = (key is UInt64) ? (ulong) key > (ulong) current_kb.last : System.Convert.ToInt64 (key) > current_kb.last; if (next_block) current_kb = (KeyBlock) key_blocks [++iBlockCurr]; current_kb.element_keys.Add (key); } } // sort the blocks so we can tackle the largest ones first key_blocks.Sort (); // okay now we can start... Label lbl_end = ec.DefineLabel (); // at the end ;-) Label lbl_default = default_target; Type type_keys = null; if (element_keys.Length > 0) type_keys = element_keys [0].GetType (); // used for conversions TypeSpec compare_type; if (TypeManager.IsEnumType (SwitchType)) compare_type = EnumSpec.GetUnderlyingType (SwitchType); else compare_type = SwitchType; for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock) { KeyBlock kb = ((KeyBlock) key_blocks [iBlock]); lbl_default = (iBlock == 0) ? default_target : ec.DefineLabel (); if (kb.Length <= 2) { foreach (object key in kb.element_keys) { SwitchLabel sl = (SwitchLabel) Elements [key]; if (key is int && (int) key == 0) { val.EmitBranchable (ec, sl.GetILLabel (ec), false); } else { val.Emit (ec); EmitObjectInteger (ec, key); ec.Emit (OpCodes.Beq, sl.GetILLabel (ec)); } } } else { // TODO: if all the keys in the block are the same and there are // no gaps/defaults then just use a range-check. if (compare_type == TypeManager.int64_type || compare_type == TypeManager.uint64_type) { // TODO: optimize constant/I4 cases // check block range (could be > 2^31) val.Emit (ec); EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys)); ec.Emit (OpCodes.Blt, lbl_default); val.Emit (ec); EmitObjectInteger (ec, System.Convert.ChangeType (kb.last, type_keys)); ec.Emit (OpCodes.Bgt, lbl_default); // normalize range val.Emit (ec); if (kb.first != 0) { EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys)); ec.Emit (OpCodes.Sub); } ec.Emit (OpCodes.Conv_I4); // assumes < 2^31 labels! } else { // normalize range val.Emit (ec); int first = (int) kb.first; if (first > 0) { ec.EmitInt (first); ec.Emit (OpCodes.Sub); } else if (first < 0) { ec.EmitInt (-first); ec.Emit (OpCodes.Add); } } // first, build the list of labels for the switch int iKey = 0; int cJumps = kb.Length; Label [] switch_labels = new Label [cJumps]; for (int iJump = 0; iJump < cJumps; iJump++) { object key = kb.element_keys [iKey]; if (System.Convert.ToInt64 (key) == kb.first + iJump) { SwitchLabel sl = (SwitchLabel) Elements [key]; switch_labels [iJump] = sl.GetILLabel (ec); iKey++; } else switch_labels [iJump] = lbl_default; } // emit the switch opcode ec.Emit (OpCodes.Switch, switch_labels); } // mark the default for this block if (iBlock != 0) ec.MarkLabel (lbl_default); } // TODO: find the default case and emit it here, // to prevent having to do the following jump. // make sure to mark other labels in the default section // the last default just goes to the end if (element_keys.Length > 0) ec.Emit (OpCodes.Br, lbl_default); // now emit the code for the sections bool found_default = false; foreach (SwitchSection ss in Sections) { foreach (SwitchLabel sl in ss.Labels) { if (sl.Converted == SwitchLabel.NullStringCase) { ec.MarkLabel (null_target); } else if (sl.Label == null) { ec.MarkLabel (lbl_default); found_default = true; if (!has_null_case) ec.MarkLabel (null_target); } ec.MarkLabel (sl.GetILLabel (ec)); ec.MarkLabel (sl.GetILLabelCode (ec)); } ss.Block.Emit (ec); } if (!found_default) { ec.MarkLabel (lbl_default); if (!has_null_case) { ec.MarkLabel (null_target); } } ec.MarkLabel (lbl_end); }
protected override void DoEmit (EmitContext ec) { Label label_init = ec.DefineLabel (); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldflda, host.PC.Spec); ec.EmitInt ((int) Iterator.State.Start); ec.EmitInt ((int) Iterator.State.Uninitialized); var m = ec.Module.PredefinedMembers.InterlockedCompareExchange.Resolve (loc); if (m != null) ec.Emit (OpCodes.Call, m); ec.EmitInt ((int) Iterator.State.Uninitialized); ec.Emit (OpCodes.Bne_Un_S, label_init); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ret); ec.MarkLabel (label_init); new_storey.Emit (ec); ec.Emit (OpCodes.Ret); }
// // Called back from Yield // public void MarkYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) { // Store the new current ec.Emit (OpCodes.Ldarg_0); expr.Emit (ec); ec.Emit (OpCodes.Stfld, IteratorHost.CurrentField.Spec); // // Guard against being disposed meantime // Label disposed = ec.DefineLabel (); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.DisposingField.Spec); ec.Emit (OpCodes.Brtrue_S, disposed); // // store resume program-counter // ec.Emit (OpCodes.Ldarg_0); ec.EmitInt (resume_pc); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); ec.MarkLabel (disposed); // mark finally blocks as disabled if (unwind_protect && skip_finally != null) { ec.EmitInt (1); ec.Emit (OpCodes.Stloc, skip_finally); } // Return ok ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); ec.MarkLabel (resume_point); }
public void EmitDispose(EmitContext ec) { if (resume_points == null) { return; } Label end = ec.DefineLabel(); Label[] labels = null; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = 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(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); } ec.EmitThis(); ec.EmitInt(1); ec.Emit(OpCodes.Stfld, ((IteratorStorey)storey).DisposingField.Spec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); if (labels != null) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); foreach (ResumableStatement s in resume_points) { s.EmitForDispose(ec, current_pc, end, true); } } ec.MarkLabel(end); }
internal void EmitValueChangedCallback (EmitContext ec, string name, TypeSpec type, Location loc) { if (listener_id == null) listener_id = ListenerProxy.Register (ModificationListener); if (listener_proxy_value == null) listener_proxy_value = typeof (ListenerProxy).GetMethod ("ValueChanged"); #if STATIC throw new NotSupportedException (); #else // object value, int row, int col, string name, int listenerId if (type.IsStructOrEnum) ec.Emit (OpCodes.Box, type); ec.EmitInt (loc.Row); ec.EmitInt (loc.Column); ec.Emit (OpCodes.Ldstr, name); ec.EmitInt (listener_id.Value); ec.Emit (OpCodes.Call, listener_proxy_value); #endif }
public override void Emit(EmitContext ec) { // // Load Iterator storey instance // method.Storey.Instance.Emit (ec); // // Initialize iterator PC when it's unitialized // if (IsEnumerable) { ec.Emit (OpCodes.Dup); ec.EmitInt ((int)State.Uninitialized); var field = IteratorHost.PC.Spec; if (Storey.MemberName.IsGeneric) { field = MemberCache.GetMember (Storey.Instance.Type, field); } ec.Emit (OpCodes.Stfld, field); } }
public override void Emit (EmitContext ec) { ec.EmitInt (unchecked ((int) Value)); }
public void EmitDispose(EmitContext ec) { Label end = ec.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); ec.Emit (OpCodes.Ldarg_0); ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec); ec.Emit (OpCodes.Stloc, current_pc); } ec.Emit (OpCodes.Ldarg_0); ec.EmitInt ((int) State.After); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); if (labels != null) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit (OpCodes.Ldloc, current_pc); ec.Emit (OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); foreach (ResumableStatement s in resume_points) s.EmitForDispose (ec, this, end, true); } ec.MarkLabel (end); }
public override void Emit (EmitContext ec) { // // Emits null pointer // ec.EmitInt (0); ec.Emit (OpCodes.Conv_U); }
// // Called back from Yield // public void MarkYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) { // Store the new current ec.Emit (OpCodes.Ldarg_0); expr.Emit (ec); ec.Emit (OpCodes.Stfld, IteratorHost.CurrentField.Spec); // store resume program-counter ec.Emit (OpCodes.Ldarg_0); ec.EmitInt (resume_pc); ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec); // mark finally blocks as disabled if (unwind_protect && skip_finally != null) { ec.EmitInt (1); ec.Emit (OpCodes.Stloc, skip_finally); } // Return ok ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); ec.MarkLabel (resume_point); }
public override void Emit (EmitContext ec) { ec.EmitInt (Value); }
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); }