public void EmitCatchBlock(EmitContext ec) { 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)Storey).EmitSetException(ec, new LocalVariableReference(catch_value, Location)); ec.Emit(OpCodes.Leave, move_next_ok); ec.EndExceptionBlock(); }
protected override void DoEmit (EmitContext ec) { if (IsGeneral) ec.BeginCatchBlock (TypeManager.object_type); else ec.BeginCatchBlock (CatchType); if (li != null) { li.CreateBuilder (ec); // // Special case hoisted catch variable, we have to use a temporary variable // to pass via anonymous storey initialization with the value still on top // of the stack // if (li.HoistedVariant != null) { LocalTemporary lt = new LocalTemporary (li.Type); SymbolWriter.OpenCompilerGeneratedBlock (ec); lt.Store (ec); SymbolWriter.CloseCompilerGeneratedBlock (ec); // switch to assigning from the temporary variable and not from top of the stack assign.UpdateSource (lt); } } else { SymbolWriter.OpenCompilerGeneratedBlock (ec); ec.Emit (OpCodes.Pop); SymbolWriter.CloseCompilerGeneratedBlock (ec); } Block.Emit (ec); }
protected override void DoEmit (EmitContext ec) { if (CatchType != null) ec.BeginCatchBlock (CatchType); else ec.BeginCatchBlock (TypeManager.object_type); if (VarBlock != null) VarBlock.Emit (ec); if (Name != null) { // TODO: Move to resolve LocalVariableReference lvr = new LocalVariableReference (Block, Name, loc); lvr.Resolve (new ResolveContext (ec.MemberContext)); // Only to make verifier happy if (TypeManager.IsGenericParameter (lvr.Type)) ec.Emit (OpCodes.Unbox_Any, lvr.Type); Expression source; if (lvr.IsHoisted) { LocalTemporary lt = new LocalTemporary (lvr.Type); lt.Store (ec); source = lt; } else { // Variable is at the top of the stack source = EmptyExpression.Null; } lvr.EmitAssign (ec, source, false, false); } else ec.Emit (OpCodes.Pop); Block.Emit (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]); 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); } }