Пример #1
0
        /// <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);
        }
Пример #2
0
        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();
        }
Пример #3
0
        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;
        }