/// <summary> /// Begins a finally block on the given exception block. /// /// Only one finally block can be defined per exception block, and the block cannot appear within a catch block. /// /// The given exception block must still be open. /// </summary> public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry) { if (forTry == null) { throw new ArgumentNullException("forTry"); } if (((IOwned)forTry).Owner != this) { FailOwnership(forTry); } var tryBlock = TryBlocks[forTry]; if (tryBlock.Item2 != -1) { throw new InvalidOperationException("BeginFinallyBlock expects an unclosed exception block, but " + forTry + " is already closed"); } if (CurrentExceptionBlock.Count > 0 && forTry != CurrentExceptionBlock.Peek()) { throw new InvalidOperationException("Cannot begin FinallyBlock on " + forTry + " while inner ExceptionBlock " + CurrentExceptionBlock.Peek() + " is still open"); } if (FinallyBlocks.Any(kv => kv.Key.ExceptionBlock == forTry)) { throw new InvalidOperationException("There can only be one finally block per ExceptionBlock, and one is already defined for " + forTry); } if (MustMark) { MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel"))); } UpdateState(Wrap(new[] { new StackTransition(0) }, "BeginFinallyBlock")); var ret = new FinallyBlock(forTry); IL.BeginFinallyBlock(); FinallyBlocks[ret] = SigilTuple.Create(IL.Index, -1); return(ret); }
void EmitUsing(LocalBuilder local, System.Action body) { var endFinally = IL.DefineLabel(); IL.BeginExceptionBlock(); body(); IL.BeginFinallyBlock(); IL.Emit(OpCodes.Ldloc, local); IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Beq, endFinally); IL.Emit(OpCodes.Ldloc, local); IL.Emit(OpCodes.Callvirt, typeof(IDisposable).GetMethod("Dispose")); IL.MarkLabel(endFinally); IL.EndExceptionBlock(); }
private void EmitTryExpression(Expression expr) { var node = (TryExpression)expr; CheckTry(); //****************************************************************** // 1. ENTERING TRY //****************************************************************** PushLabelBlock(LabelScopeKind.Try); IL.BeginExceptionBlock(); //****************************************************************** // 2. Emit the try statement body //****************************************************************** EmitExpression(node.Body); var tryType = node.Type; LocalBuilder value = null; if (tryType != typeof(void)) { //store the value of the try body value = GetLocal(tryType); IL.Emit(OpCodes.Stloc, value); } //****************************************************************** // 3. Emit the catch blocks //****************************************************************** foreach (var cb in node.Handlers) { PushLabelBlock(LabelScopeKind.Catch); // Begin the strongly typed exception block if (cb.Filter == null) { IL.BeginCatchBlock(cb.Test); } else { IL.BeginExceptFilterBlock(); } EnterScope(cb); EmitCatchStart(cb); // // Emit the catch block body // EmitExpression(cb.Body); if (tryType != typeof(void)) { //store the value of the catch block body // ReSharper disable once AssignNullToNotNullAttribute IL.Emit(OpCodes.Stloc, value); } ExitScope(cb); PopLabelBlock(LabelScopeKind.Catch); } //****************************************************************** // 4. Emit the finally block //****************************************************************** if (node.Finally != null || node.Fault != null) { PushLabelBlock(LabelScopeKind.Finally); if (node.Finally != null) { IL.BeginFinallyBlock(); } else { IL.BeginFaultBlock(); } // Emit the body EmitExpressionAsVoid(node.Finally ?? node.Fault); IL.EndExceptionBlock(); PopLabelBlock(LabelScopeKind.Finally); } else { IL.EndExceptionBlock(); } if (tryType != typeof(void)) { // ReSharper disable once AssignNullToNotNullAttribute IL.Emit(OpCodes.Ldloc, value); FreeLocal(value); } PopLabelBlock(LabelScopeKind.Try); }
private void EmitTryExpression(Expression expr) { var node = (TryExpression)expr; CheckTry(_labelBlock); //****************************************************************** // 1. ENTERING TRY //****************************************************************** var parent = _labelBlock; _labelBlock = new LabelScopeInfo(parent, LabelScopeKind.Try); IL.BeginExceptionBlock(); //****************************************************************** // 2. Emit the try statement body //****************************************************************** EmitExpression(node.Body); var tryType = node.Type; LocalBuilder?value = null; if (tryType != typeof(void)) { //store the value of the try body value = GetLocal(tryType); IL.Emit(OpCodes.Stloc, value); } //****************************************************************** // 3. Emit the catch blocks //****************************************************************** foreach (var cb in node.Handlers) { var tmpParent = _labelBlock; _labelBlock = new LabelScopeInfo(tmpParent, LabelScopeKind.Catch); // Begin the strongly typed exception block if (cb.Filter == null) { IL.BeginCatchBlock(cb.Test); } else { IL.BeginExceptFilterBlock(); } var innerScopeInfo = GetInnerScope(node, _scope); if (innerScopeInfo.HasValue) { _scope = innerScopeInfo.Value.child.Enter(this, innerScopeInfo.Value.parent); } EmitCatchStart(cb); // // Emit the catch block body // EmitExpression(cb.Body); if (tryType != typeof(void)) { //store the value of the catch block body // ReSharper disable once AssignNullToNotNullAttribute IL.Emit(OpCodes.Stloc, value); } if (innerScopeInfo.HasValue) { innerScopeInfo.Value.child.Exit(); _scope = innerScopeInfo.Value.parent; } _labelBlock = tmpParent; } //****************************************************************** // 4. Emit the finally block //****************************************************************** if (node.Finally != null || node.Fault != null) { var tmpParent = _labelBlock; _labelBlock = new LabelScopeInfo(tmpParent, LabelScopeKind.Finally); if (node.Finally != null) { IL.BeginFinallyBlock(); } else { IL.BeginFaultBlock(); } // Emit the body EmitExpressionAsVoid(node.Finally ?? node.Fault !); IL.EndExceptionBlock(); _labelBlock = tmpParent; } else { IL.EndExceptionBlock(); } if (value != null) { // ReSharper disable once AssignNullToNotNullAttribute IL.Emit(OpCodes.Ldloc, value); FreeLocal(value); } _labelBlock = parent; }