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 = 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.Emit(OpCodes.Ldarg_0); ec.Emit(OpCodes.Ldfld, IteratorHost.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); } ec.Emit(OpCodes.Ldarg_0); ec.EmitInt(1); ec.Emit(OpCodes.Stfld, IteratorHost.DisposingField.Spec); 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 int AddResumePoint(ResumableStatement stmt) { if (resume_points == null) { resume_points = new ArrayList(); } resume_points.Add(stmt); return(resume_points.Count); }
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); }
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]); BodyEnd = ec.DefineLabel(); block.EmitEmbedded(ec); ec.MarkLabel(BodyEnd); if (async_init != null) { async_init.EmitCatchBlock(ec); } 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); } }
public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { int errors = Report.Errors; Parent.AddResumePoint (stmt, this.stmt, out pc); if (errors == Report.Errors) { if (finally_vector == null) this.stmt.AddResumePoint (current, pc); else { if (stmt is AwaitStatement) { Report.Error (1984, stmt.loc, "The `await' operator cannot be used in the body of a finally clause"); } else { Report.Error (1625, stmt.loc, "Cannot yield in the body of a finally clause"); } } } return true; }
/* public override bool CheckRethrow (Location loc) { return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); } */ public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { pc = async_init.AddResumePoint (current); return true; }
public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { int errors = Report.Errors; Parent.AddResumePoint (stmt, tc.IsTryCatchFinally ? current : tc, out pc); if (errors == Report.Errors) { if (stmt is AwaitStatement) { if (CurrentUsageVector.Next != null) { Report.Error (1985, stmt.loc, "The `await' operator cannot be used in the body of a catch clause"); } else { this.tc.AddResumePoint (current, pc); } } else { if (CurrentUsageVector.Next == null) Report.Error (1626, stmt.loc, "Cannot yield a value in the body of a try block with a catch clause"); else Report.Error (1631, stmt.loc, "Cannot yield a value in the body of a catch clause"); } } return true; }
public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { throw new InternalErrorException ("A yield in a non-iterator block"); }
public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { pc = iterator.AddResumePoint (current); return false; }
public virtual bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc) { return Parent.AddResumePoint (stmt, current, out pc); }
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); }
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); }